Jump to content

Push notifications not going through to client


noket
Go to solution Solved by hthgihwaymonk,

Recommended Posts

Hello!

I've been tinkering away at this the last four hours - I finally got through everything required.

I get an X-Emby-Token from the user, in this case Tom

I get Tom's session, and device details from that session.

Then, I try to POST - python generates the following data:

url: http://192.168.0.xxx:xxx/emby/Sessions/[session id]/Message?Id=[session id]&Text=What+a+message&Header=Wowza
body: Username=Tom&Pw=
header: {'User-Agent': 'python-requests/2.22.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'X-Emby-Token': '["AccessToken" from auth as user]', 'Content-Length': '16', 'Content-Type': 'application/x-www-form-urlencoded'}

<Response [204]>
b''
No Content

Unfortunately - I'm not getting the notification on the device.

These are the logs - I turned off authentication on localhost, since I couldn't auth as a user via API key when password or passcode was required on localhost.

Looks like there's an auth issue, but an access token is definitely being returned:

2023-10-26 00:58:20.493 Info Server: http/1.1 POST http://URL/emby/Users/[user-id-with-dashes]/Authenticate. Accept=*/*, Connection=keep-alive, Host=URL, User-Agent=python-requests/2.22.0, Accept-Encoding=gzip, deflate, Content-Type=application/x-www-form-urlencoded, Content-Length=3, X-Emby-Token=[token]
2023-10-26 00:58:20.494 Error UserManager: Error authenticating with provider Default
*** Error Report ***
Version: 4.7.14.0
Command line: /opt/emby-server/system/EmbyServer.dll -programdata /var/lib/emby -ffdetect /opt/emby-server/bin/ffdetect -ffmpeg /opt/emby-server/bin/ffmpeg -ffprobe /opt/emby-server/bin/ffprobe -restartexitcode 3 -updatepackage emby-server-deb_{version}_amd64.deb
Operating system: Linux version 5.15.0-86-generic (buildd@lcy02-amd64-062) (gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #96~20.04.
Framework: .NET 6.0.20
OS/Process: x64/x64
Runtime: opt/emby-server/system/System.Private.CoreLib.dll
Processor count: 8
Data path: /var/lib/emby
Application path: /opt/emby-server/system
System.Exception: System.Exception: Invalid username or password..
at Emby.Server.Implementations.Library.DefaultAuthenticationProvider.Authenticate(String username, String password, User resolvedUser)
at Emby.Server.Implementations.Library.UserManager.AuthenticateWithProvider(IAuthenticationProvider provider, String username, String password, User resolvedUser, CancellationToken cancellationToken)
Source: Emby.Server.Implementations
TargetSite: System.Threading.Tasks.Task`1[MediaBrowser.Controller.Authentication.ProviderAuthenticationResult] Authenticate(System.String, System.String, MediaBrowser.Controller.Entities.User)
2023-10-26 00:58:20.494 Info UserManager: Authentication request for Tom has succeeded.
2023-10-26 00:58:20.494 Info SessionManager: Reissuing access token: [token]
2023-10-26 00:58:20.494 Info Server: http/1.1 Response 200 to URL. Time: 1ms. http://URL/emby/Users/[user-id-with-dashes]/Authenticate
2023-10-26 00:58:20.501 Info Server: http/1.1 POST http://URL/emby/Sessions/[sessionidnodashes]/Message?Id=[sessionidnodashes]&Text=What+a+message&Header=Wowza. UserAgent: python-requests/2.22.0
2023-10-26 00:58:20.502 Info Server: http/1.1 Response 204 to URL. Time: 0ms. http://URL/emby/Sessions/[sessionidnodashes]/Message?Id=[sessionidnodashes]&Text=What+a+message&Header=Wowza
2023-10-26 00:58:24.617 Info Server: http/1.1 POST http://host1/emby/Sessions/Capabilities/Full?X-Emby-Client=Emby Web&X-Emby-Device-Name=Brave Windows&X-Emby-Device-Id=[device-id-with-dashes]&X-Emby-Client-Version=4.7.14.0&X-Emby-Language=en-us&reqformat=json. UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36

I appreciate any help you can give - I'm stumped.

Edited by noket
Link to comment
Share on other sites

hthgihwaymonk
11 hours ago, noket said:

I get an X-Emby-Token from the user, in this case Tom

I use the server API KEY not the user 
and this works for me
 

url = f"{emby_url}/Sessions/{session_id}/Message?Text=These are not the droids you are looking for&Header=Greetings&api_key={emby_api_key}"
requests.post(url)

 

  • Thanks 1
Link to comment
Share on other sites

Oddly, still not working. Getting 204, passed all the same data as params just like you, but no pop up. The API key is one you generated in the admin API settings, right? Next to the DLNA api key?

What method are you using to get the users session (including params, headers, body, etc)? 

I figure if I ensure I'm getting session the same exact way as you, then it's either an issue with app versioning or networking

If it's not the session id, I wonder if it has something to do with upgrading the connection (nginx is set to upgrade insecure). I don't have it setup via reverse proxy, just subdomain. But still, that shouldn't affect local traffic unless emby is bouncing traffic externally for some reason.

Edited by noket
Link to comment
Share on other sites

  • Solution
hthgihwaymonk

I sure there's more than one way to get the Session ID,
But I use -
 

def get_sessions(emby_api_key):
    url = f"{emby_url}/Sessions?api_key={emby_api_key}"
    response = requests.get(url)
    return response.json()

sessions = get_sessions(emby_api_key)
for session in sessions:
    DeviceId = session.get("DeviceId")
    DeviceName = session.get("DeviceName")
    ClientName = session.get("Client")
    RemoteEndPoint = session.get("RemoteEndPoint")
    SessionId = session.get("Id")
    UserName = session.get("UserName")

You'll need to add some kind of if statement to just get the ID you are looking for, based on deviceId or useranme, or whatever

Also, in case you were unaware -
There are quite a few emby clients/devices that do not support having messages sent to their screen.
So I would test using a browser as the client can accepts messages and you'll be able to make sure it's not just the client refusing to show the message

Edited by hthgihwaymonk
Link to comment
Share on other sites

I got it working .. but also didn't.

I think it's an issue with the session persisting between/after API calls.

Basically, I set up monk's code (or at least, what I could extrapolate from it), then started watching a video at emby.mydomain.null .. when I triggered the code, the code didn't work.

Thinking it might be an issue with the reverse-proxy, I then started watching the video via my subnet at 192.168.xxx.xxx:xxxxx .. when I triggered the code, this time around, the code worked. The lil button popped up with my message no matter how many times I pressed it.

I went back to emby.mydomain.null to confirm it was the issue .. triggering the code didn't work.

Then, I went back to my subnet, happy to have fixed it .. and ran the code. It didn't work.

So .. if you'd be willing to answer this @Luke.. would an improperly ended (or not ended at all) session cause future API calls to fail in the way I've seen?

And - for the /Session/Logout API call, is it right that the x-emby-token goes in the header, the admin api key goes in the params, and the username goes in the data (if something should be added or omitted, please let me know). I'm getting burned out trying to piece this all together lol

Link to comment
Share on other sites

bakes82

You can literally test this from the swagger UI,  call the get seesions, copy the id, then goto the message endpoint type in your info, press execute.

I run my setup behind a reverse proxy, there 0 issues.

image.png.c09caa4ceb4367c6ebe45d77ba5edfb5.png

image.png.b561cd8bb829eccfffc0439e9b0b96d4.png

Link to comment
Share on other sites

Thank you for your input bakes, but that isn't really helpful in determining what the root cause is - especially considering how my last post was about how it likely isn't the proxy that's the issue.

Part of troubleshooting is narrowing down possibilities - that's all I'm trying to do.

So - if anyone has knowledge about whether a session needs to be ended before other api calls are made, or whether session issues might be causing the problem, that would helpful.

Link to comment
Share on other sites

Yes.

Swagger =/= Python.. And even if it did work, that doesn't solve the problem, because:

I've passed variables exactly as the Swagger documentation has indicated. It should work. It's not. I've followed everything according to the github docs.

Again - the code worked briefly on my subnet after a day via 192.168.x.x. I navigated away from the page, then back, to confirm it was persistently fixed - and the unchanged code stopped pushing the notifications. I cleared my browser cache/cookies and restarted the browser. Code still isn't working. It's reasonable to suspect session errors in this case.

Quote

And - for the /Session/Logout API call, is it right that the x-emby-token goes in the header, the admin api key goes in the params, and the username goes in the data?

I appreciate your help Luke and Monk so far, it's honestly been great and helpful and I appreciate your time and effort .. but Swagger is what I've been leaning on so far and it hasn't been helpful to troubleshoot. I've made more progress solving this with the comments here versus the Swagger and github docs

Link to comment
Share on other sites

What session did you send it to? Did you look through the session data first for that session to see what commands it supports receiving?

Link to comment
Share on other sites

hthgihwaymonk
51 minutes ago, Luke said:

What session did you send it to? Did you look through the session data first for that session to see what commands it supports receiving?

beyond what is listed under "SupportedCommands", does "SupportsRemoteControl" need to be true as well ?
Or does "DisplayMessage" not need "SupportsRemoteControl" to be TRUE to work ?

Link to comment
Share on other sites

hthgihwaymonk
40 minutes ago, Luke said:

Yes it needs to be true.

One more followup - 
In the list of "SupportedCommands", which one will indicate if the ability to stop playback is available during a particular session ?
I'd like to know before attempting to use `/Sessions/{session_id}/Playing/Stop` is it will work

Link to comment
Share on other sites

3 hours ago, hthgihwaymonk said:

One more followup - 
In the list of "SupportedCommands", which one will indicate if the ability to stop playback is available during a particular session ?
I'd like to know before attempting to use `/Sessions/{session_id}/Playing/Stop` is it will work

That is supported as long as it supports remote control.

Link to comment
Share on other sites

bakes82
17 hours ago, noket said:

Swagger =/= Python.. And even if it did work, that doesn't solve the problem, because:

That would be false since we can’t see your code.  Also if you are testing via web and multi tabs I believe all tabs share the same sessionid and thus it could be randomly appearing on any of the tabs.  It’s been a while so don’t quote me on that, but I recall that happening.  You also said you navigated away did you get a new session? 

Link to comment
Share on other sites

bakes82
13 hours ago, hthgihwaymonk said:

Sessions/{session_id}/Playing/Stop` is it will work

Let me know if it works on rokus. I think luke said they don’t support remote commands, but I don’t have one to test with.

Link to comment
Share on other sites

hthgihwaymonk
19 minutes ago, bakes82 said:

Let me know if it works on rokus. I think luke said they don’t support remote commands, but I don’t have one to test with.

It doesn't seem to work on rokus, even when "SupportsRemoteControl" is true.
And yeah, I've seen that comment as well from Luke :)
It doesn't seem to send messages to them either.
But I don't have a roku either.

.
For those (Rokus and some smart tvs) I've been trying toggling "IsDisabled", for that account, on and off as well as deleting the "Device".
That seems to work to brute force stopping the stream

Edited by hthgihwaymonk
Link to comment
Share on other sites

6 hours ago, bakes82 said:

That would be false since we can’t see your code.  Also if you are testing via web and multi tabs I believe all tabs share the same sessionid and thus it could be randomly appearing on any of the tabs.  It’s been a while so don’t quote me on that, but I recall that happening.  You also said you navigated away did you get a new session? 

To bakes:

https://media.tenor.com/b1gMxd9bNn8AAAAC/oh-no-stressed.gif

To luke: fair point.. It doesn't hurt to validate I'm using the right arguments. I'll have it spit the json results of each sequential command/function into a file and get back to you on this later today. I'll also include relevant code to show breadcrumbs/process. Thanks again

Link to comment
Share on other sites

bakes82
8 hours ago, hthgihwaymonk said:

For those (Rokus and some smart tvs) I've been trying toggling "IsDisabled", for that account, on and off as well as deleting the "Device".
That seems to work to brute force stopping the stream

Interesting, if you delete the device though it still uses a slot and if you "limit" devices per user it not adds extra work to renable that device for the user,  too bad plex figured this out years ago as basic functionality, not sure why emby thinks not being able to kill a stream isnt basic/priority.  Nothing like a rogue stream taking causing performance issues for everyone and the only way to fix is to restart emby.  @Lukeis the ability to kill a stream something that is on the list and can be added in the future, ie "coming soon" maybe in 10 years, or should we be expected to restart the box as a solution?

@hthgihwaymonkI havent tried this but I know one "automatic" solution for plex was to monitor the system processes for ffmpeg and then certain conditions but this was more of a general kill hevc type process

Link to comment
Share on other sites

hthgihwaymonk
1 hour ago, bakes82 said:

Interesting, if you delete the device though it still uses a slot and if you "limit" devices per user it not adds extra work to renable that device for the user,  too bad plex figured this out years ago as basic functionality, not sure why emby thinks not being able to kill a stream isnt basic/priority.  Nothing like a rogue stream taking causing performance issues for everyone and the only way to fix is to restart emby.  @Lukeis the ability to kill a stream something that is on the list and can be added in the future, ie "coming soon" maybe in 10 years, or should we be expected to restart the box as a solution?

@hthgihwaymonkI havent tried this but I know one "automatic" solution for plex was to monitor the system processes for ffmpeg and then certain conditions but this was more of a general kill hevc type process

I tried killing the ffmpeg process too
It does work, but for the roku -
it has to be killed multiple times before the roku gives up.

toggling `IsDisabled` seems to work better for me

Link to comment
Share on other sites

Following back up to give closure - I found the issue .. it was kind of  right: The problem was there were many old sessions that had been lingering. In my code, I was finding the first session for a user and assuming it was their only session, when in fact there could be sessions sticking around from days ago.

user session 1
current time: 2023-11-04 03:50:16.458331+00:00
session last activity: 2023-11-04 03:50:16.237826+00:00
difference: 0:00:00.220505

user session 2
current time: 2023-11-04 03:50:16.458563+00:00
session last activity: session last activity: 2023-11-04 00:22:56.317559+00:00
difference: 3:27:20.141004

user session 3
current time: 2023-11-04 03:50:16.458770+00:00
session last activity: 2023-10-30 22:24:55.406477+00:00
difference: 4 days, 5:25:21.052293

user session 4
current time: 2023-11-04 03:50:16.458954+00:00
session last activity: 2023-10-27 02:33:50.094616+00:00
difference: 8 days, 1:16:26.364338

user session 5
current time: 2023-11-04 03:50:16.459136+00:00
session last activity: 2023-10-27 01:32:03.346762+00:00
difference: 8 days, 2:18:13.112374

user session 6
current time: 2023-11-04 03:50:16.459315+00:00
session last activity: 2023-10-27 01:30:24.209836+00:00
difference: 8 days, 2:19:52.249479

In case this helps people in the future - below is code that compares the current UTC time to the time of the last session activity, and pushes a notification to that user for any sessions that are active. The code is still a sloppy .. I need to clean it up. But .. it works.

This also gives a good example of how to authenticate as a user (you have to have require local network passwords disabled in admin settings for it to work) and use that access token to do work in a user context

Much thanks for all your support Luke and Monk

from datetime import datetime, timezone
import requests #https://pypi.org/project/requests/
from dateutil.parser import parse as timeparse

static_api_key = ""
static_dict_x_emby_token = {"X-Emby-Token":static_api_key}

emby_base_url = "http://127.0.0.1:1234/emby/"

def push_message(username:str,header:str,message:str,delay_secs:int=None):

    predata = {"Pw":""}
    user_sessions = []

    #get all session
    sessions = requests.get(
        url=emby_base_url+"Sessions",
        headers=static_dict_x_emby_token
        ).json()
    
    #find any sessions for the user that were active within the last 5 seconds. Store the sessions in user_sessions
    for var in sessions:
        if var.get("UserName") is not None and var.get("UserId") is not None:
            if username == var.get("UserName"):
                activity_time = timeparse(timestr=var["LastActivityDate"],yearfirst=True)
                current_time = datetime.now(timezone.utc)
                time_difference = current_time-activity_time
                if time_difference.seconds < 5:
                    user_sessions.append(var)
                    
    #iterate through user_sessions and push the message to each session
    for session in user_sessions:
        user_authentication = requests.post(
            url=emby_base_url+"Users/"+session["UserId"]+"/Authenticate",
            headers=static_dict_x_emby_token,
            data=predata
            ).json()
        
        #provide the user's access token    
        message_header = {"X-Emby-Token":user_authentication["AccessToken"]}
        
        requests.post(
            url=emby_base_url+"Sessions/"+session["Id"]+"/Message",
            headers=message_header,
            params={
                "Id":session["Id"],
                "Text":message,
                "Header":header,
                "TimeoutMs":delay_secs*1000
            }
        )

 

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...