Jump to content

Detect if user is logged into emby server via HTTP request.


Recommended Posts

Posted

I'm using Autohotkey to automate my HTPC and would like to know if there is a way to detect if a user is logged into emby server and/or currently streaming video/tv? Possibly with a simple HTTP request?

 

Thanks, Nic.

Posted (edited)

Hi Luke,

 

I tried using:

http://127.0.0.1:8096/emby/Sessions

It returned Access token is required?

 

I need an access token? Where do I get this and how do I include it in the http request above?

 

Looks like once this is working 'Sessions' will include 'NowViewingItem' and 'PlayState' which should be enough data for what im after.

 

Thanks, Nic.

Edited by niczoom
Posted

Hi, you're going to have to start at the beginning of the wiki and learn how to use the api, and that includes going through the authentication section. Please let us know if this helps. Thanks.

Posted

Its beginning to look like more work than I expected.

 

I've read through the wiki here https://github.com/MediaBrowser/Emby/wiki/Authentication but with no examples I was still in the dark. I then stumbled on a post here which I believe is what I need to do, although it's in PHP I could translate into Autohotkey.

 

Is all this coding needed to perform what I need?

 

My Autohotkey script will be running locally on the PC which Emby Server is running on so why do I need all this authentication code with a returned X-MediaBrowser-Token just to get the data returned from a call to /Sessions?

 

Is their no simple 1 liner with a username and password to get what I need?

 

Thanks, Nic.

Posted

Is all this coding needed to perform what I need?

 

Yes, because if it wasn't required, then there'd be no security and that would create it's own set of problems.

Posted (edited)

Ok, I have a valid token returned! Now when I try to access http://127.0.0.1:8096/emby/Users/Sessions using the new token in a header http.SetRequestHeader("X-MediaBrowser-Token", accessToken), I get the following response:

 

Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

 

In my 'Authorization Request Header' as per github, I'm using UserID="515753215976426ca68b47dd986f36b2", Ive also tried using Guid="51575321-5976-426c-a68b-47dd986f36b2" with the same result.

 

My whole Authorization header is:

MediaBrowser Client="PC", Device="LoungePC", DeviceId="1", Version="1", UserID="515753215976426ca68b47dd986f36b2"

 

The code:

http.Open("POST", "http://127.0.0.1:8096/emby/Users/Sessions", true)
http.SetRequestHeader("Content-Type", "application/json")
http.SetRequestHeader("Authorization", authString)
http.SetRequestHeader("X-MediaBrowser-Token", accessToken)
http.Send(data)
http.WaitForResponse()
response := http.ResponseText 

Any ideas?

 

Thanks, Nic.

Edited by niczoom
Posted (edited)

Ok, got it working, had the wrong HTTP address, and also removed the 'data' variable from the http.send command (contains the passwords from the previous AuthenticateByName request).

 

The following works for me and returns the current session:

http.Open("POST", "http://127.0.0.1:8096/emby/Sessions", true)
http.SetRequestHeader("Content-Type", "application/json")
http.SetRequestHeader("Authorization", authString)
http.SetRequestHeader("X-MediaBrowser-Token", accessToken)
http.Send()
http.WaitForResponse() ; Using 'true' above and this call allows the script to remain responsive.
response := http.ResponseText

Using AutoHotkey BTW.

Edited by niczoom
Posted (edited)

Why are you requesting /Users/Sessions? I don't see that documented. Think you want /Sessions.

 

Edit: You beat me to it

Edited by xyz
Posted

I have my code looping through users in the current session. When I return 'LastActivityDate' it has never changed from when I started testing, at the moment it shows activity from like 6 hours ago, but I've logged in/out and played a few different movies in between time but the date/time in LastActivityDate does not change?

 

Any ideas why?

 

When logging into the dashboard (http://localhost:8096/web/dashboard.html) under Active Devices  it shows all current active devices with correct times, as in 'Last seen X minutes ago'. Where does it get this info from?

 

Cheers Nic.

Posted

the session object has a LastActivityDate as well.

Posted (edited)

the session object has a LastActivityDate as well.

What do you mean Luke?

 

I made a call to 'http.Open("GET", "http://127.0.0.1:8096/emby/Sessions",true)' and it returns (im assuming) a session object. Ive written some code to loop through this 'session data' and extract some data for each user including the ' LastActivityDate'.

 

As I mentioned above the 'LastActivityDate' does not seem to update with the users latest activity. For example I just pulled out my phone now 2018-01-05T06:08:00 and logged into emby through the android app and check the sessions 'LastActivityDate' and it reported 2018-01-04T19:37:23, which is last night?

 

If I then log into the dashboard (http://localhost:809.../dashboard.html) under Active Devices it shows my android phone 'SMG930F Emby for Android Mobile 2.9.76, Last seen 5 minutes ago'.

 

Any ideas why the LastActivityDate is not current? And where does the dashboard gets its data from?

 

Thanks, Nic.

Edited by niczoom
Posted

That endpoint gives you a list of sessions, and each session has a LastActivityDate property attached to it. That is what the dashboard is using.

Posted (edited)

Ok, I've only just noticed that the 'LastActivityDate' does not seem to be set to the device that its used on, its behind by 630 minutes.

 

For example when I got up this morning the 'LastActivityDate' was set to:

 

06:07:26.255 Fri, 05 Jan 2018 :: LastActivityDate: 2018-01-04T19:37:26.2236542Z

 

Now ive just returned home and checked the 'LastActivityDate' again and it was:

 

07:39:39.346 Fri, 05 Jan 2018 :: LastActivityDate: 2018-01-04T21:09:39.3119501Z

 

As you can see, my log shows the actual date/time on the left. Why is the 'LastActivityDate' returned from emby 630 minutes behind the actual date/time?

 

Thanks, Nic.

Edited by niczoom
Posted

I now figured out that whatever time emby uses for the LastActivityDate parameter its 630 minutes behind the actual time on my PC where emby is running. So I'll work with that offset.

 

Is emby hardcoded to use a particular date/time for the LastActivityDate parameter? If so why can't it just use my PCs current date/time where it's running on?

Posted

 

 

2018-01-04T21:09:39.3119501Z

 

UTC

Posted (edited)

Got it sorted now. I'll post my code below in case anyone is interested, it's using AutoHotkey.

EMBY_State(z:=0) {
	debug := 0
	log_global ? debug ? log(tab(z) A_ThisFunc "()")
	returnString := ""
	
	authString = MediaBrowser Client="PC", Device="LoungePC", DeviceId="1", Version="1", UserID="515753215976426ca68b47dd986f36b2"
	; pw - password in plain text, password - password in Sha1, passwordMd5 - password in MD5
	data = {"Username":"_YOUR_USERNAME_", "pw":"_PASSWORD_", "password":"_PASSWORD_", "passwordMd5":"_PASSWORD_"}

	; Example: Download file over http into a variable:
	http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	http.Open("POST", "http://127.0.0.1:8096/emby/Users/AuthenticateByName", true) ;http.Open("POST", "http://127.0.0.1:8096/emby/Sessions", true)
	http.SetRequestHeader("Content-Type", "application/json")
	http.SetRequestHeader("Authorization", authString)
	http.Send(data) ; Using 'true' above and this call allows the script to remain responsive.
	http.WaitForResponse()
	response := http.ResponseText
	log_global ? debug ? log(tab(z+1) "response: " response)
	
	; Check for a valid 'AccessToken'
	Try {
		accessToken := jsonGet(response,"AccessToken")
		log_global ? debug ? log(tab(z+1) "AccessToken : " accessToken)
	} catch {
		returnString := response
		return returnString
	}
	
	; Return current session data
	http.Open("GET", "http://127.0.0.1:8096/emby/Sessions", true)
	http.SetRequestHeader("Content-Type", "application/json")
	http.SetRequestHeader("Authorization", authString)
	http.SetRequestHeader("X-MediaBrowser-Token", accessToken)
	http.Send()
	http.WaitForResponse() ; Using 'true' above and this call allows the script to remain responsive.
	response := http.ResponseText
	log_global ? debug ? log(tab(z+1) "Session Data : " response)
	sessionData := jsonAHK(response)
	
	; The returned json session data can be formatted at : https://www.freeformatter.com/json-formatter.html

	; Loop through all users logged into the current session.
	; 10 is an arbitary number as I will never have 10 users connected at once.
	; 'Loop 0' (A_Index=1) is skipped as this is the authenticated user session which uses the 'AccessToken' to gain authorized access to the emby api.
	; 	-> Using the above Authorization string 'authString'
	
	OverTime := false ;Reset
	EmbyIdle := false ;Reset
	EmbyTimeOffset := 630 ;Minutes. Emby uses UTC time, this is the offset in minutes compared to my local time.
	MaxIdleEmbyUserTime := 5
		
	Loop 10
	{
		try {
			log_global ? debug ? log(tab(z+1) "Loop " A_Index)
			log_global ? debug ? log(tab(z+2) "`tUserName:" sessionData[A_Index].UserName 
											. "  Client:" sessionData[A_Index].Client
											. "  DeviceName:" sessionData[A_Index].DeviceName)
			data1 := sessionData[A_Index].LastActivityDate
			log_global ? debug ? log(tab(z+2) "`tLastActivityDate:`t`t" data1)
			StringSplit SplitDate,data1,. ; Only keep left of colon (emby date 2018-01-04T09:11:25.7169690Z)
			log_global ? debug ? log(tab(z+2) "`tSplitDate:`t`t`t`t" SplitDate1)
			CleanDate := RegExReplace(SplitDate1, "(-|:|T)")  ;Strip emby date back to AHK friendly type (2018-01-04T09:11:25.7169690Z)
			log_global ? debug ? log(tab(z+2) "`tCleanDate:`t`t`t`t" CleanDate)
			CleanDate += EmbyTimeOffset, Min ;Add offset to CleanDate
			log_global ? debug ? log(tab(z+2) "`tCleanDate+Offset:`t`t" CleanDate)
			TimeSinceLastActivity = ;Reset variable, make blank.
			TimeSinceLastActivity -= CleanDate, Min ; Time difference between 'startTime' and A_Now, using EnvSub.
			log_global ? debug ? log(tab(z+2) "`tTimeSinceLastActivity:`t" TimeSinceLastActivity " min")
			
			; If LastActivityTime > MaxIdleEmbyUserTime then set OverTime=True
			
			if(TimeSinceLastActivity >= MaxIdleEmbyUserTime)
			{
				log_global ? debug ? log(tab(z+2) "`tOverTime:`t`t`t`tTrue")
				OverTime := true
			}
			
			; Check 'NowPlayingItem' seperatly
			try
			{
				; Streaming media IS detected for current user session.
				EmbyIdle := false
				NowPlaying := sessionData[A_Index].NowPlayingItem.Name 
				log_global ? debug ? log(tab(z+2) "`tNowPlayingItem.Name:`t" NowPlaying " (EmbyIdle=False)")
				returnString := "Streaming: " NowPlaying
			}
			catch
			{
				; NO streaming media detected for current user session.
				; If OverTime=True then set EmbyIdle=True
				if(OverTime)
				{
					EmbyIdle := true
					log_global ? debug ? log(tab(z+2) "`tNo streaming detected. Max user idle time exceeded. Setting 'EmbyIdle=True'")
				}
				else
				{
					timeRemain := (MaxIdleEmbyUserTime-TimeSinceLastActivity)
					log_global ? debug ? log(tab(z+2) "`ttimeRemain:`t`t`t`t" timeRemain)
					timeRemainString := (timeRemain=1)?("< 1 minute"):(timeRemain " minutes") 
					returnString := "User logged in, no streaming detected. (" timeRemainString " until max idle time is exceeded)"
				}
			}
		}
		catch
		{
			; if no data is detected in the first loop then no users were detected therefore set EmbyIdle=True
			log_global ? debug ? log(tab(z+2) "A_Index:"A_Index)
			if(A_Index=1)
			{
				EmbyIdle := true
				break ;out of loop
			}
		}
		
	}
	
	if(EmbyIdle)
	{
		log_global ? debug ? log(tab(z+1) "EMBY IS IDLE - Allow Sleep")
		return "Idle"
	}
	else
	{
		log_global ? debug ? log(tab(z+1) "returnString="returnString)
		return returnString
	}
}

and a small function to parse JSON:
jsonAHK(s){
	; https://autohotkey.com/board/topic/95262-obj-json-obj/
	static o:=comobjcreate("scriptcontrol")
	o.language:="jscript"
	return o.eval("(" s ")")
}
Edited by niczoom

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...