diff --git a/aberrant.py b/aberrant.py index 34c68fe..476ff55 100644 --- a/aberrant.py +++ b/aberrant.py @@ -2,7 +2,9 @@ """ The primary module for serving the Aberrant application. """ -from flask import Flask, render_template +import signal + +from flask import Flask, render_template, send_from_directory import rtorrent @@ -10,7 +12,8 @@ app = Flask(__name__) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True app.jinja_env.undefined = "StrictUndefined" -rtorrent.get_all() +rtorrent.init() +signal.signal(signal.SIGINT, rtorrent.stop_watch) @app.route("/") def index(): @@ -18,5 +21,10 @@ def index(): torrents = rtorrent.get_active() return render_template("index.html", **locals()) +@app.route("/static/") +def send_static(path): + """Sends static files.""" + return send_from_directory("static", path) + if __name__ == "__main__": app.run(host='0.0.0.0', port=5250) diff --git a/rtorrent.py b/rtorrent.py index 049b44b..923d38f 100644 --- a/rtorrent.py +++ b/rtorrent.py @@ -2,15 +2,21 @@ """ This module handles the interface with rTorrent via XMLRPC. """ +import re +import time +import threading import xmlrpc.client -_s = xmlrpc.client.ServerProxy("http://localhost:8000/RPC0") -torrents = [] +NUM_INST = 10 +WATCH_HANDLE = None +sp = [] +torrents = [[]] * NUM_INST class Torrent: def __init__(self, raw): self.hash = raw[0] self.name = raw[1] + self.active = raw[2] self.complete = raw[3] if not self.active: @@ -19,13 +25,64 @@ class Torrent: self.state = "seeding" else: self.state = "leeching" - self.downrate = raw[4] - self.uprate = raw[5] -def get_all(): - """Gets all torrent information and stores it.""" - global torrents - res = _s.d.multicall2('', 'main', + self.downrate = raw[4] + self.downrate_str = speedrate(self.downrate) + self.uprate = raw[5] + self.uprate_str = speedrate(self.uprate) + + +class Watch(threading.Thread): + """A thread class that continously queries the rTorrent instances.""" + def __init__(self): + super(Watch, self).__init__() + self._stop_event = threading.Event() + + def stop(self): + self._stop_event.set() + + def stopped(self): + return self._stop_event.is_set() + + def run(self): + global torrents + while not self.stopped(): + for n in range(NUM_INST): + if self.stopped(): + break + torrents[n] = get_all(n) + self._stop_event.wait(2) + + +def speedrate(rate): + """Helper to assign appropriate prefixes to speed rates.""" + unit = "B/s" + if rate > 1024: + rate /= 1024 + unit = "KiB/s" + if rate > 1024: + rate /= 1024 + unit = "MiB/s" + rate = round(rate, 1) + return str(rate) + unit + +def all_torrents(): + """Helper that returns a list of all torrents.""" + res = [] + for item in torrents: + res += item + return res + +def open_proxy(): + """Opens connections to all of the rtorrent instances.""" + global sp + for n in range(NUM_INST): + s = xmlrpc.client.ServerProxy(f"http://localhost:8000/RPC{n}") + sp.append(s) + +def get_all(n): + """Gets all torrent information from a instance and returns it.""" + res = sp[n].d.multicall2('', 'main', 'd.hash=', 'd.name=', 'd.is_active=', @@ -33,9 +90,21 @@ def get_all(): 'd.down.rate=', 'd.up.rate=', ) - torrents = [Torrent(raw) for raw in res] + return [Torrent(raw) for raw in res] + +def init(): + """Initializes the rTorrent interface.""" + global WATCH_HANDLE + open_proxy() + WATCH_HANDLE = Watch() + WATCH_HANDLE.start() + +def stop_watch(sig, frame): + """Stops the watch thread.""" + global WATCH_HANDLE + WATCH_HANDLE.stop() def get_active(): """Returns all actively seeding or leeching torrents.""" - active = [t for t in torrents if t.downrate or t.uprate] + active = [t for t in all_torrents() if t.downrate or t.uprate] return active diff --git a/static/aberrant.css b/static/aberrant.css new file mode 100644 index 0000000..a2b49c9 --- /dev/null +++ b/static/aberrant.css @@ -0,0 +1,28 @@ +#torrents { + width: 100%; + border-collapse: collapse; + border: 1px solid #ccc; +} + +tr { + border: 1px solid #ccc; +} + +.name { + padding-left: 1em; +} + +.state { + text-align: center; + width: 10%; +} + +.downrate { + text-align: center; + width: 10%; +} + +.uprate { + text-align: center; + width: 10%; +} diff --git a/templates/index.html b/templates/index.html index c4a9eae..f4be317 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,9 +2,10 @@ Aberrant + - +
@@ -16,10 +17,10 @@ {% for torrent in torrents %} - - - - + + + + {% endfor %}
Name
{{ torrent.name }}{{ torrent.state }}{{ torrent.downrate }}{{ torrent.uprate }}{{ torrent.name }}{{ torrent.state }}{{ torrent.downrate_str }}{{ torrent.uprate_str }}