Skip to content

Instantly share code, notes, and snippets.

@cvium
Last active March 13, 2018 08:54
Show Gist options
  • Save cvium/3eabf74dfc428b6df710c7ece21dfebd to your computer and use it in GitHub Desktop.
Save cvium/3eabf74dfc428b6df710c7ece21dfebd to your computer and use it in GitHub Desktop.
A plexpy/tautulli notification script agent that throttles the upload rate of an rtorrent instance using rtxmlrpc if there are any remote Plex streams.
#!/usr/bin/env python
"""
Throttle an rtorrent instance when a remote stream is started. Can be executed from PlexPy/Tautulli or directly from
CLI.
Requirements:
1. Install pyroscope from github
2. install requests from pip
"""
import argparse
import platform
import requests
import subprocess
import sys
import time
from uuid import getnode
# CONFIG -- CHANGE THESE
limited_up = 100 # KiB/s
full_up = 0 # unlimited, max value = int(math.pow(2, 16))
rtxmlrpc_path = '~/local/bin/rtxmlrpc'
rtxmlrpc_config_dir = '' # leave empty to use default, no configs are required though
scgi_url = 'scgi://IP:PORT'
plex_host = 'http://plex:32400'
plex_token = 'TOKEN'
lan_subnet = '' # don't throttle when streaming from this subnet
# CODE HERE -- DO NOT CHANGE
def get_initial_args():
args = [rtxmlrpc_path, '-Dscgi_url={}'.format(scgi_url)]
if rtxmlrpc_config_dir:
args.extend(['--config-dir', rtxmlrpc_config_dir])
return args
def get_max_global_up_rate():
print('Getting max global upload rate')
up_rate_args = get_initial_args()
up_rate_args.extend(['throttle.global_up.max_rate', ''])
print('Args: {}'.format(up_rate_args))
up_rate = subprocess.check_output(up_rate_args, stderr=sys.stdout).strip()
up_rate_kb_args = get_initial_args()
up_rate_kb_args.extend(['to_kb', up_rate])
print('Args: {}'.format(up_rate_kb_args))
# Output contains a newline and it's a decimal, so...
return int(float(subprocess.check_output(up_rate_kb_args, stderr=sys.stdout).strip()))
def set_max_global_up_rate(new_rate):
current_rate = get_max_global_up_rate()
print('Current max global upload rate: {} KiB/s'.format(current_rate))
if current_rate == new_rate:
print('New upload rate == old upload rate. Skipping.')
return
print('Setting upload rate to {} KiB/s'.format(new_rate))
args = get_initial_args()
args.extend(['-q', 'throttle.global_up.max_rate.set_kb', '', '{}'.format(new_rate)])
print('Args: {}'.format(args))
subprocess.call(args, stdout=sys.stdout, stderr=sys.stdout)
def any_remote_sessions():
try:
headers = {
'X-Plex-Token': plex_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-Device': platform.platform(),
'X-Plex-Client-Identifier': str(hex(getnode()))
}
response = requests.get(plex_host + '/status/sessions', headers=headers)
except requests.RequestException as e:
print(str(e))
sys.exit(1)
if not response.content:
print('Empty response from Plex {}/status/sessions'.format(plex_host))
sys.exit(1)
media_container = response.json()['MediaContainer']
print('Active streams: {}'.format(media_container['size']))
if not media_container['size']:
return False
active_ips = set()
for stream in media_container['Video']:
# Only interested in remote streams
if not stream['Session'] or stream['Session']['location'] != 'wan':
continue
player = stream['Player']
if lan_subnet and lan_subnet in player['address']:
continue
# Skip paused streams as they don't use any bw
if player['state'] == 'paused':
print('Stream from {} is paused. Skipping.'.format(player['address']))
continue
active_ips.add(player['address'])
print('Active remote ips (not paused): {}'.format(', '.join(active_ips) or 'None'))
return bool(active_ips)
def main():
if any_remote_sessions():
set_max_global_up_rate(limited_up)
else:
set_max_global_up_rate(full_up)
sys.exit(0)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment