Apply patch from David Mohr to make core.py more 1.2 compatible

This commit is contained in:
Andrew Resch 2009-09-02 22:36:34 +00:00
parent a6ab62f7ce
commit 4e3f4128fa
1 changed files with 219 additions and 185 deletions

View File

@ -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.
#
@ -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 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']
@ -88,7 +99,7 @@ class Filter:
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
@ -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,7 +381,7 @@ 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.timers[feedname] = Timer( self.time,
self.config['feeds'][feedname].updatetime * 60 * 1000,
self.update_feed, feedname )
except Exception, e:
@ -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)
@ -271,7 +440,7 @@ class Core(CorePluginBase):
def test_filter(self, entry, filter):
"Tests a filter to a given rss entry"
"""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)
@ -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)