Skip to content

Instantly share code, notes, and snippets.

@blacktwin
Last active January 13, 2017 05:07
Show Gist options
  • Save blacktwin/2394e5aaccfe36df5b6d320ee90b7339 to your computer and use it in GitHub Desktop.
Save blacktwin/2394e5aaccfe36df5b6d320ee90b7339 to your computer and use it in GitHub Desktop.
Limit user concurrent streams by unsharing libraries when concurrent stream count reaches limit. Restore sharing of libraries when concurrent stream is below limit.
"""
Share functions from https://gist.github.com/JonnyWong16/f8139216e2748cb367558070c1448636
Once user stream count hits LIMIT they are unshared from libraries.
Once user stream count is below LIMIT their shares are restored.
Unsharing does not pause or stop the user's stream.
After unsharing user can pause but not skip ahead or skip back.
Restrictions remain if unshared to shared while playing.
Effected user will need to refresh browser/app or restart app to reconnect.
User watch record stop when unshare is executed.
If user finishes a movie/show while unshared they will not have that record.
Run manually or cron or task
Adding to PlexPy....
PlexPy > Settings > Notification Agents > Scripts > Bell icon:
[X] Notify on playback start
[X] Notify on playback stop
PlexPy > Settings > Notification Agents > Scripts > Gear icon:
Playback Start: stream_limiter.py
Playback Stop: stream_limiter.py
If used in PlexPy:
PlexPy will continue displaying that user is watching after unshare is executed in ACTIVITY.
PlexPy will update after ~5 minutes and no longer display user's stream in ACTIVITY.
PlexPy will think that user has stopped and kick off share, if set for Playback Stop.
This is indented to restrict users to the LIMIT amount of concurrent streams.
"""
import requests
import sys
from xml.dom import minidom
## EDIT THESE SETTINGS ###
PLEXPY_APIKEY = 'XXXXXX' # Your PlexPy API key
PLEXPY_URL = 'http://localhost:8181/' # Your PlexPy URL
PLEX_TOKEN = "ENTER_YOUR_PLEX_TOKEN_HERE"
SERVER_ID = "ENTER_YOUR_SERVER_ID_HERE" # Example: https://i.imgur.com/EjaMTUk.png
# Get the User IDs and Library IDs from
# https://plex.tv/api/servers/SERVER_ID/shared_servers
# Example: https://i.imgur.com/yt26Uni.png
# Enter the User IDs and Library IDs in this format below:
# {UserID1: [LibraryID1, LibraryID2],
# UserID2: [LibraryID1, LibraryID2]}
USER_LIBRARIES = {1234567: [1234567, 1234567]}
LIMIT = 2
class Activity(object):
def __init__(self, data=None):
d = data or {}
self.rating_key = d['rating_key']
self.title = d['full_title']
self.user = d['user']
self.user_id = d['user_id']
self.video_decision = d['video_decision']
self.transcode_decision = d['transcode_decision']
self.transcode_key = d['transcode_key']
self.state = d['state']
def share(user_id):
headers = {"X-Plex-Token": PLEX_TOKEN,
"Accept": "application/json"}
url = "https://plex.tv/api/servers/" + SERVER_ID + "/shared_servers"
library_ids = USER_LIBRARIES[user_id]
payload = {"server_id": SERVER_ID,
"shared_server": {"library_section_ids": library_ids,
"invited_id": user_id}
}
r = requests.post(url, headers=headers, json=payload)
if r.status_code == 401:
print("Invalid Plex token")
return
elif r.status_code == 400:
print(r.content)
return
elif r.status_code == 200:
print("Shared libraries with user %s" % str(user_id))
return
return
def unshare(user_id):
headers = {"X-Plex-Token": PLEX_TOKEN,
"Accept": "application/json"}
url = "https://plex.tv/api/servers/" + SERVER_ID + "/shared_servers"
r = requests.get(url, headers=headers)
if r.status_code == 401:
print("Invalid Plex token")
return
elif r.status_code == 400:
print r.content
return
elif r.status_code == 200:
response_xml = minidom.parseString(r.content)
MediaContainer = response_xml.getElementsByTagName("MediaContainer")[0]
SharedServer = MediaContainer.getElementsByTagName("SharedServer")
shared_servers = {int(s.getAttribute("userID")): int(s.getAttribute("id"))
for s in SharedServer}
server_id = shared_servers.get(user_id)
if server_id:
url = "https://plex.tv/api/servers/" + SERVER_ID + "/shared_servers/" + str(server_id)
r = requests.delete(url, headers=headers)
if r.status_code == 200:
print("Unshared libraries with user %s" % str(user_id))
else:
print("No libraries shared with user %s" % str(user_id))
return
def get_get_activity():
# Get the user IP list from PlexPy
payload = {'apikey': PLEXPY_APIKEY,
'cmd': 'get_activity'}
try:
r = requests.get(PLEXPY_URL.rstrip('/') + '/api/v2', params=payload)
response = r.json()
res_data = response['response']['data']['sessions']
return [Activity(data=d) for d in res_data]
except Exception as e:
sys.stderr.write("PlexPy API 'get_get_users_tables' request failed: {0}.".format(e))
if __name__ == "__main__":
activity = get_get_activity()
act_lst = [a.user_id for a in activity]
user_lst = [key for key, value in USER_LIBRARIES.iteritems()]
for i in user_lst:
try:
if act_lst.count(i) >= LIMIT:
unshare(i)
else:
share(i)
except Exception:
share(i)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment