Last active
March 13, 2018 08:54
-
-
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.
This file contains 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
#!/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