Apply patch from David Mohr to make core.py more 1.2 compatible
This commit is contained in:
parent
a6ab62f7ce
commit
4e3f4128fa
|
@ -1,11 +1,12 @@
|
|||
#
|
||||
# core.py
|
||||
#
|
||||
# Copyright (C) 2009 David Mohr <david@mcbf.net>
|
||||
# Copyright (C) 2008 Fredrik Eriksson <feeder@winterbird.org>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
|
@ -21,9 +22,9 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
|
@ -33,25 +34,32 @@
|
|||
# exception, you may extend this exception to your version of the file(s),
|
||||
# but you are not obligated to do so. If you do not wish to do so, delete
|
||||
# this exception statement from your version. If you delete this exception
|
||||
|
||||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
|
||||
import feedparser # for parsing rss feeds
|
||||
import gobject # for the update timer
|
||||
import threading # for threaded updates
|
||||
import re # for regular expressions
|
||||
import threading # for threaded updates
|
||||
import re # for regular expressions
|
||||
|
||||
|
||||
import deluge
|
||||
import string
|
||||
from deluge.log import LOG as log
|
||||
from deluge.plugins.corepluginbase import CorePluginBase
|
||||
from deluge import component
|
||||
from deluge.plugins.coreclient import client #1.1 and later only
|
||||
#client: see http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi
|
||||
from deluge.plugins.pluginbase import CorePluginBase
|
||||
import deluge.component as component
|
||||
import deluge.configmanager
|
||||
from deluge.core.rpcserver import export
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
"feeds": {},
|
||||
"filters": {},
|
||||
"updatetime": 15,
|
||||
"history": []
|
||||
}
|
||||
|
||||
# Helper classes
|
||||
|
||||
"""Help classes"""
|
||||
class Feed:
|
||||
"Class for the Feed object (containging feed configurations)"
|
||||
"""
|
||||
Class for the Feed object (containging feed configurations)
|
||||
"""
|
||||
def __init__(self):
|
||||
self.url = ""
|
||||
self.updatetime = 15
|
||||
|
@ -63,8 +71,11 @@ class Feed:
|
|||
self.url = config['url']
|
||||
self.updatetime = config['updatetime']
|
||||
|
||||
|
||||
class Filter:
|
||||
"Class for the Filter object (containing filter configurations)"
|
||||
"""
|
||||
Class for the Filter object (containing filter configurations)
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.regex = ""
|
||||
|
@ -74,7 +85,7 @@ class Filter:
|
|||
|
||||
# by default, set the configuration to match
|
||||
# the per-torrent settings in deluge
|
||||
def_conf = client.get_config()
|
||||
def_conf = component.get("Core").get_config()
|
||||
self.max_download_speed = def_conf['max_download_speed_per_torrent']
|
||||
self.max_upload_speed = def_conf['max_upload_speed_per_torrent']
|
||||
self.max_connections = def_conf['max_connections_per_torrent']
|
||||
|
@ -86,9 +97,9 @@ class Filter:
|
|||
self.stop_at_ratio = def_conf['stop_seed_at_ratio']
|
||||
self.stop_ratio = def_conf['stop_seed_ratio']
|
||||
self.remove_at_ratio = def_conf['remove_seed_at_ratio']
|
||||
|
||||
|
||||
def get_config(self):
|
||||
def_conf = client.get_config()
|
||||
def_conf = component.get("Core").get_config()
|
||||
|
||||
try:
|
||||
tmp = self.active
|
||||
|
@ -105,13 +116,13 @@ class Filter:
|
|||
self.stop_at_ratio = def_conf['stop_seed_at_ratio']
|
||||
self.stop_ratio = def_conf['stop_seed_ratio']
|
||||
self.remove_at_ratio = def_conf['remove_seed_at_ratio']
|
||||
|
||||
|
||||
conf = {
|
||||
'regex': self.regex,
|
||||
'feeds': self.feeds,
|
||||
'all_feeds': self.all_feeds,
|
||||
'active' : self.active,
|
||||
'max_download_speed': self.max_download_speed,
|
||||
'max_download_speed': self.max_download_speed,
|
||||
'max_upload_speed': self.max_upload_speed,
|
||||
'max_connections': self.max_connections,
|
||||
'max_upload_slots': self.max_upload_slots,
|
||||
|
@ -141,50 +152,208 @@ class Filter:
|
|||
self.stop_at_ratio = conf['stop_at_ratio']
|
||||
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
"feeds": {},
|
||||
"filters": {},
|
||||
"updatetime": 15,
|
||||
"history": []
|
||||
}
|
||||
class Timer:
|
||||
def Timer(self, curr_time, timeout, callback, data):
|
||||
self.timeout = curr_time + timeout
|
||||
"""Timeout is specified in seconds, since it is used by the update() method"""
|
||||
self.callback = callback
|
||||
self.data = data
|
||||
|
||||
def check_timeout(self, curr_time):
|
||||
return curr_time == self.timeout
|
||||
|
||||
def execute(self):
|
||||
self.callback(data)
|
||||
|
||||
|
||||
class Core(CorePluginBase):
|
||||
|
||||
|
||||
|
||||
"""=============enable/disable functions============="""
|
||||
|
||||
def enable(self):
|
||||
#initiate variables
|
||||
self.config = deluge.configmanager.ConfigManager("feeder.conf", DEFAULT_PREFS)
|
||||
self.feeds = {}
|
||||
self.timers = {}
|
||||
self.history = self.config['history']
|
||||
self.time = 0
|
||||
|
||||
# Setting default timer to configured update time
|
||||
for feed in self.config['feeds']:
|
||||
self.timers[feed] = gobject.timeout_add(
|
||||
self.config['feeds'][feed].updatetime * 60 * 1000,
|
||||
self.timers[feed] = Timer( self,time,
|
||||
self.config['feeds'][feed].updatetime * 60,
|
||||
self.update_feed, feed )
|
||||
|
||||
# update all feeds on startup
|
||||
self.update_feeds()
|
||||
|
||||
|
||||
def disable(self):
|
||||
self.config['history'] = self.history
|
||||
self.config.save()
|
||||
|
||||
|
||||
def update(self):
|
||||
self.time += 1
|
||||
for timer in self.timers:
|
||||
if timer.check_timeout(time):
|
||||
timer.execute()
|
||||
|
||||
"""=============Internal functions============="""
|
||||
|
||||
|
||||
#=================Exported functions==================
|
||||
|
||||
@export
|
||||
def set_config(self, config):
|
||||
"""sets the config dictionary"""
|
||||
for key in config.keys():
|
||||
self.config[key] = config[key]
|
||||
self.config.save()
|
||||
|
||||
####################Configuration Getters##################
|
||||
|
||||
@export
|
||||
def get_config(self):
|
||||
"""returns the config dictionary"""
|
||||
return self.config.config
|
||||
|
||||
@export
|
||||
def get_feed_config(self, feedname):
|
||||
"""Returns configuration for a feed"""
|
||||
return self.config['feeds'][feedname].get_config()
|
||||
|
||||
@export
|
||||
def get_filter_config(self, filtername):
|
||||
"""Returns a configuration for a filter"""
|
||||
return self.config['filters'][filtername].get_config()
|
||||
|
||||
####################Information Getters####################
|
||||
|
||||
@export
|
||||
def get_feeds(self):
|
||||
"""Returns a list of the configured feeds"""
|
||||
feeds = []
|
||||
for feedname in self.config['feeds']:
|
||||
feeds.append(feedname)
|
||||
feeds.sort(key=string.lower)
|
||||
return feeds
|
||||
|
||||
@export
|
||||
def get_filters(self):
|
||||
"""Returns a list of all available filters"""
|
||||
filters = []
|
||||
for filter in self.config['filters']:
|
||||
filters.append(filter)
|
||||
filters.sort(key=string.lower)
|
||||
return filters
|
||||
|
||||
@export
|
||||
def get_items(self, feedname):
|
||||
"""Returns a dictionary with feedname:link"""
|
||||
try:
|
||||
items = {}
|
||||
feed = self.feeds[feedname]
|
||||
for entry in feed['entries']:
|
||||
items[entry.title] = entry.link
|
||||
except Exception, e:
|
||||
items = {}
|
||||
log.warning("Feed '%s' not loaded", feedname)
|
||||
return items
|
||||
|
||||
@export
|
||||
def test_filter(self, regex):
|
||||
filters = { "to_test":Filter() }
|
||||
conf = filters["to_test"].get_config()
|
||||
conf["regex"] = regex
|
||||
filters["to_test"].set_config(conf)
|
||||
hits = {}
|
||||
for feed in self.feeds:
|
||||
hits.update(self.run_filters(feed, filters, test=True))
|
||||
return hits
|
||||
|
||||
@export
|
||||
def add_feed(self, config):
|
||||
"""adds/updates a feed and, for whatever reason, sets the default timeout"""
|
||||
|
||||
# save the feedname and remove it from the config
|
||||
feedname = config['name']
|
||||
del config['name']
|
||||
|
||||
# check if the feed already exists and save config
|
||||
try:
|
||||
conf = self.config['feeds'][feedname].get_config()
|
||||
del self.config['feeds'][feedname]
|
||||
except Exception, e:
|
||||
conf = {}
|
||||
|
||||
# update configuration
|
||||
for var in config:
|
||||
conf[var] = config[var]
|
||||
|
||||
# save as default update time
|
||||
try:
|
||||
self.config['updatetime'] = config['updatetime']
|
||||
except Exception, e:
|
||||
log.warning("updatetime not set when adding feed %s", feedname)
|
||||
|
||||
# Create the new feed
|
||||
newfeed = Feed()
|
||||
newfeed.set_config(conf)
|
||||
|
||||
# Add a timer (with default timer for now, since we can't get ttl just yet)...
|
||||
self.timers[feedname] = Timer( self.time,
|
||||
newfeed.updatetime * 60,
|
||||
self.update_feed, feedname )
|
||||
|
||||
# Save the new feed
|
||||
self.config['feeds'].update({feedname: newfeed })
|
||||
self.config.save()
|
||||
|
||||
# And update the new feed
|
||||
self.update_feed(feedname)
|
||||
|
||||
@export
|
||||
def remove_feed(self, feedname):
|
||||
"""Remove a feed"""
|
||||
if self.feeds.has_key(feedname): # Check if we have the feed saved and remove it
|
||||
del self.feeds[feedname]
|
||||
if self.timers.has_key(feedname): # Check if we have a timer for this feed and remove it
|
||||
del self.timers[feedname]
|
||||
if self.config['feeds'].has_key(feedname): # Check if we have the feed in the configuration and remove it
|
||||
del self.config['feeds'][feedname]
|
||||
self.config.save()
|
||||
|
||||
@export
|
||||
def add_filter(self, name):
|
||||
"""Adds a new filter to the configuration"""
|
||||
if not self.config['filters'].has_key(name): # we don't want to add a filter that already exists
|
||||
self.config['filters'][name] = Filter()
|
||||
self.config.save()
|
||||
|
||||
@export
|
||||
def set_filter_config(self, filtername, conf):
|
||||
"""Changes the options for a filter"""
|
||||
oldconf = self.config['filters'][filtername].get_config()
|
||||
for item in conf:
|
||||
oldconf[item] = conf[item]
|
||||
|
||||
self.config['filters'][filtername].set_config(oldconf)
|
||||
self.config.save()
|
||||
for feed in self.config['feeds']: # we would like to check if the filter now matches something new
|
||||
self.run_filters(feed)
|
||||
|
||||
@export
|
||||
def remove_filter(self, name):
|
||||
"""Removes a filter"""
|
||||
if self.config['filters'].has_key(name): # Can't remove a filter that doesn't exists
|
||||
del self.config['filters'][name]
|
||||
self.config.save()
|
||||
|
||||
#=================Internal functions================
|
||||
|
||||
def update_feeds(self):
|
||||
"Start threads to update all feeds"
|
||||
"""Start threads to update all feeds"""
|
||||
for feedname in self.config['feeds']:
|
||||
self.update_feed(feedname)
|
||||
|
||||
|
||||
def update_feed(self, feedname):
|
||||
"Start a thread to update a single feed"
|
||||
"""Start a thread to update a single feed"""
|
||||
threading.Thread(
|
||||
target=self.update_feed_thread,
|
||||
args=(self.on_feed_updated, feedname)).start()
|
||||
|
@ -193,7 +362,7 @@ class Core(CorePluginBase):
|
|||
return True
|
||||
|
||||
def update_feed_thread(self, callback, feedname):
|
||||
"updates a feed"
|
||||
"""updates a feed"""
|
||||
feed = self.config['feeds'][feedname]
|
||||
try:
|
||||
self.feeds[feedname] = feedparser.parse(feed.url)
|
||||
|
@ -203,7 +372,7 @@ class Core(CorePluginBase):
|
|||
callback(feedname)
|
||||
|
||||
def on_feed_updated(self, feedname):
|
||||
"Run stuff when a feed has been updated"
|
||||
"""Run stuff when a feed has been updated"""
|
||||
|
||||
# Not all feeds contain a ttl value, but if it does
|
||||
# we would like to obey it
|
||||
|
@ -212,8 +381,8 @@ class Core(CorePluginBase):
|
|||
log.debug("feed '%s' request a ttl of %s, updating timer", feedname, self.feeds[feedname].ttl)
|
||||
self.config['feeds'][feedname].updatetime = self.feeds[feedname].ttl
|
||||
del self.timers[feedname]
|
||||
self.timers[feedname] = gobject.timeout_add(
|
||||
self.config['feeds'][feedname].updatetime * 60 * 1000,
|
||||
self.timers[feedname] = Timer( self.time,
|
||||
self.config['feeds'][feedname].updatetime * 60 * 1000,
|
||||
self.update_feed, feedname )
|
||||
except Exception, e:
|
||||
log.debug("feed '%s' has no ttl set, will use default timer", feedname)
|
||||
|
@ -222,7 +391,7 @@ class Core(CorePluginBase):
|
|||
self.run_filters(feedname)
|
||||
|
||||
def run_filters(self, feedname, filters={}, test=False):
|
||||
"Test all available filters on the given feed"
|
||||
"""Test all available filters on the given feed"""
|
||||
if not filters:
|
||||
filters = self.config['filters']
|
||||
log.debug("will test filters %s", filters)
|
||||
|
@ -241,7 +410,7 @@ class Core(CorePluginBase):
|
|||
if filters[filter].regex == "": # we don't want a empty regex...
|
||||
log.warning("Filter '%s' has not been configured, ignoring!", filter)
|
||||
continue
|
||||
|
||||
|
||||
# if the filter isn't supposed to be run on this feed we don't want to run it...
|
||||
# if filter.all_feeds or self.config['filters'][filter].feeds.has_element(feedname) : # ...apparently has_element doesn't work on arrays... TODO
|
||||
if self.test_filter(entry, filters[filter].regex):
|
||||
|
@ -271,8 +440,8 @@ class Core(CorePluginBase):
|
|||
|
||||
|
||||
def test_filter(self, entry, filter):
|
||||
"Tests a filter to a given rss entry"
|
||||
f = re.compile(filter, re.IGNORECASE)
|
||||
"""Tests a filter to a given rss entry"""
|
||||
f = re.compile(filter, re.IGNORECASE)
|
||||
if f.search(entry.title) or f.search(entry.link):
|
||||
log.debug("RSS item '%s' matches filter '%s'", entry.title, filter)
|
||||
return True
|
||||
|
@ -281,139 +450,4 @@ class Core(CorePluginBase):
|
|||
|
||||
def add_torrent(self, url, torrent_options):
|
||||
log.debug("Attempting to add torrent %s", url)
|
||||
client.add_torrent_url(url, torrent_options)
|
||||
|
||||
"""=============Export functions============="""
|
||||
|
||||
"""#############Configuration Setters#############"""
|
||||
|
||||
def export_add_feed(self, config):
|
||||
"adds/updates a feed and, for whatever reason, sets the default timeout"
|
||||
|
||||
# save the feedname and remove it from the config
|
||||
feedname = config['name']
|
||||
del config['name']
|
||||
|
||||
# check if the feed already exists and save config
|
||||
try:
|
||||
conf = self.config['feeds'][feedname].get_config()
|
||||
del self.config['feeds'][feedname]
|
||||
except Exception, e:
|
||||
conf = {}
|
||||
|
||||
# update configuration
|
||||
for var in config:
|
||||
conf[var] = config[var]
|
||||
|
||||
# save as default update time
|
||||
try:
|
||||
self.config['updatetime'] = config['updatetime']
|
||||
except Exception, e:
|
||||
log.warning("updatetime not set when adding feed %s", feedname)
|
||||
|
||||
# Create the new feed
|
||||
newfeed = Feed()
|
||||
newfeed.set_config(conf)
|
||||
|
||||
# Add a timer (with default timer for now, since we can't get ttl just yet)...
|
||||
self.timers[feedname] = gobject.timeout_add(
|
||||
newfeed.updatetime * 60 * 1000,
|
||||
self.update_feed, feedname )
|
||||
|
||||
# Save the new feed
|
||||
self.config['feeds'].update({feedname: newfeed })
|
||||
self.config.save()
|
||||
|
||||
# And update the new feed
|
||||
self.update_feed(feedname)
|
||||
|
||||
def export_remove_feed(self, feedname):
|
||||
"Remove a feed"
|
||||
if self.feeds.has_key(feedname): # Check if we have the feed saved and remove it
|
||||
del self.feeds[feedname]
|
||||
if self.timers.has_key(feedname): # Check if we have a timer for this feed and remove it
|
||||
del self.timers[feedname]
|
||||
if self.config['feeds'].has_key(feedname): # Check if we have the feed in the configuration and remove it
|
||||
del self.config['feeds'][feedname]
|
||||
self.config.save()
|
||||
|
||||
def export_add_filter(self, name):
|
||||
"Adds a new filter to the configuration"
|
||||
if not self.config['filters'].has_key(name): # we don't want to add a filter that already exists
|
||||
self.config['filters'][name] = Filter()
|
||||
self.config.save()
|
||||
|
||||
def export_set_filter_config(self, filtername, conf):
|
||||
"Changes the options for a filter"
|
||||
oldconf = self.config['filters'][filtername].get_config()
|
||||
for item in conf:
|
||||
oldconf[item] = conf[item]
|
||||
|
||||
self.config['filters'][filtername].set_config(oldconf)
|
||||
self.config.save()
|
||||
for feed in self.config['feeds']: # we would like to check if the filter now matches something new
|
||||
self.run_filters(feed)
|
||||
|
||||
def export_remove_filter(self, name):
|
||||
"Removes a filter"
|
||||
if self.config['filters'].has_key(name): # Can't remove a filter that doesn't exists
|
||||
del self.config['filters'][name]
|
||||
self.config.save()
|
||||
|
||||
|
||||
|
||||
"""#############Configuration Getters#############"""
|
||||
|
||||
def export_get_config(self):
|
||||
"returns the config dictionary"
|
||||
return self.config.config
|
||||
|
||||
|
||||
def export_get_feed_config(self, feedname):
|
||||
"Returns configuration for a feed"
|
||||
return self.config['feeds'][feedname].get_config()
|
||||
|
||||
def export_get_filter_config(self, filtername):
|
||||
"Returns a configuration for a filter"
|
||||
return self.config['filters'][filtername].get_config()
|
||||
|
||||
|
||||
"""#############Information Getters#############"""
|
||||
|
||||
def export_get_feeds(self):
|
||||
"Returns a list of the configured feeds"
|
||||
feeds = []
|
||||
for feedname in self.config['feeds']:
|
||||
feeds.append(feedname)
|
||||
feeds.sort(key=string.lower)
|
||||
return feeds
|
||||
|
||||
def export_get_filters(self):
|
||||
"Returns a list of all available filters"
|
||||
filters = []
|
||||
for filter in self.config['filters']:
|
||||
filters.append(filter)
|
||||
filters.sort(key=string.lower)
|
||||
return filters
|
||||
|
||||
def export_get_items(self, feedname):
|
||||
"Returns a dictionary with feedname:link"
|
||||
try:
|
||||
items = {}
|
||||
feed = self.feeds[feedname]
|
||||
for entry in feed['entries']:
|
||||
items[entry.title] = entry.link
|
||||
except Exception, e:
|
||||
items = {}
|
||||
log.warning("Feed '%s' not loaded", feedname)
|
||||
return items
|
||||
|
||||
def export_test_filter(self, regex):
|
||||
filters = { "to_test":Filter() }
|
||||
conf = filters["to_test"].get_config()
|
||||
conf["regex"] = regex
|
||||
filters["to_test"].set_config(conf)
|
||||
hits = {}
|
||||
for feed in self.feeds:
|
||||
hits.update(self.run_filters(feed, filters, test=True))
|
||||
return hits
|
||||
component.get("Core").add_torrent_url(url, torrent_options)
|
||||
|
|
Loading…
Reference in New Issue