fourth commit

This commit is contained in:
iou1name 2019-02-14 15:00:21 -05:00
parent 70c95d28af
commit 1d81c7fb63
4 changed files with 123 additions and 17 deletions

View File

@ -2,7 +2,9 @@
""" """
The primary module for serving the Aberrant application. 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 import rtorrent
@ -10,7 +12,8 @@ app = Flask(__name__)
app.jinja_env.trim_blocks = True app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True app.jinja_env.lstrip_blocks = True
app.jinja_env.undefined = "StrictUndefined" app.jinja_env.undefined = "StrictUndefined"
rtorrent.get_all() rtorrent.init()
signal.signal(signal.SIGINT, rtorrent.stop_watch)
@app.route("/") @app.route("/")
def index(): def index():
@ -18,5 +21,10 @@ def index():
torrents = rtorrent.get_active() torrents = rtorrent.get_active()
return render_template("index.html", **locals()) return render_template("index.html", **locals())
@app.route("/static/<path:path>")
def send_static(path):
"""Sends static files."""
return send_from_directory("static", path)
if __name__ == "__main__": if __name__ == "__main__":
app.run(host='0.0.0.0', port=5250) app.run(host='0.0.0.0', port=5250)

View File

@ -2,15 +2,21 @@
""" """
This module handles the interface with rTorrent via XMLRPC. This module handles the interface with rTorrent via XMLRPC.
""" """
import re
import time
import threading
import xmlrpc.client import xmlrpc.client
_s = xmlrpc.client.ServerProxy("http://localhost:8000/RPC0") NUM_INST = 10
torrents = [] WATCH_HANDLE = None
sp = []
torrents = [[]] * NUM_INST
class Torrent: class Torrent:
def __init__(self, raw): def __init__(self, raw):
self.hash = raw[0] self.hash = raw[0]
self.name = raw[1] self.name = raw[1]
self.active = raw[2] self.active = raw[2]
self.complete = raw[3] self.complete = raw[3]
if not self.active: if not self.active:
@ -19,13 +25,64 @@ class Torrent:
self.state = "seeding" self.state = "seeding"
else: else:
self.state = "leeching" self.state = "leeching"
self.downrate = raw[4]
self.uprate = raw[5]
def get_all(): self.downrate = raw[4]
"""Gets all torrent information and stores it.""" self.downrate_str = speedrate(self.downrate)
global torrents self.uprate = raw[5]
res = _s.d.multicall2('', 'main', 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.hash=',
'd.name=', 'd.name=',
'd.is_active=', 'd.is_active=',
@ -33,9 +90,21 @@ def get_all():
'd.down.rate=', 'd.down.rate=',
'd.up.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(): def get_active():
"""Returns all actively seeding or leeching torrents.""" """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 return active

28
static/aberrant.css Normal file
View File

@ -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%;
}

View File

@ -2,9 +2,10 @@
<html> <html>
<head> <head>
<title>Aberrant</title> <title>Aberrant</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='aberrant.css') }}">
</head> </head>
<body> <body>
<table> <table id="torrents">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
@ -16,10 +17,10 @@
<tbody> <tbody>
{% for torrent in torrents %} {% for torrent in torrents %}
<tr> <tr>
<td>{{ torrent.name }}</td> <td class="name">{{ torrent.name }}</td>
<td>{{ torrent.state }}</td> <td class="state">{{ torrent.state }}</td>
<td>{{ torrent.downrate }}</td> <td class="downrate">{{ torrent.downrate_str }}</td>
<td>{{ torrent.uprate }}</td> <td class="uprate">{{ torrent.uprate_str }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>