From a333effc88133be64ec09b0f1a3655c098fb8420 Mon Sep 17 00:00:00 2001 From: chestm007 Date: Fri, 21 Dec 2018 03:23:16 +1100 Subject: [PATCH] Deluge (#685) deluge module --- docs/conf.py | 1 + i3pystatus/core/util.py | 14 +++++ i3pystatus/deluge.py | 112 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 i3pystatus/deluge.py diff --git a/docs/conf.py b/docs/conf.py index 7f116b4..5113304 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -33,6 +33,7 @@ MOCK_MODULES = [ "requests.exceptions", "bs4", "dota2py", + 'deluge_client', "novaclient", "speedtest", "pyzabbix", diff --git a/i3pystatus/core/util.py b/i3pystatus/core/util.py index 5d9bd71..268e3be 100644 --- a/i3pystatus/core/util.py +++ b/i3pystatus/core/util.py @@ -136,6 +136,20 @@ def convert_position(pos, json): return pos +def bytes_info_dict(in_bytes): + power = 2**10 # 2 ** 10 == 1024 + n = 0 + pow_dict = {0: '', 1: 'K', 2: 'M', 3: 'G', 4: 'T'} + out_bytes = int(in_bytes) + while out_bytes > power: + out_bytes /= power + n += 1 + return { + 'value': out_bytes, + 'unit': '{prefix}B'.format(prefix=pow_dict[n]) + } + + def flatten(l): """ Flattens a hierarchy of nested lists into a single list containing all elements in order diff --git a/i3pystatus/deluge.py b/i3pystatus/deluge.py new file mode 100644 index 0000000..c3634e5 --- /dev/null +++ b/i3pystatus/deluge.py @@ -0,0 +1,112 @@ +import time + +from deluge_client import DelugeRPCClient + +from i3pystatus import IntervalModule, logger +from i3pystatus.core.util import bytes_info_dict + + +class Deluge(IntervalModule): + """ + Deluge torrent module + Requires `deluge-client` + + .. rubric:: Formatters: + + * `{num_torrents}` - number of torrents in deluge + * `{free_space_bytes}` - bytes free in path + * `{used_space_bytes}` - bytes used in path + * `{upload_rate}` - bytes sent per second + * `{download_rate}` - bytes received per second + * `{total_uploaded}` - bytes sent total + * `{total_downloaded}` - bytes received total + + """ + + settings = ( + 'format', + ('rounding', 'number of decimal places to round numbers too'), + ('host', 'address of deluge server (default: 127.0.0.1)'), + ('port', 'port of deluge server (default: 58846)'), + ('username', 'username to authenticate with deluge'), + ('password', 'password to authenticate to deluge'), + ('path', 'override "download path" server-side when checking space used/free'), + ) + required = ('username', 'password') + + host = '127.0.0.1' + port = 58846 + path = None + libtorrent_stats = False + rounding = 2 + + format = '⛆{num_torrents} ✇{free_space_bytes}' + + id = int(time.time()) # something random + + def init(self): + self.client = DelugeRPCClient(self.host, self.port, self.username, self.password) + self.data = {} + + def run(self): + if not self.client.connected: + self.client.connect() + + self.data = self.get_session_statistics() + + torrents = self.get_torrents_status() + if torrents: + self.data['num_torrents'] = len(torrents) + + if 'free_space_bytes' in self.format: + self.data['free_space_bytes'] = self.get_free_space(self.path) + if 'used_space_bytes' in self.format: + self.data['used_space_bytes'] = self.get_path_size(self.path) + + self.parse_values(self.data) + + self.output = { + 'full_text': self.format.format(**self.data) + } + + def parse_values(self, values): + for k, v in values.items(): + if v: + if k in ['total_upload', 'total_download', 'download_rate', 'upload_rate'] or k.endswith('_bytes'): + values[k] = '{value:.{round}f}{unit}'.format(round=self.rounding, **bytes_info_dict(v)) + + def get_path_size(self, path=None): + """ + get used space of path in bytes (default: download location) + """ + if path is None: + path = [] + return self.client.call('core.get_path_size', path) + + def get_free_space(self, path=None): + """ + get free space of path in bytes (default: download location) + """ + if path is None: + path = [] + return self.client.call('core.get_free_space', path) + + def get_torrents_status(self, torrent_id=None, keys=None): + if torrent_id is None: + torrent_id = [] + if keys is None: + keys = [] + return self.client.call('core.get_torrents_status', torrent_id, keys) + + def get_session_statistics(self): + keys = ['upload_rate', 'download_rate', 'total_upload', 'total_download'] + + out = {} # some of the values from deluge-client are bytes, the others are ints - we need to decode them + for k, v in self.client.call('core.get_session_status', keys).items(): + k = k.decode('utf-8') # keys aswell + if type(v) == bytes: + out[k] = v.decode('utf-8') + else: + out[k] = v + + return out