Last active
January 13, 2017 05:07
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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