Skip to content

Commit 5dc4fd9

Browse files
Merge branch 'dasimmet-master'
2 parents 97190b6 + e43599e commit 5dc4fd9

File tree

5 files changed

+231
-11
lines changed

5 files changed

+231
-11
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ was added so it works perfectly fine with infohashes.
88
Private torrents are excluded on purpose, because their metadata is not
99
supposed to reach public trackers.
1010

11+
Besides manually creating the default tracker list, you can also load it (periodically) from a URL.
12+
1113
## Installation
1214

1315
* create the egg with
@@ -18,11 +20,16 @@ supposed to reach public trackers.
1820

1921
* add it to Deluge from Preferences -> Plugins -> Install Plugin
2022

23+
## Dependencies
24+
25+
* [Requests][3]
26+
2127
## TODO:
2228

2329
* log the added trackers so we can remove them from torrents when they are deleted from the default list
2430
* WebUI version
2531

2632
[1]: http://deluge-torrent.org/
2733
[2]: egg/
34+
[3]: http://python-requests.org/
2835

defaulttrackers/core.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#
1+
# -*- coding: utf-8 -*-
22
# core.py
33
#
4-
# Copyright (C) 2013-2016 Stefan Talpalaru <[email protected]>
4+
# Copyright (C) 2013-2018 Ștefan Talpalaru <[email protected]>
55
#
66
# Basic plugin template created by:
77
# Copyright (C) 2008 Martijn Voncken <[email protected]>
@@ -38,16 +38,27 @@
3838
# statement from all source files in the program, then also delete it here.
3939
#
4040

41+
import datetime
4142
import logging
43+
import re
44+
import requests
45+
import time
46+
import traceback
47+
48+
from deluge.common import is_url
49+
from deluge.core.rpcserver import export
4250
from deluge.plugins.pluginbase import CorePluginBase
4351
import deluge.component as component
4452
import deluge.configmanager
45-
from deluge.core.rpcserver import export
53+
4654

4755
DEFAULT_PREFS = {
4856
"trackers": [
49-
#{"url": "test"},
57+
#{"url": "udp://foo.bar:6969/announce"},
5058
],
59+
"dynamic_trackerlist_url": "",
60+
"last_dynamic_trackers_update": 0, # UTC timestamp
61+
"dynamic_trackers_update_interval": 1, # in days
5162
}
5263

5364
log = logging.getLogger(__name__)
@@ -67,12 +78,30 @@ def disable(self):
6778
def update(self):
6879
pass
6980

81+
@export
82+
def update_trackerlist_from_url(self):
83+
if self.config["dynamic_trackerlist_url"]:
84+
now = datetime.datetime.utcnow()
85+
last_update = datetime.datetime.utcfromtimestamp(self.config["last_dynamic_trackers_update"])
86+
if now - last_update > datetime.timedelta(days=self.config["dynamic_trackers_update_interval"]):
87+
old_trackers = set([t["url"] for t in self.config["trackers"]])
88+
try:
89+
page = requests.get(self.config["dynamic_trackerlist_url"]).text
90+
new_trackers = [url for url in re.findall(r'\w+://[\w\-.:/]+', page) if is_url(url) and url not in old_trackers]
91+
for new_tracker in new_trackers:
92+
self.config["trackers"].append({"url": new_tracker})
93+
self.config["last_dynamic_trackers_update"] = time.mktime(now.timetuple())
94+
except:
95+
traceback.print_exc()
96+
return self.config.config
97+
7098
def on_torrent_added(self, torrent_id, from_state=False):
7199
torrent = component.get("TorrentManager")[torrent_id]
72100
if (torrent.torrent_info and torrent.torrent_info.priv()) or torrent.get_status(["private"])["private"]:
73101
return
74102
trackers = list(torrent.get_status(["trackers"])["trackers"])
75103
existing_urls = [tracker["url"] for tracker in trackers]
104+
self.update_trackerlist_from_url()
76105
got_new_trackers = False
77106
for new_tracker in self.config["trackers"]:
78107
if new_tracker["url"] not in existing_urls:
@@ -96,3 +125,4 @@ def set_config(self, config):
96125
def get_config(self):
97126
"""Returns the config dictionary"""
98127
return self.config.config
128+

defaulttrackers/data/config.glade

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,169 @@
88
<widget class="GtkVBox" id="prefs_box">
99
<property name="visible">True</property>
1010
<property name="can_focus">False</property>
11+
<child>
12+
<widget class="GtkFrame" id="frame2">
13+
<property name="visible">True</property>
14+
<property name="can_focus">False</property>
15+
<property name="label_xalign">0</property>
16+
<property name="shadow_type">none</property>
17+
<child>
18+
<widget class="GtkAlignment" id="alignment2">
19+
<property name="visible">True</property>
20+
<property name="can_focus">False</property>
21+
<property name="left_padding">12</property>
22+
<child>
23+
<widget class="GtkVBox" id="vbox1">
24+
<property name="visible">True</property>
25+
<property name="can_focus">False</property>
26+
<child>
27+
<widget class="GtkHBox" id="hbox2">
28+
<property name="visible">True</property>
29+
<property name="can_focus">False</property>
30+
<child>
31+
<widget class="GtkLabel" id="label3">
32+
<property name="visible">True</property>
33+
<property name="can_focus">False</property>
34+
<property name="label" translatable="yes">tracker list URL:</property>
35+
</widget>
36+
<packing>
37+
<property name="expand">False</property>
38+
<property name="fill">False</property>
39+
<property name="position">0</property>
40+
</packing>
41+
</child>
42+
<child>
43+
<widget class="GtkEntry" id="tracker_list_url">
44+
<property name="visible">True</property>
45+
<property name="can_focus">True</property>
46+
<property name="invisible_char">●</property>
47+
<property name="primary_icon_activatable">False</property>
48+
<property name="secondary_icon_activatable">False</property>
49+
<property name="primary_icon_sensitive">True</property>
50+
<property name="secondary_icon_sensitive">True</property>
51+
</widget>
52+
<packing>
53+
<property name="expand">True</property>
54+
<property name="fill">True</property>
55+
<property name="padding">6</property>
56+
<property name="position">1</property>
57+
</packing>
58+
</child>
59+
</widget>
60+
<packing>
61+
<property name="expand">True</property>
62+
<property name="fill">True</property>
63+
<property name="position">0</property>
64+
</packing>
65+
</child>
66+
<child>
67+
<widget class="GtkLabel" id="label6">
68+
<property name="visible">True</property>
69+
<property name="can_focus">False</property>
70+
<property name="label" translatable="yes">e.g.: https://newtrackon.com/api/stable
71+
or https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_all.txt</property>
72+
<property name="selectable">True</property>
73+
</widget>
74+
<packing>
75+
<property name="expand">True</property>
76+
<property name="fill">True</property>
77+
<property name="position">1</property>
78+
</packing>
79+
</child>
80+
<child>
81+
<widget class="GtkHBox" id="hbox3">
82+
<property name="visible">True</property>
83+
<property name="can_focus">False</property>
84+
<child>
85+
<widget class="GtkLabel" id="label4">
86+
<property name="visible">True</property>
87+
<property name="can_focus">False</property>
88+
<property name="label" translatable="yes">reload every</property>
89+
</widget>
90+
<packing>
91+
<property name="expand">False</property>
92+
<property name="fill">False</property>
93+
<property name="position">0</property>
94+
</packing>
95+
</child>
96+
<child>
97+
<widget class="GtkEntry" id="tracker_list_update_interval">
98+
<property name="width_request">34</property>
99+
<property name="visible">True</property>
100+
<property name="can_focus">True</property>
101+
<property name="invisible_char">●</property>
102+
<property name="invisible_char_set">True</property>
103+
<property name="primary_icon_activatable">False</property>
104+
<property name="secondary_icon_activatable">False</property>
105+
<property name="primary_icon_sensitive">True</property>
106+
<property name="secondary_icon_sensitive">True</property>
107+
</widget>
108+
<packing>
109+
<property name="expand">False</property>
110+
<property name="fill">False</property>
111+
<property name="padding">6</property>
112+
<property name="position">1</property>
113+
</packing>
114+
</child>
115+
<child>
116+
<widget class="GtkLabel" id="label5">
117+
<property name="visible">True</property>
118+
<property name="can_focus">False</property>
119+
<property name="label" translatable="yes">days</property>
120+
</widget>
121+
<packing>
122+
<property name="expand">False</property>
123+
<property name="fill">False</property>
124+
<property name="position">2</property>
125+
</packing>
126+
</child>
127+
<child>
128+
<widget class="GtkButton" id="tracker_list_reload">
129+
<property name="label">gtk-refresh</property>
130+
<property name="visible">True</property>
131+
<property name="can_focus">True</property>
132+
<property name="receives_default">True</property>
133+
<property name="has_tooltip">True</property>
134+
<property name="tooltip" translatable="yes">reload the tracker list now</property>
135+
<property name="use_stock">True</property>
136+
<signal name="clicked" handler="on_reload_now_clicked"/>
137+
</widget>
138+
<packing>
139+
<property name="expand">False</property>
140+
<property name="fill">False</property>
141+
<property name="padding">10</property>
142+
<property name="position">3</property>
143+
</packing>
144+
</child>
145+
</widget>
146+
<packing>
147+
<property name="expand">False</property>
148+
<property name="fill">False</property>
149+
<property name="position">2</property>
150+
</packing>
151+
</child>
152+
</widget>
153+
</child>
154+
</widget>
155+
</child>
156+
<child>
157+
<widget class="GtkLabel" id="label2">
158+
<property name="visible">True</property>
159+
<property name="can_focus">False</property>
160+
<property name="label" translatable="yes">&lt;b&gt;Dynamic tracker list&lt;/b&gt; (optional)</property>
161+
<property name="use_markup">True</property>
162+
</widget>
163+
<packing>
164+
<property name="type">label_item</property>
165+
</packing>
166+
</child>
167+
</widget>
168+
<packing>
169+
<property name="expand">True</property>
170+
<property name="fill">True</property>
171+
<property name="position">0</property>
172+
</packing>
173+
</child>
11174
<child>
12175
<widget class="GtkFrame" id="frame1">
13176
<property name="visible">True</property>
@@ -149,7 +312,7 @@
149312
<packing>
150313
<property name="expand">True</property>
151314
<property name="fill">True</property>
152-
<property name="position">0</property>
315+
<property name="position">1</property>
153316
</packing>
154317
</child>
155318
</widget>

defaulttrackers/gtkui.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#
1+
# -*- coding: utf-8 -*-
22
# gtkui.py
33
#
4-
# Copyright (C) 2013-2016 Stefan Talpalaru <[email protected]>
4+
# Copyright (C) 2013-2018 Ștefan Talpalaru <[email protected]>
55
#
66
# Basic plugin template created by:
77
# Copyright (C) 2008 Martijn Voncken <[email protected]>
@@ -142,6 +142,7 @@ def enable(self):
142142
"on_remove_button_clicked": self.on_remove_button_clicked,
143143
"on_up_button_clicked": self.on_up_button_clicked,
144144
"on_down_button_clicked": self.on_down_button_clicked,
145+
"on_reload_now_clicked": self.on_reload_now_clicked,
145146
})
146147

147148
component.get("Preferences").add_page("Default Trackers", self.glade.get_widget("prefs_box"))
@@ -172,16 +173,28 @@ def disable(self):
172173

173174
def on_apply_prefs(self):
174175
log.debug("applying prefs for DefaultTrackers")
175-
config = {
176-
"trackers": [{"url": str(row[0])} for row in self.store]
177-
}
178-
client.defaulttrackers.set_config(config)
176+
try:
177+
update_interval = int(self.glade.get_widget("tracker_list_update_interval").get_text() or 1)
178+
except:
179+
update_interval = 1
180+
self.config.update({
181+
"trackers": [{"url": str(row[0])} for row in self.store],
182+
"dynamic_trackerlist_url": self.glade.get_widget("tracker_list_url").get_text(),
183+
"dynamic_trackers_update_interval": update_interval,
184+
})
185+
client.defaulttrackers.set_config(self.config)
179186

180187
def on_show_prefs(self):
181188
client.defaulttrackers.get_config().addCallback(self.cb_get_config)
182189

183190
def cb_get_config(self, config):
184191
"callback for on show_prefs"
192+
self.config = config
193+
# dynamic tracker list
194+
if config["dynamic_trackerlist_url"]:
195+
self.glade.get_widget("tracker_list_url").set_text(config["dynamic_trackerlist_url"])
196+
self.glade.get_widget("tracker_list_update_interval").set_text(str(config["dynamic_trackers_update_interval"]))
197+
# trackers
185198
self.trackers = list(config["trackers"])
186199
self.store.clear()
187200
for tracker in self.trackers:
@@ -258,3 +271,10 @@ def on_down_button_clicked(self, widget):
258271
if nexti is not None:
259272
self.store.swap(tree_id, nexti)
260273

274+
def on_reload_now_clicked(self, widget):
275+
# reset the last update timestamp
276+
self.config["last_dynamic_trackers_update"] = 0
277+
self.on_apply_prefs()
278+
# we need to reload the tracker list after the update
279+
client.defaulttrackers.update_trackerlist_from_url().addCallback(self.cb_get_config)
280+

egg/DefaultTrackers-0.1-py2.7.egg

1.91 KB
Binary file not shown.

0 commit comments

Comments
 (0)