Skip to content

Instantly share code, notes, and snippets.

@Hellowlol
Last active January 18, 2021 14:37
Show Gist options
  • Save Hellowlol/ee47b6534410b1880e19 to your computer and use it in GitHub Desktop.
Save Hellowlol/ee47b6534410b1880e19 to your computer and use it in GitHub Desktop.
Plexpy script, kill a plex stream
"""
This is a simple script showing how you can used plexpys notifications system to kill a stream
Possible plexpyargs: -tk {transcode_key} -u {username} -td {transcode_decision} -t 20:20 -ln Secret_tash
Instructions:
1. Save the script somewhere on your computer as kill_a_stream.py.
2. Edit the variables at the top of the script:
The host, port, token, and ssl, can be the same as in the PlexPy settings
Edit the list of blocked_users, separated by a comma.
3. PlexPy > Settings > Notification Agents > Scripts > Bell icon:
[X] Notify on playback start
[X] Notify on playback resume
4. PlexPy > Settings > Notification Agents > Scripts > Gear icon:
Enter the "Script folder" where you save the script from step 1.
Playback Start: kill_a_stream.py
Playback Resume: kill_a_stream.py
Save
5. PlexPy > Settings > Notifications > Script > Script Arguments:
-tk {transcode_key} -u {username} -td {transcode_decision}
Any time one of the blocked_users starts a transcoded session, the script will stop the stream.
You can also supply a -t 20:30 and the script will only kill a stream after 20:30 or disallow transcode from a library with -ln
"""
import argparse
import requests
from uuid import getnode
import platform
from datetime import datetime
### Edit me ###
host = '10.0.0.97'
port = 32400
token = '<token>'
ssl = '' # s or ''
kill_time = '' # time for date in 20:00 format
blocked_users = 'Hellowlol' # 'username1, username2'
blocked_librarys = '' # 'PG-18, adult'
### stop ###
def tcomp(kill_time):
zz = False
if kill_time:
tk = kill_time.split(':')
h = int(tk[0])
m = int(tk[1])
zz = datetime(2009, 12, 2, h, m).time()
return zz
def fetch(path, t='GET'):
url = 'http%s://%s:%s/' % (ssl, host, port)
headers = {'X-Plex-Token': token,
'Accept': 'application/json',
'X-Plex-Provides': 'controller',
'X-Plex-Platform': platform.uname()[0],
'X-Plex-Platform-Version': platform.uname()[2],
'X-Plex-Product': 'Plexpy script',
'X-Plex-Version': '0.9.5',
'X-Plex-Device': platform.platform(),
'X-Plex-Client-Identifier': str(hex(getnode()))
}
try:
if t == 'GET':
r = requests.get(url + path, headers=headers, verify=False)
elif t == 'POST':
r = requests.post(url + path, headers=headers, verify=False)
elif t == 'DELETE':
r = requests.delete(url + path, headers=headers, verify=False)
if r and len(r.content): # incase it dont return anything
return r.json()
else:
return r.content
except Exception as e:
print e
def kill_transcode(transcode_key):
print fetch('video/:/transcode/universal/stop?session=' + transcode_key)
def now():
return datetime.now().time()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-tk', '--transcode_key', action='store', default='',
help='Transcode key of the the current stream to kill')
parser.add_argument('-u', '--user', action='store', default=None,
help='username of the person watching a stream')
parser.add_argument('-td', '--transcode_decision', action='store', default=None,
help='transcode decision')
parser.add_argument('-ln', '--library_name', action='store', default=blocked_librarys,
help='What library was this played from')
parser.add_argument('-t', '--time', action='store', default=kill_time,
help='Kill only streams if clock is above t')
p = parser.parse_args()
if p.user in [bu.strip() for bu in blocked_users.split(',')] and p.transcode_decision.lower() == 'transcode' and not p.time:
kill_transcode(p.transcode_key)
# You can also kill any transcodes based on time by passing the -t parameter or editing the kill_tme
elif p.time and now() > tcomp(p.time) and p.transcode_decision.lower() == 'transcode' and p.user in [bu.strip() for bu in blocked_users.split(',')]:
kill_transcode(p.transcode_key)
elif p.library_name in [bln.strip() for bln in blocked_librarys.split(',')] and p.user in [bu.strip() for bu in blocked_users.split(',')] and p.transcode_decision.lower() == 'transcode':
kill_transcode(p.transcode_key)
@JonnyWong16
Copy link

On L27, usernames separated by space if you use split() on L95.

You should add {transcode_decision} as an argument so it will only kill the stream if it's transcode.

@JonnyWong16
Copy link

The PlexPy substitution is {transcode_key}, not {session_id}.

And another fix (L98):
if p.user in [bu.strip() for bu in blocked_users.split(',')] and p.transcode_decision.lower() == 'transcode':

@mescon
Copy link

mescon commented Apr 2, 2016

(trying to figure out if kill_time = '20:20' is something i'm supposed to change... )

I always want transcodes for banned users to be killed, so what's the point of a kill_time variable?

@mescon
Copy link

mescon commented Apr 2, 2016

It seems that when I enter an IP and force SSL, the requests library throws an error because by default it will verify SSL certificates. Because we're connecting directly to the plex server and not via the FQDN that the SSL certificate is issued to, it will fail.

Suggested fix is is to change:

            r = requests.get(url + path, headers=headers)
        elif t == 'POST':
            r = requests.post(url + path, headers=headers)
        elif t == 'DELETE':
            r = requests.delete(url + path, headers=headers)

into:

            r = requests.get(url + path, headers=headers, verify=False)
        elif t == 'POST':
            r = requests.post(url + path, headers=headers,verify=False)
        elif t == 'DELETE':
            r = requests.delete(url + path, headers=headers, verify=False)

@jrudio
Copy link

jrudio commented May 3, 2016

I'm testing out this method, but via Postman and I'm receiving a 404 status error. I know it's only been a month since this was posted, but does this method still work?

@Hellowlol
Copy link
Author

@jrudio if get 404 you need to check your token.

@jrudio
Copy link

jrudio commented May 14, 2016

@Hellowlol I believe the token should be fine, I took it from a browser session. The transcode key I am getting is from /transcode/sessions.

I just checked the pms logs and it's showing that the colon in video/:/transcode/universal/stop is missing. So it looks like that's the reason. Why it's getting stripped idk.

@jrudio
Copy link

jrudio commented May 14, 2016

Oh fuck me.

😠 😭

Postman treats colons as variables

@jrudio
Copy link

jrudio commented May 14, 2016

@Hellowlol Is there another method to kill direct play streams?

@iscmarkiemark
Copy link

@Hellowlol am also interest in killing direct play streams..

@cokefriend
Copy link

cokefriend commented Jun 16, 2016

script is being sent, but isnt killing the stream
not sure whats wrong.

@jrudio
Copy link

jrudio commented Jun 19, 2016

@iscmarkiemark I kind of have it working, if you revoke library access to a user, it will stop downloading more data. The downside is that the user can still play what they buffered.

@Hellowlol
Copy link
Author

Sorry for not responsive before. There is no way to stop a non transcode except revoke access as @jrudio explained.

@cokefriend
Copy link

@Hellowlol
i'm wondering about transcodes though
i'm checking the logs and the script does get activated, but it doesn't seem to do anything to the transcode

@seanvree
Copy link

seanvree commented Nov 6, 2016

is this still in development?

Is there a way to simply run this script on demand to stop all or SOME of the current streams? Like, if I have x ammount of streams from remote users and I want to kick them all w/o restarting PMS, or brining down my LAN?

@jrdnlc
Copy link

jrdnlc commented Nov 16, 2016

I'm also wondering if this still in development also. I want to be able to limit certain users to 1 stream.

@seanvree
Copy link

seanvree commented Dec 8, 2016

SO, just so I'm clear, this will "auto kill" the stream based on the user? Is there any way to kill a stream say, ON DEMAND?

@rembomy
Copy link

rembomy commented Jan 3, 2017

So, I have this working, but it is canceling on all transcodes. I would not mind when it transcodes audio, so I changed transcode_decision to video_decision, but now I get this issue where sometimes it responds as copy altho its transcode. This happens when user decides to start with Original, but changes to lower quality later, any ideas how to avoid that?

@archangel00uk
Copy link

archangel00uk commented Jan 6, 2017

I have separate VMs hosting Plex Media Server and PlexPy, when the stream is getting killed - which server is killing the stream? is it PlexPy or is it Plex Media Server? Just curious which machine requires all pre-requisite modules to be installed.

Am currently getting the following error (shown in PlexPy logs) -

PlexPy Notifiers :: Script error:
Traceback (most recent call last):
File "/opt/plexpy/PlexPy_Scripts/Kill_A_Stream.py", line 26, in
import requests
ImportError: No module named requests

However, running it in CLI I do not get the error when attempting to run python /opt/plexpy/PlexPy_Scripts/Kill_A_Stream.py.

I can also confirm the necessary modules are installed, any helps or a more simple guide would be much appreciated. Or even a sample configuration someone has setup.

Currently running both Plex Media Server and PlexPy on Ubuntu Server 16.04.

Thanks.

@blacktwin
Copy link

@seanvree I've created an on demand script using Hellowlol's kill_transcode function, here.

Here is another for killing when playback is paused or to be ran on demand.

@Hellowlol
Copy link
Author

Hellowlol commented Jan 11, 2017

Sorry for not responding before. I don't get notified when some adds a comment to this gist. I'll respond when I have access to a computer

@seanvree This script isnt in development anymore. I cant remember why i added it i think it was a request on reddit. (I have loads of fun with it)
@rembomy Check for both transcode and copy in https://gist.github.com/Hellowlol/ee47b6534410b1880e19#file-kill_a_stream-py-L120
Fx if p.user in [bu.strip() for bu in blocked_users.split(',')] and p.transcode_decision.lower() in ['copy', 'transcode'] and not p.time:

@mescon I know is a really long time since you asked but in answering out of posterinty. The -t variable is intended if you want to block a user after a set amount of time. Say you dont want the kid use plex on the ipad after 2200

@neuroryuu
Copy link

Hello friend, I am new to the plexpy script for a long time ago I am trying to make a script that allows me to have multiple users and some 2 to 3 transcodes, I want to close their transcodes if they are more than 2 and let them use only 1, it is possible???

@BattleKat
Copy link

@neuroryuu .. that functionality is built into the plex server. If you access server settings under Network there is:

Remote streams allowed per user  xxx
Maximum number of simultaneous streams each user is allowed when not on the local network.

@delexuz
Copy link

delexuz commented Aug 21, 2017

Hi, first off all, thank you so much for this script :D after i updated plex to Version 1.7.5.4035. the script doesn't kill streams anymore. Can anyone comfirm this, or is it just me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment