From: Michael Tremer Date: Thu, 26 Jul 2012 12:37:10 +0000 (+0200) Subject: Update tracker websites. Show more information about the torrents. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=938d083d1a5ff7bfc11114471917b2b680729679;p=ipfire.org.git Update tracker websites. Show more information about the torrents. --- diff --git a/www/templates/tracker-torrent-detail.html b/www/templates/tracker-torrent-detail.html index 5afe1eb5..a4d8c52d 100644 --- a/www/templates/tracker-torrent-detail.html +++ b/www/templates/tracker-torrent-detail.html @@ -1,34 +1,31 @@ {% extends "base-1.html" %} -{% block title %}{{ _("Torrent Downloads") }}{% end block %} +{% block title %}{{ file.basename }} - {{ release.name }} - {{ _("Torrent download") }}{% end block %} {% block body %} - - - - - - - - - -
{{ _("Release") }} - {{ release.name }} -
{{ _("Hash") }}{{ release.torrent_hash }}
+

+ + {{ _("Magnet link") }} + + + {{ _("Torrent download") }} + +

-
- - {% if torrent.peers %} + {% if peers %}

{{ _("Peers") }}

- {{ modules.TrackerPeerList(torrent.peers, percentages=True) }} + {{ modules.TrackerPeerList(peers, percentages=True) }} {% end %} - {% if torrent.seeds %} + {% if seeds %}

{{ _("Seeds") }}

- {{ modules.TrackerPeerList(torrent.seeds) }} + {{ modules.TrackerPeerList(seeds) }} {% end %} {% end block %} diff --git a/www/templates/tracker-torrents.html b/www/templates/tracker-torrents.html index 8364ee1b..e3291172 100644 --- a/www/templates/tracker-torrents.html +++ b/www/templates/tracker-torrents.html @@ -8,36 +8,63 @@ {% if lang == "de" %} - - +

+ Dies ist der IPFire Torrent Tracker. +

+

+ Er wird für das verteilen der IPFire-Downloads gebraucht + und tut das effizient mit Hilfe des Bittorrent-Protokols. +

{% else %}

This is the home of the IPFire torrent tracker. +

+

This tracker is used to distribute the IPFire downloads in an efficient way with help of the Bittorrent protocol.

-

- The Bittorrent protocol transfers large files from one - peer to an other without need to download data from - a central server. However, there is a server which is - called the tracker that enables the clients to talk to - each other. -

{% end %} - +
+ - - + + + - {% for torrent in torrents %} + + + {% for release in releases %} - - - + + + {% for torrent in release.torrents %} + + + + + + + {% end %} {% end %} -
{{ _("Release") }}{{ _("Seeders") }}{{ _("Peers") }}{{ _("Seeders") }}{{ _("Peers") }} 
{{ torrent.name }}{{ torrent.seeds }}{{ torrent.peers }} +

{{ release.name }}

+
+ {{ torrent.basename }} + + {{ len(torrent.seeders) }} + + {{ len(torrent.peers) }} + + + + + + + +
+ + {% end block %} diff --git a/www/translations/de_DE/LC_MESSAGES/webapp.po b/www/translations/de_DE/LC_MESSAGES/webapp.po index 74a128be..9adfc089 100644 --- a/www/translations/de_DE/LC_MESSAGES/webapp.po +++ b/www/translations/de_DE/LC_MESSAGES/webapp.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-26 12:27+0200\n" +"POT-Creation-Date: 2012-07-26 14:36+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -97,8 +97,7 @@ msgstr "" msgid "Go back to latest stable downloads." msgstr "Zurück zu den neuesten stabilen Downloads." -#: templates/downloads-older.html:25 templates/tracker-torrent-detail.html:12 -#: templates/tracker-torrents.html:31 +#: templates/downloads-older.html:25 templates/tracker-torrents.html:32 msgid "Release" msgstr "Release" @@ -174,23 +173,22 @@ msgstr "Mirrorauslastung von heute" msgid "Mirror load" msgstr "Mirrorauslastung" -#: templates/tracker-torrent-detail.html:3 templates/tracker-torrents.html:3 -msgid "Torrent Downloads" -msgstr "Torrent-Downloads" - -#: templates/tracker-torrent-detail.html:7 templates/tracker-torrents.html:7 -msgid "IPFire Torrent Tracker" -msgstr "IPFire Torrent-Tracker" - +#: templates/tracker-torrent-detail.html:3 #: templates/tracker-torrent-detail.html:18 -msgid "Hash" -msgstr "Hash" +#: templates/modules/release-item.html:123 +msgid "Torrent download" +msgstr "Torrent-Download" -#: templates/tracker-torrent-detail.html:26 templates/tracker-torrents.html:33 +#: templates/tracker-torrent-detail.html:15 +#: templates/modules/release-item.html:122 +msgid "Magnet link" +msgstr "Magnet-Link" + +#: templates/tracker-torrent-detail.html:23 templates/tracker-torrents.html:34 msgid "Peers" msgstr "Peers" -#: templates/tracker-torrent-detail.html:31 +#: templates/tracker-torrent-detail.html:28 msgid "Seeds" msgstr "Seeds" @@ -845,7 +843,15 @@ msgstr "Details" msgid "Delete" msgstr "Löschen" -#: templates/tracker-torrents.html:32 +#: templates/tracker-torrents.html:3 +msgid "Torrent Downloads" +msgstr "Torrent-Downloads" + +#: templates/tracker-torrents.html:7 +msgid "IPFire Torrent Tracker" +msgstr "IPFire Torrent-Tracker" + +#: templates/tracker-torrents.html:33 msgid "Seeders" msgstr "Seeders" @@ -869,14 +875,6 @@ msgstr "Größe" msgid "Legend:" msgstr "Legende:" -#: templates/modules/release-item.html:122 -msgid "Magnet link" -msgstr "Magnet-Link" - -#: templates/modules/release-item.html:123 -msgid "Torrent download" -msgstr "Torrent-Download" - #: templates/modules/release-item.html:131 #: templates/modules/release-item-short.html:13 msgid "There are no downloads available for this release." @@ -1293,73 +1291,73 @@ msgstr "Unbekannter Autor" msgid "%s to %s" msgstr "%s nach %s" -#: webapp/backend/releases.py:73 +#: webapp/backend/releases.py:93 msgid "Image for the armv5tel architecture" msgstr "Image für die armv5tel-Architektur" -#: webapp/backend/releases.py:74 +#: webapp/backend/releases.py:94 msgid "Installable CD image" msgstr "Bootbares CD-Image" -#: webapp/backend/releases.py:75 +#: webapp/backend/releases.py:95 msgid "Torrent file" msgstr "Torrentdatei" -#: webapp/backend/releases.py:76 +#: webapp/backend/releases.py:96 msgid "Flash image" msgstr "Flash-Image" -#: webapp/backend/releases.py:77 +#: webapp/backend/releases.py:97 msgid "Alix image" msgstr "Alix-Image" -#: webapp/backend/releases.py:78 +#: webapp/backend/releases.py:98 msgid "USB FDD Image" msgstr "USB-FDD-Image" -#: webapp/backend/releases.py:79 +#: webapp/backend/releases.py:99 msgid "USB HDD Image" msgstr "USB-HDD-Image" -#: webapp/backend/releases.py:80 +#: webapp/backend/releases.py:100 msgid "Pregenerated Xen image" msgstr "Vorgefertigtes Xen-Image" -#: webapp/backend/releases.py:86 webapp/backend/releases.py:124 +#: webapp/backend/releases.py:106 webapp/backend/releases.py:144 msgid "Unknown image type" msgstr "Unbekanntes Imageformat" -#: webapp/backend/releases.py:111 +#: webapp/backend/releases.py:131 msgid "This image runs on many ARM-based boards" msgstr "Dieses Image läuft auf vielen ARM-basierten Boards" -#: webapp/backend/releases.py:112 +#: webapp/backend/releases.py:132 msgid "Use this image to burn a CD and install IPFire from it." msgstr "" "Nutze dieses Image um eine CD zu erstellen und IPFire von dieser zu " "installieren." -#: webapp/backend/releases.py:113 +#: webapp/backend/releases.py:133 msgid "Download the CD image from the torrent network." msgstr "CD-Image mit aus dem Torrentnetzwerk laden" -#: webapp/backend/releases.py:114 +#: webapp/backend/releases.py:134 msgid "An image that is meant to run on embedded devices." msgstr "Ein Image, das für eingebettete Systeme optimiert ist." -#: webapp/backend/releases.py:115 +#: webapp/backend/releases.py:135 msgid "Flash image where a serial console is enabled by default." msgstr "Image, bei welchem die serielle Konsole eingeschaltet ist." -#: webapp/backend/releases.py:116 +#: webapp/backend/releases.py:136 msgid "Install IPFire from a floppy-formated USB key." msgstr "IPFire von einem Floppy-formatiertem USB-Stick installieren." -#: webapp/backend/releases.py:117 +#: webapp/backend/releases.py:137 msgid "If the floppy image doesn't work, use this image instead." msgstr "Wenn das Floppy-Image nicht funktioniert, dieses verwenden." -#: webapp/backend/releases.py:118 +#: webapp/backend/releases.py:138 msgid "A ready-to-run image for Xen." msgstr "Ein fertiges Image für Xen." @@ -1530,6 +1528,9 @@ msgstr "%(weekday)s, %(day)s. %(month_name)s" msgid "%(commas)s and %(last)s" msgstr "%(commas)s und %(last)s" +#~ msgid "Hash" +#~ msgstr "Hash" + #~ msgid "Getting support" #~ msgstr "Support bekommen" diff --git a/www/translations/webapp.pot b/www/translations/webapp.pot index fcc3385d..54b73107 100644 --- a/www/translations/webapp.pot +++ b/www/translations/webapp.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-26 12:27+0200\n" +"POT-Creation-Date: 2012-07-26 14:36+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -93,8 +93,7 @@ msgstr "" msgid "Go back to latest stable downloads." msgstr "" -#: templates/downloads-older.html:25 templates/tracker-torrent-detail.html:12 -#: templates/tracker-torrents.html:31 +#: templates/downloads-older.html:25 templates/tracker-torrents.html:32 msgid "Release" msgstr "" @@ -170,23 +169,22 @@ msgstr "" msgid "Mirror load" msgstr "" -#: templates/tracker-torrent-detail.html:3 templates/tracker-torrents.html:3 -msgid "Torrent Downloads" -msgstr "" - -#: templates/tracker-torrent-detail.html:7 templates/tracker-torrents.html:7 -msgid "IPFire Torrent Tracker" +#: templates/tracker-torrent-detail.html:3 +#: templates/tracker-torrent-detail.html:18 +#: templates/modules/release-item.html:123 +msgid "Torrent download" msgstr "" -#: templates/tracker-torrent-detail.html:18 -msgid "Hash" +#: templates/tracker-torrent-detail.html:15 +#: templates/modules/release-item.html:122 +msgid "Magnet link" msgstr "" -#: templates/tracker-torrent-detail.html:26 templates/tracker-torrents.html:33 +#: templates/tracker-torrent-detail.html:23 templates/tracker-torrents.html:34 msgid "Peers" msgstr "" -#: templates/tracker-torrent-detail.html:31 +#: templates/tracker-torrent-detail.html:28 msgid "Seeds" msgstr "" @@ -837,7 +835,15 @@ msgstr "" msgid "Delete" msgstr "" -#: templates/tracker-torrents.html:32 +#: templates/tracker-torrents.html:3 +msgid "Torrent Downloads" +msgstr "" + +#: templates/tracker-torrents.html:7 +msgid "IPFire Torrent Tracker" +msgstr "" + +#: templates/tracker-torrents.html:33 msgid "Seeders" msgstr "" @@ -861,14 +867,6 @@ msgstr "" msgid "Legend:" msgstr "" -#: templates/modules/release-item.html:122 -msgid "Magnet link" -msgstr "" - -#: templates/modules/release-item.html:123 -msgid "Torrent download" -msgstr "" - #: templates/modules/release-item.html:131 #: templates/modules/release-item-short.html:13 msgid "There are no downloads available for this release." @@ -1285,71 +1283,71 @@ msgstr "" msgid "%s to %s" msgstr "" -#: webapp/backend/releases.py:73 +#: webapp/backend/releases.py:93 msgid "Image for the armv5tel architecture" msgstr "" -#: webapp/backend/releases.py:74 +#: webapp/backend/releases.py:94 msgid "Installable CD image" msgstr "" -#: webapp/backend/releases.py:75 +#: webapp/backend/releases.py:95 msgid "Torrent file" msgstr "" -#: webapp/backend/releases.py:76 +#: webapp/backend/releases.py:96 msgid "Flash image" msgstr "" -#: webapp/backend/releases.py:77 +#: webapp/backend/releases.py:97 msgid "Alix image" msgstr "" -#: webapp/backend/releases.py:78 +#: webapp/backend/releases.py:98 msgid "USB FDD Image" msgstr "" -#: webapp/backend/releases.py:79 +#: webapp/backend/releases.py:99 msgid "USB HDD Image" msgstr "" -#: webapp/backend/releases.py:80 +#: webapp/backend/releases.py:100 msgid "Pregenerated Xen image" msgstr "" -#: webapp/backend/releases.py:86 webapp/backend/releases.py:124 +#: webapp/backend/releases.py:106 webapp/backend/releases.py:144 msgid "Unknown image type" msgstr "" -#: webapp/backend/releases.py:111 +#: webapp/backend/releases.py:131 msgid "This image runs on many ARM-based boards" msgstr "" -#: webapp/backend/releases.py:112 +#: webapp/backend/releases.py:132 msgid "Use this image to burn a CD and install IPFire from it." msgstr "" -#: webapp/backend/releases.py:113 +#: webapp/backend/releases.py:133 msgid "Download the CD image from the torrent network." msgstr "" -#: webapp/backend/releases.py:114 +#: webapp/backend/releases.py:134 msgid "An image that is meant to run on embedded devices." msgstr "" -#: webapp/backend/releases.py:115 +#: webapp/backend/releases.py:135 msgid "Flash image where a serial console is enabled by default." msgstr "" -#: webapp/backend/releases.py:116 +#: webapp/backend/releases.py:136 msgid "Install IPFire from a floppy-formated USB key." msgstr "" -#: webapp/backend/releases.py:117 +#: webapp/backend/releases.py:137 msgid "If the floppy image doesn't work, use this image instead." msgstr "" -#: webapp/backend/releases.py:118 +#: webapp/backend/releases.py:138 msgid "A ready-to-run image for Xen." msgstr "" diff --git a/www/webapp/backend/databases.py b/www/webapp/backend/databases.py index 42f4952c..f09ceadc 100644 --- a/www/webapp/backend/databases.py +++ b/www/webapp/backend/databases.py @@ -32,14 +32,6 @@ class Databases(object): return self._connections["geoip"] - @property - def tracker(self): - if not self._connections.has_key("tracker"): - self._connections["tracker"] = \ - Connection(MYSQL_SERVER, "tracker", user="webapp") - - return self._connections["tracker"] - class Connection(tornado.database.Connection): def __init__(self, *args, **kwargs): diff --git a/www/webapp/backend/releases.py b/www/webapp/backend/releases.py index 6701f755..923c4dbf 100644 --- a/www/webapp/backend/releases.py +++ b/www/webapp/backend/releases.py @@ -15,14 +15,35 @@ from settings import Settings class File(object): def __init__(self, release, id): - self.release = release + self.id = id + self._release = release # get all data from database - self.__data = self.db.get("SELECT * FROM files WHERE id = %s", id) + self.__data = None @property def db(self): - return self.release.db + return Databases().webapp + + @property + def tracker(self): + return self.release.tracker + + @property + def data(self): + if self.__data is None: + self.__data = self.db.get("SELECT * FROM files WHERE id = %s", self.id) + assert self.__data + + return self.__data + + @property + def release(self): + if not self._release: + release_id = self.data.get("releases") + self._release = Release(release_id) + + return self._release @property def type(self): @@ -124,11 +145,11 @@ class File(object): @property def sha1(self): - return self.__data.get("sha1") + return self.data.get("sha1") @property def filename(self): - return self.__data.get("filename") + return self.data.get("filename") @property def basename(self): @@ -136,7 +157,7 @@ class File(object): @property def size(self): - return self.__data.get("filesize") + return self.data.get("filesize") @property def arch(self): @@ -150,7 +171,7 @@ class File(object): @property def torrent_hash(self): - return self.__data.get("torrent_hash", None) + return self.data.get("torrent_hash", None) @property def magnet_link(self): @@ -168,12 +189,37 @@ class File(object): return s + @property + def seeders(self): + if not self.torrent_hash: + return + + return self.tracker.get_seeds(self.torrent_hash) + + @property + def peers(self): + if not self.torrent_hash: + return + + return self.tracker.get_peers(self.torrent_hash) + + @property + def completed(self): + if not self.torrent_hash: + return + + return self.tracker.complete(self.torrent_hash) + class Release(object): @property def db(self): return Releases().db + @property + def tracker(self): + return tracker.Tracker() + def __init__(self, id): self.id = id @@ -191,13 +237,25 @@ class Release(object): def files(self): if not self.__files: files = self.db.query("SELECT id, filename FROM files WHERE releases = %s \ - AND loadable = 'Y'", self.id) + AND loadable = 'Y' AND NOT filename LIKE '%%.torrent'", self.id) - self.__files = [File(self, f.id) for f in files if not f.filename.endswith(".torrent")] + self.__files = [File(self, f.id) for f in files] self.__files.sort(lambda a, b: cmp(a.prio, b.prio)) return self.__files + @property + def torrents(self): + torrents = [] + + for file in self.files: + if not file.torrent_hash: + continue + + torrents.append(file) + + return torrents + @property def name(self): return self.__data.get("name") @@ -358,14 +416,17 @@ class Releases(object): return [Release(r.id) for r in releases] - def get_filename_for_torrent_hash(self, torrent_hash): - file = self.db.get("SELECT filename FROM files WHERE torrent_hash = %s LIMIT 1", + def get_file_for_torrent_hash(self, torrent_hash): + file = self.db.get("SELECT id, releases FROM files WHERE torrent_hash = %s LIMIT 1", torrent_hash) if not file: return - return file.filename + release = Release(file.releases) + file = File(release, file.id) + + return file if __name__ == "__main__": diff --git a/www/webapp/backend/tracker.py b/www/webapp/backend/tracker.py index 99624fae..4880bee4 100644 --- a/www/webapp/backend/tracker.py +++ b/www/webapp/backend/tracker.py @@ -1,9 +1,12 @@ #!/usr/bin/python +import os import random import time -from databases import Databases +import releases + +from databases import Databases, Row from misc import Singleton def decode_hex(s): @@ -30,10 +33,10 @@ class Tracker(object): @property def db(self): - return Databases().tracker + return Databases().webapp def _fetch(self, hash, limit=None, random=False, completed=False, no_peer_id=False): - query = "SELECT * FROM peers WHERE last_update >= %d" % self.since + query = "SELECT * FROM tracker_peers WHERE last_update >= %d" % self.since if hash: query += " AND hash = '%s'" % hash @@ -81,21 +84,21 @@ class Tracker(object): def event_started(self, hash, peer_id): # Damn, mysql does not support INSERT IF NOT EXISTS... - if not self.db.query("SELECT id FROM peers WHERE hash = '%s' AND peer_id = '%s'" % (hash, peer_id)): - self.db.execute("INSERT INTO peers(hash, peer_id) VALUES('%s', '%s')" % (hash, peer_id)) + if not self.db.query("SELECT id FROM tracker_peers WHERE hash = '%s' AND peer_id = '%s'" % (hash, peer_id)): + self.db.execute("INSERT INTO tracker_peers(hash, peer_id) VALUES('%s', '%s')" % (hash, peer_id)) if not hash in self.hashes: - self.db.execute("INSERT INTO hashes(hash) VALUES('%s')" % hash) + self.db.execute("INSERT INTO tracker_hashes(hash) VALUES('%s')" % hash) def event_stopped(self, hash, peer_id): - self.db.execute("DELETE FROM peers WHERE hash = '%s' AND peer_id = '%s'" % (hash, peer_id)) + self.db.execute("DELETE FROM tracker_peers WHERE hash = '%s' AND peer_id = '%s'" % (hash, peer_id)) def event_completed(self, hash, peer_id): - self.db.execute("UPDATE hashes SET completed=completed+1 WHERE hash = '%s'" % hash) + self.db.execute("UPDATE tracker_hashes SET completed=completed+1 WHERE hash = '%s'" % hash) def scrape(self, hashes=[]): ret = {} - for hash in self.db.query("SELECT hash, completed FROM hashes"): + for hash in self.db.query("SELECT hash, completed FROM tracker_hashes"): hash, completed = hash.hash, hash.completed if hashes and hash not in hashes: @@ -133,7 +136,7 @@ class Tracker(object): if not args: return - query = "UPDATE peers SET " + ", ".join(args) + \ + query = "UPDATE tracker_peers SET " + ", ".join(args) + \ " WHERE hash = '%s' AND peer_id = '%s'" % (hash, id) self.db.execute(query) @@ -141,7 +144,7 @@ class Tracker(object): @property def hashes(self): hashes = [] - for h in self.db.query("SELECT hash FROM hashes"): + for h in self.db.query("SELECT hash FROM tracker_hashes"): hashes.append(h["hash"].lower()) return hashes diff --git a/www/webapp/handlers_tracker.py b/www/webapp/handlers_tracker.py index 184ea505..6a911166 100644 --- a/www/webapp/handlers_tracker.py +++ b/www/webapp/handlers_tracker.py @@ -8,55 +8,37 @@ from handlers_base import * class TrackerIndexHandler(BaseHandler): def get(self): - hashes = self.tracker.hashes + releases = self.releases.get_all() - torrents = [] - for release in self.releases.list(): - if not release.torrent_hash: - continue + limit = 5 + releases = releases[:limit] - if release.torrent_hash in hashes: - torrents.append(tornado.database.Row({ - "name" : release.name, - "hash" : release.torrent_hash.lower(), - "peers" : self.tracker.incomplete(release.torrent_hash), - "seeds" : self.tracker.complete(release.torrent_hash), - })) - - self.render("tracker-torrents.html", torrents=torrents) + self.render("tracker-torrents.html", releases=releases) class TrackerDetailHandler(BaseHandler): - def get(self, hash): - release = None - for r in self.releases.list(): - if not r.torrent_hash: - continue - - if r.torrent_hash.lower() == hash.lower(): - release = r - break + def get(self, torrent_hash): + file = self.releases.get_file_for_torrent_hash(torrent_hash) - if not release: - raise tornado.web.HTTPError(404) + if not file: + raise tornado.web.HTTPError(404, "Could not find torrent file for hash: %s" % torrent_hash) - torrent = tornado.database.Row({ - "peers" : self.tracker.get_peers(hash), - "seeds" : self.tracker.get_seeds(hash), - }) + peers = self.tracker.get_peers(torrent_hash) + seeds = self.tracker.get_seeds(torrent_hash) - self.render("tracker-torrent-detail.html", release=release, torrent=torrent) + self.render("tracker-torrent-detail.html", release=file.release, + file=file, peers=peers, seeds=seeds) class TrackerDownloadHandler(BaseHandler): def get(self, torrent_hash): - file = self.releases.get_filename_for_torrent_hash(torrent_hash) + file = self.releases.get_file_for_torrent_hash(torrent_hash) if not file: - raise tornado.web.HTTPError(404, "Could not find torrent file for hash: %s" % hash) + raise tornado.web.HTTPError(404, "Could not find torrent file for hash: %s" % torrent_hash) # Redirect the user to the download redirector. - self.redirect("http://downloads.ipfire.org/%s.torrent" % file) + self.redirect("http://downloads.ipfire.org/%s.torrent" % file.filename) #class TrackerTorrentsHandler(BaseHandler):