Skip to content

Commit 6fe7ad5

Browse files
author
Sam
committed
Initial commit.
0 parents  commit 6fe7ad5

15 files changed

+960
-0
lines changed

Diff for: EGG-INFO/PKG-INFO

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Metadata-Version: 1.0
2+
Name: Managed Pause
3+
Version: 0.2
4+
Summary: Pauses auto-managed torrents on a per-hour per-day basis.
5+
Home-page: http://deluge-torrent.org
6+
Author: Sam Lai
7+
Author-email: [email protected]
8+
License: GPLv3
9+
Description: Pauses auto-managed torrents on a per-hour per-day basis. Configurable only via web UI.
10+
Platform: UNKNOWN

Diff for: EGG-INFO/SOURCES.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
setup.py
2+
ManagedPause.egg-info/PKG-INFO
3+
ManagedPause.egg-info/SOURCES.txt
4+
ManagedPause.egg-info/dependency_links.txt
5+
ManagedPause.egg-info/entry_points.txt
6+
ManagedPause.egg-info/top_level.txt
7+
managedpause/__init__.py
8+
managedpause/common.py
9+
managedpause/core.py
10+
managedpause/gtkui.py
11+
managedpause/webui.py

Diff for: EGG-INFO/dependency_links.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Diff for: EGG-INFO/entry_points.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
[deluge.plugin.core]
3+
ManagedPause = managedpause:CorePlugin
4+
[deluge.plugin.gtkui]
5+
ManagedPause = managedpause:GtkUIPlugin
6+
[deluge.plugin.web]
7+
ManagedPause = managedpause:WebUIPlugin
8+

Diff for: EGG-INFO/top_level.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
managedpause

Diff for: EGG-INFO/zip-safe

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Diff for: README.markdown

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
deluge-managedpause
2+
===================
3+
4+
This plugin for [Deluge][1] pauses (and resumes) auto-managed torrents
5+
according to an hourly schedule.
6+
7+
This means that if you don't want the preset schedule to affect a particular
8+
torrent, you simply change the auto-managed setting on that torrent to false.
9+
10+
There is also an option to ignore any torrents that are seeding only; this is
11+
useful if uploading is not counted towards your quota.
12+
13+
It can only be configured via the web interface (or by hand); there is no GTK
14+
UI for this plugin.
15+
16+
If there are any issues, feel free to drop me an email at [email protected], or
17+
better yet, fork, fix, and I'll pull your changes.
18+
19+
[1]: http://deluge-torrent.org

Diff for: managedpause/__init__.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#
2+
# __init__.py
3+
#
4+
# Copyright (C) 2009 Andrew Resch <[email protected]>
5+
#
6+
# Basic plugin template created by:
7+
# Copyright (C) 2008 Martijn Voncken <[email protected]>
8+
# Copyright (C) 2007-2009 Andrew Resch <[email protected]>
9+
#
10+
# Deluge is free software.
11+
#
12+
# You may redistribute it and/or modify it under the terms of the
13+
# GNU General Public License, as published by the Free Software
14+
# Foundation; either version 3 of the License, or (at your option)
15+
# any later version.
16+
#
17+
# deluge is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20+
# See the GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with deluge. If not, write to:
24+
# The Free Software Foundation, Inc.,
25+
# 51 Franklin Street, Fifth Floor
26+
# Boston, MA 02110-1301, USA.
27+
#
28+
# In addition, as a special exception, the copyright holders give
29+
# permission to link the code of portions of this program with the OpenSSL
30+
# library.
31+
# You must obey the GNU General Public License in all respects for all of
32+
# the code used other than OpenSSL. If you modify file(s) with this
33+
# exception, you may extend this exception to your version of the file(s),
34+
# but you are not obligated to do so. If you do not wish to do so, delete
35+
# this exception statement from your version. If you delete this exception
36+
# statement from all source files in the program, then also delete it here.
37+
#
38+
39+
from deluge.plugins.init import PluginInitBase
40+
41+
class CorePlugin(PluginInitBase):
42+
def __init__(self, plugin_name):
43+
from core import Core as _plugin_cls
44+
self._plugin_cls = _plugin_cls
45+
super(CorePlugin, self).__init__(plugin_name)
46+
47+
class GtkUIPlugin(PluginInitBase):
48+
def __init__(self, plugin_name):
49+
from gtkui import GtkUI as _plugin_cls
50+
self._plugin_cls = _plugin_cls
51+
super(GtkUIPlugin, self).__init__(plugin_name)
52+
53+
class WebUIPlugin(PluginInitBase):
54+
def __init__(self, plugin_name):
55+
from webui import WebUI as _plugin_cls
56+
self._plugin_cls = _plugin_cls
57+
super(WebUIPlugin, self).__init__(plugin_name)

Diff for: managedpause/common.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#
2+
# common.py
3+
#
4+
# Copyright (C) 2010 Sam Lai <[email protected]>
5+
# Copyright (C) 2009 Andrew Resch <[email protected]>
6+
#
7+
# Basic plugin template created by:
8+
# Copyright (C) 2008 Martijn Voncken <[email protected]>
9+
# Copyright (C) 2007-2009 Andrew Resch <[email protected]>
10+
#
11+
# Deluge is free software.
12+
#
13+
# You may redistribute it and/or modify it under the terms of the
14+
# GNU General Public License, as published by the Free Software
15+
# Foundation; either version 3 of the License, or (at your option)
16+
# any later version.
17+
#
18+
# deluge is distributed in the hope that it will be useful,
19+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21+
# See the GNU General Public License for more details.
22+
#
23+
# You should have received a copy of the GNU General Public License
24+
# along with deluge. If not, write to:
25+
# The Free Software Foundation, Inc.,
26+
# 51 Franklin Street, Fifth Floor
27+
# Boston, MA 02110-1301, USA.
28+
#
29+
# In addition, as a special exception, the copyright holders give
30+
# permission to link the code of portions of this program with the OpenSSL
31+
# library.
32+
# You must obey the GNU General Public License in all respects for all of
33+
# the code used other than OpenSSL. If you modify file(s) with this
34+
# exception, you may extend this exception to your version of the file(s),
35+
# but you are not obligated to do so. If you do not wish to do so, delete
36+
# this exception statement from your version. If you delete this exception
37+
# statement from all source files in the program, then also delete it here.
38+
#
39+
40+
def get_resource(filename):
41+
import pkg_resources, os
42+
return pkg_resources.resource_filename("managedpause", os.path.join("data", filename))

Diff for: managedpause/core.py

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#
2+
# core.py
3+
#
4+
# Copyright (C) 2010 Sam Lai <[email protected]>
5+
# Copyright (C) 2009 Andrew Resch <[email protected]>
6+
#
7+
# Basic plugin template created by:
8+
# Copyright (C) 2008 Martijn Voncken <[email protected]>
9+
# Copyright (C) 2007-2009 Andrew Resch <[email protected]>
10+
#
11+
# Deluge is free software.
12+
#
13+
# You may redistribute it and/or modify it under the terms of the
14+
# GNU General Public License, as published by the Free Software
15+
# Foundation; either version 3 of the License, or (at your option)
16+
# any later version.
17+
#
18+
# deluge is distributed in the hope that it will be useful,
19+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21+
# See the GNU General Public License for more details.
22+
#
23+
# You should have received a copy of the GNU General Public License
24+
# along with deluge. If not, write to:
25+
# The Free Software Foundation, Inc.,
26+
# 51 Franklin Street, Fifth Floor
27+
# Boston, MA 02110-1301, USA.
28+
#
29+
# In addition, as a special exception, the copyright holders give
30+
# permission to link the code of portions of this program with the OpenSSL
31+
# library.
32+
# You must obey the GNU General Public License in all respects for all of
33+
# the code used other than OpenSSL. If you modify file(s) with this
34+
# exception, you may extend this exception to your version of the file(s),
35+
# but you are not obligated to do so. If you do not wish to do so, delete
36+
# this exception statement from your version. If you delete this exception
37+
# statement from all source files in the program, then also delete it here.
38+
#
39+
40+
import time
41+
42+
from deluge.log import LOG as log
43+
from deluge.plugins.pluginbase import CorePluginBase
44+
import deluge.component as component
45+
import deluge.configmanager
46+
from deluge.core.rpcserver import export
47+
from deluge.event import DelugeEvent
48+
49+
from twisted.internet import reactor
50+
51+
DEFAULT_PREFS = {
52+
"button_state": [[0] * 7 for dummy in xrange(24)],
53+
"ignore_seeding": False
54+
}
55+
56+
STATES = {
57+
0: "Green",
58+
2: "Red"
59+
}
60+
61+
class ScheduleEvent(DelugeEvent):
62+
"""
63+
Emitted when a schedule state changes.
64+
"""
65+
def __init__(self, colour):
66+
"""
67+
:param colour: str, the current scheduler state
68+
"""
69+
self._args = [colour]
70+
71+
class Core(CorePluginBase):
72+
def enable(self):
73+
self.config = deluge.configmanager.ConfigManager("managedpause.conf", DEFAULT_PREFS)
74+
75+
self.state = self.get_state()
76+
77+
# Register to apply scheduling rules once session has started, i.e. torrents loaded.
78+
component.get("EventManager").register_event_handler("SessionStartedEvent", self.on_session_started)
79+
80+
# Also when session is resuming...
81+
component.get("EventManager").register_event_handler("SessionResumedEvent", self.on_session_resumed)
82+
83+
def disable(self):
84+
try:
85+
self.timer.cancel()
86+
except:
87+
pass
88+
component.get("EventManager").deregister_event_handler("SessionStartedEvent", self.on_session_started)
89+
component.get("EventManager").deregister_event_handler("TorrentAddedEvent", self.on_torrent_added)
90+
component.get("EventManager").deregister_event_handler("SessionResumedEvent", self.on_session_resumed)
91+
92+
def update(self):
93+
pass
94+
95+
def on_session_started(self):
96+
# Apply the scheduling rules
97+
self.do_schedule(False)
98+
99+
# Schedule the next do_schedule() call for on the next hour
100+
now = time.localtime(time.time())
101+
secs_to_next_hour = ((60 - now[4]) * 60) + (60 - now[5])
102+
self.timer = reactor.callLater(secs_to_next_hour, self.do_schedule)
103+
log.debug("MANAGEDPAUSE: scheduling next check in %d seconds." % (secs_to_next_hour))
104+
105+
# Apply rules to newly added torrents too
106+
# add event here to avoid processing the event for each torrent when session is restoring
107+
component.get("EventManager").register_event_handler("TorrentAddedEvent", self.on_torrent_added)
108+
109+
def on_torrent_added(self, torrent_id):
110+
# Apply current scheduling rule to new torrent
111+
state = self.get_state()
112+
torrent = component.get("TorrentManager").torrents[torrent_id]
113+
114+
# only apply the pause action to avoid interfering with the user option
115+
# 'add torrent as paused'
116+
if state == "Red":
117+
log.debug("MANAGEDPAUSE [TORRENT ADDED]: paused new torrent, %s" % torrent.get_status(["name"])[0])
118+
torrent.pause()
119+
120+
def on_session_resumed(self):
121+
# Apply the scheduling rules
122+
self.do_schedule(False)
123+
124+
def _set_managed_torrents_state(self, active):
125+
"""
126+
Sets all auto-managed torrents to the state specfied in active, i.e. either running, or paused.
127+
"""
128+
129+
torrents = component.get("TorrentManager").torrents
130+
log.debug("MANAGEDPAUSE [SET STATE]: currently have %d torrents." % len(torrents))
131+
for t in torrents.values():
132+
log.debug("MANAGEDPAUSE [SET STATE]: %s, auto-managed %s, currently %s" % (t.filename, t.options["auto_managed"], t.state))
133+
if t.options["auto_managed"] and (not self.config["ignore_seeding"] or t.state != "Seeding"):
134+
if active:
135+
t.resume()
136+
else:
137+
t.pause()
138+
139+
def do_schedule(self, timer=True):
140+
"""
141+
This is where we apply schedule rules.
142+
"""
143+
144+
log.debug("MANAGEDPAUSE: applying schedule rules")
145+
146+
state = self.get_state()
147+
log.debug("MANAGEDPAUSE: the current state is %s" % state)
148+
149+
# if this isn't timer triggered, run processing regardless to ensure it
150+
# is applied and consistent.
151+
if (state != self.state) or not timer:
152+
if state == "Green":
153+
# This is Green (Normal) so we just resume all auto-managed torrents
154+
log.debug("MANAGEDPAUSE: resuming all auto-managed torrents")
155+
self._set_managed_torrents_state(True)
156+
# Resume the session if necessary
157+
component.get("Core").session.resume()
158+
elif state == "Red":
159+
# This is Red, so pause all auto-managed torrents
160+
log.debug("MANAGEDPAUSE: pausing all auto-managed torrents")
161+
self._set_managed_torrents_state(False)
162+
163+
if state != self.state:
164+
# The state has changed since last update so we need to emit an event
165+
self.state = state
166+
component.get("EventManager").emit(ScheduleEvent(self.state))
167+
168+
if timer:
169+
# Call this again in 1 hour
170+
self.timer = reactor.callLater(3600, self.do_schedule)
171+
172+
@export()
173+
def set_config(self, config):
174+
"sets the config dictionary"
175+
for key in config.keys():
176+
self.config[key] = config[key]
177+
self.config.save()
178+
self.do_schedule(False)
179+
180+
@export()
181+
def get_config(self):
182+
"returns the config dictionary"
183+
return self.config.config
184+
185+
@export()
186+
def get_state(self):
187+
now = time.localtime(time.time())
188+
level = self.config["button_state"][now[3]][now[6]]
189+
return STATES[level]

Diff for: managedpause/data/green.png

792 Bytes
Loading

0 commit comments

Comments
 (0)