def gtk_treeview_search_cb_stristr(model, column, key, iter, data=None): value = model.get_value(iter, column) if value.lower().find(key.lower()) > -1: return False else: return True class plugin_FlexRSS_Config: constants = { 'Generic' : 0, 'TV Show' : 1, 'TV Show (dated)' : 2 } feeds_counter = 0 filters_counter = 0 feeds = None filters = None version = 0 show_toolbar_button = False threaded_retrieval = False def getFilter(self, id): if not self.filters: return None for filter in self.filters: if filter['id'] == id: return filter return None def setFilter(self, id, key, value): filter = self.getFilter(id) if not filter: return False else: filter[key] = value return True def addFilter(self, name, type, patterns, feeds): id = self.feeds_counter + 1 self.feeds_counter = id if not self.filters: self.filters = [] filter = { "id" : id, "name" : name, "type" : type, "patterns" : patterns, "feeds" : feeds, "history" : {}, "path" : None, "enabled" : True, "queue_top": False, "pause" : False, "delete" : False} self.filters.append(filter) return id def deleteFilter(self, id): if not self.filters: return False i = 0 while i < len(self.filters): if self.filters[i]['id'] == id: del self.filters[i] return True i = i + 1 def checkHistory(self, id, type, data): filter = self.getFilter(id) if not filter: return False try: if type == self.constants['TV Show']: filter['history'][type][data['series']].index(data['episode']) return True elif type == self.constants['TV Show (dated)']: filter['history'][type][data['year']][data['month']].index(data['day']) return True else: filter['history'][type].index(data['url']) return True except: return False def checkRange(self, id, type, data): filter = self.getFilter(id) if not filter: return False if type == self.constants['TV Show']: if filter['history'][type].has_key('from'): if data['series'] < filter['history'][type]['from']['season']: return False elif data['series'] == filter['history'][type]['from']['season']: if data['episode'] < filter['history'][type]['from']['episode']: return False if filter['history'][type].has_key('thru'): if data['series'] > filter['history'][type]['thru']['season']: return False elif data['series'] == filter['history'][type]['thru']['season']: if data['episode'] > filter['history'][type]['thru']['episode']: return False return True elif type == self.constants['TV Show (dated)']: if filter['history'][type].has_key('from'): if data['year'] < filter['history'][type]['from']['year']: return False elif data['year'] == filter['history'][type]['from']['year']: if data['month'] < filter['history'][type]['from']['month']: return False elif data['month'] == filter['history'][type]['from']['month']: if data['day'] < filter['history'][type]['from']['day']: return False if filter['history'][type].has_key('thru'): if data['year'] > filter['history'][type]['thru']['year']: return False elif data['year'] == filter['history'][type]['thru']['year']: if data['month'] > filter['history'][type]['thru']['month']: return False elif data['month'] == filter['history'][type]['thru']['month']: if data['day'] > filter['history'][type]['thru']['day']: return False return True else: return True def addHistory(self, id, type, data): filter = self.getFilter(id) if not filter: return False if type == self.constants['TV Show']: if not filter['history'].has_key(type): filter['history'][type] = {} if not filter['history'][type].has_key(data['series']): filter['history'][type][data['series']] = [] filter['history'][type][data['series']].append(data['episode']) elif type == self.constants['TV Show (dated)']: if not filter['history'].has_key(type): filter['history'][type] = {} if not filter['history'][type].has_key(data['year']): filter['history'][type][data['year']] = {} if not filter['history'][type][data['year']].has_key(data['month']): filter['history'][type][data['year']][data['month']] = [] filter['history'][type][data['year']][data['month']].append(data['day']) else: if not filter['history'].has_key(type): filter['history'][type] = [] try: filter['history'][type].append(data['url']) except AttributeError, e: filter['history'][type] = [data['url']] def getFeed(self, id): if not self.feeds: return None for feed in self.feeds: if feed['id'] == id: return feed return None def setFeed(self, id, key, value): feed = self.getFeed(id) if not feed: return False else: feed[key] = value return True def addFeed(self, name, url, interval): # Uhhh... no ++? WTF is the increment operator? id = self.feeds_counter + 1 self.feeds_counter = id if not self.feeds: self.feeds = [] self.feeds.append({ "id" : id, "name" : name, "url" : url, "interval" : interval, "enabled" : True }) return id def deleteFeed(self, id): if not self.feeds: return False i = 0 while i < len(self.feeds): if self.feeds[i]['id'] == id: del self.feeds[i] return True i = i + 1 class plugin_FlexRSS: config = None glade = None feeds = None toolbar_button = None history_calendarbuttons = None def update_config(self): if self.config.version >= 5: return if self.config.version < 1: print 'Updating config to v1' i = 0 while i < len(self.config.filters): self.config.filters[i]['enabled'] = True i = i + 1 if self.config.version < 2: print 'Updating config to v2' i = 0 while i < len(self.config.feeds): self.config.feeds[i]['enabled'] = True i = i + 1 if self.config.version < 3: print 'Updating config to v3' i = 0 while i < len(self.config.filters): type_s = self.config.filters[i]['type'] type_i = self.config.constants[type_s] if self.config.filters[i]['history'].has_key(type_s): history = { type_i: self.config.filters[i]['history'][type_s] } self.config.filters[i]['history'] = history self.config.filters[i]['type'] = self.config.constants[self.config.filters[i]['type']]; i = i + 1 if self.config.version < 4: print 'Updating config to v4' i = 0 while i < len(self.config.filters): self.config.filters[i]['queue_top'] = False self.config.filters[i]['pause'] = False i = i + 1 if self.config.version < 5: print 'Updating config to v5' i = 0 while i < len(self.config.filters): self.config.filters[i]['delete'] = False i = i + 1 self.config.version = 5 self.write_config() def load_config(self): import deluge.common, os, cookielib file = deluge.common.CONFIG_DIR + "/flexrss.dat" if os.path.isfile(file): import pickle fd = open(file, 'r') self.config = pickle.load(fd) fd.close() else: self.config = plugin_FlexRSS_Config() self.config.version = 5 self.update_config() cookie_file = deluge.common.CONFIG_DIR + "/flexrss-cookies.txt" self.cookies = cookielib.MozillaCookieJar() if os.path.isfile(cookie_file): self.cookies.load(cookie_file) def write_config(self, write_cookies=False): import deluge.common, os, pickle file = deluge.common.CONFIG_DIR + "/flexrss.dat" fd = open(file, 'w') pickle.dump(self.config, fd) fd.close() if write_cookies: print "Saving cookies." self.cookies.save(deluge.common.CONFIG_DIR + "/flexrss-cookies.txt") def configure_cb_closed(self, args): self.glade = None self.history_calendarbuttons = None def configure_cb_feed_new(self, args): feed = { "name" : 'Untitled', "url" : 'http://', "interval" : 900, "id" : 0 } feed["id"] = self.config.addFeed(feed["name"], feed["url"], feed["interval"]) view = self.glade.get_widget("FlexRSS_Feeds") model = view.get_model() view.get_selection().select_iter(model.append(None, (feed["id"], feed["name"], feed["url"]))) def configure_cb_feed_selected(self, selection): model, iter = selection.get_selected() if not iter: return parent = model.iter_parent(iter) if parent: # Selected a filter self.glade.get_widget('FlexRSS_Filters_Test_Pattern').set_text(model.get_value(iter, 1)) self.configure_cb_test_filter(None) iter = parent # We want to edit a feed. feed = self.config.getFeed(model.get_value(iter, 0)) if not feed: print 'Error: could not find feed #' + str(model.get_value(iter, 0)) return self.glade.get_widget("FlexRSS_EditFeed_Name").set_text(feed["name"]) self.glade.get_widget("FlexRSS_EditFeed_URL").set_text(feed["url"]) self.glade.get_widget("FlexRSS_EditFeed_Interval").set_text(str(feed["interval"])) if feed["enabled"] == True: self.glade.get_widget("FlexRSS_EditFeed_Status_Enabled").set_active(True) else: self.glade.get_widget("FlexRSS_EditFeed_Status_Disabled").set_active(True) self.glade.get_widget('FlexRSS_Feeds_Editor').show() def configure_cb_feed_delete(self, arg, id=None): if not id: # Which feed is selected? selection = self.glade.get_widget("FlexRSS_Feeds").get_selection() model, iter = selection.get_selected() if not iter: return id = model.get_value(iter, 0) if id == 0: id = model.get_value(model.iter_parent(iter), 0) else: model = self.glade.get_widget("FlexRSS_Feeds").get_model() iter = model.get_iter_first() while iter: if model.get_value(iter, 0) == id: break iter = model.iter_next(iter) if not iter: print 'Couldn\'t find feed.' return # Remove from config if not self.config.deleteFeed(id): print 'Unable to delete feed #' + str(id) return # Remove from UI model.remove(iter) self.write_config() # We are no longer editing a feed, so hide the editing widgets. self.glade.get_widget('FlexRSS_Feeds_Editor').hide() def configure_cb_feed_save(self, arg, id=None): if not id: # Which feed is selected? selection = self.glade.get_widget("FlexRSS_Feeds").get_selection() model, iter = selection.get_selected() if not iter: return id = model.get_value(iter, 0) if id == 0: iter = model.iter_parent(iter) id = model.get_value(iter, 0) else: model = self.glade.get_widget("FlexRSS_Feeds").get_model() iter = model.iter_first() while iter: if model.get_value(iter, 0) == id: break iter = iter.iter_next(iter) if not iter: print 'Couldn\'t find feed.' return # Update configuration self.config.setFeed(id, "name", self.glade.get_widget("FlexRSS_EditFeed_Name").get_text()) self.config.setFeed(id, "url", self.glade.get_widget("FlexRSS_EditFeed_URL").get_text()) interval = self.configure_ui_get_text_as_int("FlexRSS_EditFeed_Interval", 900) if interval < 300: # It's just not polite to hit a server that often. self.glade.get_widget("FlexRSS_EditFeed_Interval").set_text('300') interval = 300 self.config.setFeed(id, "interval", interval) self.config.setFeed(id, "enabled", self.glade.get_widget("FlexRSS_EditFeed_Status_Enabled").get_active()) self.write_config() # Update UI feed = self.config.getFeed(id) model.set_value(iter, 0, feed["id"]) model.set_value(iter, 1, feed["name"]) model.set_value(iter, 2, feed["url"]) if not self.feeds.has_key(id): self.feeds[id] = { 'cfg' : feed, 'updated' : 0, 'data' : [] } def escape_regex_special_chars(self, pattern): escape_chars = '[]()^$\\.?*+|' out = [] for c in pattern: try: escape_chars.index(c) out.append('\\' + c) except: out.append(c) return ''.join(out) def configure_cb_filter_new(self, arg, test_pattern=None): filter = { "name" : "Untitled", "type" : "Generic", "patterns" : [('', 'Title')], "feeds" : [0], "id" : 0 } if test_pattern: # Try to guess a good pattern import re, string trans_table = string.maketrans(' ', '.') # TV Show exp = re.compile(r'(.*?)S([0-9]+)E([0-9]+)', re.IGNORECASE) match = exp.match(test_pattern) if match: pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + 's%se%e' filter['patterns'][0] = (pattern, 'Title') filter['name'] = match.group(1) filter['type'] = self.config.constants['TV Show'] if not match: exp = re.compile(r'(.*?)([0-9]{4}).([0-9]{1,2}).([0-9]{1,2})', re.IGNORECASE) match = exp.match(test_pattern) if match: pattern = None if ((int(match.group(3)) <= 12) and (int(match.group(4)) <= 31)): pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%Y.%m.%d' elif ((int(match.group(3)) <= 31) and (int(match.group(4)) <= 12)): pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%Y.%d.%m' if pattern: filter['patterns'][0] = (pattern, 'Title') filter['name'] = match.group(1) filter['type'] = self.config.constants['TV Show (dated)'] else: match = None if not match: exp = re.compile(r'(.*?)([0-9]{2}).([0-9]{2}).([0-9]{2})', re.IGNORECASE) match = exp.match(test_pattern) if match: pattern = None if ((int(match.group(2)) <= 12) and (int(match.group(3)) <= 31)): pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%m.%d.%y' elif ((int(match.group(3)) <= 31) and (int(match.group(2)) <= 12)): pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%d.%m.%y' if pattern: filter['patterns'][0] = (pattern, 'Title') filter['name'] = match.group(1) filter['type'] = self.config.constants['TV Show (dated)'] else: match = None if not match: exp = re.compile(r'(.*?)([0-9]+)([x\.\-_]{1})([0-9]+)', re.IGNORECASE) match = exp.match(test_pattern) if match: pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%s' + self.escape_regex_special_chars(match.group(3)) + '%e' filter['patterns'][0] = (pattern, 'Title') filter['name'] = match.group(1) filter['type'] = self.config.constants['TV Show'] if not match: exp = re.compile(r'(.*?)([0-9]+)$', re.IGNORECASE) match = exp.match(test_pattern) if match: pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%e' filter['patterns'][0] = (pattern, 'Title') filter['name'] = match.group(1) filter['type'] = self.config.constants['TV Show'] # Add to config filter['id'] = self.config.addFilter(filter['name'], filter['type'], filter['patterns'], [0]) # Add to UI self.configure_ui_add_filter(self.config.getFilter(filter['id']), test_pattern) def configure_cb_filter_selected(self, selection): model, iter = selection.get_selected() if not iter: return # We want to edit a filter. filter = self.config.getFilter(model.get_value(iter, 0)) if not filter: print 'Error: could not find filter #' + str(model.get_value(iter, 0)) return self.configure_ui_reset_filter() self.glade.get_widget('FlexRSS_Filters_Name').set_text(filter['name']) if filter['type'] == self.config.constants['TV Show']: type_i = 1 elif filter['type'] == self.config.constants['TV Show (dated)']: type_i = 2 else: type_i = 0 self.glade.get_widget('FlexRSS_Filters_Type').set_active(type_i) selection = self.glade.get_widget('FlexRSS_Filters_Feed').get_selection() selection.unselect_all() feed_model = self.glade.get_widget('FlexRSS_Filters_Feed').get_model() for i in filter['feeds']: if i == 0: selection.select_all() else: iter = feed_model.get_iter_first() while iter: if feed_model.get_value(iter, 0) == i: selection.select_iter(iter) iter = feed_model.iter_next(iter) for pattern in filter['patterns']: self.configure_ui_add_pattern(pattern) if filter['type'] == self.config.constants['TV Show']: if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('from'): self.glade.get_widget('FlexRSS_History_TVShow_From_Enabled').set_active(True) self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_sensitive(True) self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_sensitive(True) self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_text(str(filter['history'][filter['type']]['from']['season'])) self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_text(str(filter['history'][filter['type']]['from']['episode'])) else: self.glade.get_widget('FlexRSS_History_TVShow_From_Enabled').set_active(False) self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_sensitive(False) self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_sensitive(False) self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_text('0') self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_text('0') if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('thru'): self.glade.get_widget('FlexRSS_History_TVShow_Thru_Enabled').set_active(True) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_sensitive(True) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_sensitive(True) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_text(str(filter['history'][filter['type']]['thru']['season'])) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_text(str(filter['history'][filter['type']]['thru']['episode'])) else: self.glade.get_widget('FlexRSS_History_TVShow_Thru_Enabled').set_active(False) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_sensitive(False) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_sensitive(False) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_text('0') self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_text('0') self.glade.get_widget("FlexRSS_History_TVShow_Dated").hide() self.glade.get_widget("FlexRSS_History_TVShow").show() self.glade.get_widget("FlexRSS_Filter_History_Range").show() elif filter['type'] == self.config.constants['TV Show (dated)']: import time cal_from, cal_thru = self.history_calendarbuttons today = time.localtime() if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('from'): self.glade.get_widget('FlexRSS_History_TVShow_Dated_From_Enabled').set_active(True) cal_from.set_sensitive(True) cal_from.set_date(filter['history'][filter['type']]['from']['year'], filter['history'][filter['type']]['from']['month'], filter['history'][filter['type']]['from']['day']) else: self.glade.get_widget('FlexRSS_History_TVShow_Dated_From_Enabled').set_active(False) cal_from.set_sensitive(False) cal_from.set_date(today[0], today[1], today[2]) if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('thru'): self.glade.get_widget('FlexRSS_History_TVShow_Dated_Thru_Enabled').set_active(True) cal_thru.set_sensitive(True) cal_thru.set_date(filter['history'][filter['type']]['thru']['year'], filter['history'][filter['type']]['thru']['month'], filter['history'][filter['type']]['thru']['day']) else: self.glade.get_widget('FlexRSS_History_TVShow_Dated_Thru_Enabled').set_active(False) cal_thru.set_sensitive(False) cal_thru.set_date(today[0], today[1], today[2]) self.glade.get_widget("FlexRSS_History_TVShow").hide() self.glade.get_widget("FlexRSS_History_TVShow_Dated").show() self.glade.get_widget("FlexRSS_Filter_History_Range").show() else: self.glade.get_widget("FlexRSS_History_TVShow").hide() self.glade.get_widget("FlexRSS_History_TVShow_Dated").hide() self.glade.get_widget("FlexRSS_Filter_History_Range").hide() self.glade.get_widget('FlexRSS_Filter_Download_QueueTop').set_active(filter.get('queue_top', False)) self.glade.get_widget('FlexRSS_Filter_Download_Pause').set_active(filter.get('pause', False)) self.glade.get_widget('FlexRSS_Filter_Download_Delete').set_active(filter.get('delete', False)) self.configure_cb_test_filter(None) if filter['path'] != None: self.glade.get_widget('FlexRSS_Filter_Output_Location').set_current_folder(filter['path']) self.glade.get_widget('FlexRSS_Filter_Output_Type_Custom').set_active(True) else: self.glade.get_widget('FlexRSS_Filter_Output_Type_Default').set_active(True) replace = filter.get('replace', {'pattern': '', 'with': ''}) self.glade.get_widget('FlexRSS_Filter_Rewrite_Pattern').set_text(replace['pattern']) self.glade.get_widget('FlexRSS_Filter_Rewrite_Replacement').set_text(replace['with']) def configure_cb_filter_history_toggle(self, box): name = box.get_name() active = box.get_active() if name == 'FlexRSS_History_TVShow_From_Enabled': self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_sensitive(active) self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_sensitive(active) elif name == 'FlexRSS_History_TVShow_Thru_Enabled': self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_sensitive(active) self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_sensitive(active) elif name == 'FlexRSS_History_TVShow_Dated_From_Enabled': self.history_calendarbuttons[0].set_sensitive(active) elif name == 'FlexRSS_History_TVShow_Dated_Thru_Enabled': self.history_calendarbuttons[1].set_sensitive(active) self.configure_cb_test_filter(None) def configure_ui_get_text_as_int(self, widget_name, default=0): try: return int(self.glade.get_widget(widget_name).get_text()) except: return default def configure_ui_get_history_restriction(self): h_from = None h_thru = None type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() if type == 1: type_s = self.config.constants['TV Show'] elif type == 2: type_s = self.config.constants['TV Show (dated)'] else: type_s = self.config.constants['Generic'] if type_s == self.config.constants['TV Show']: if self.glade.get_widget('FlexRSS_History_TVShow_From_Enabled').get_active(): from_season = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_From_Season') from_episode = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_From_Episode') h_from = {'season': from_season, 'episode': from_episode} elif type_s == self.config.constants['TV Show (dated)']: if self.glade.get_widget('FlexRSS_History_TVShow_Dated_From_Enabled').get_active(): from_y, from_m, from_d = self.history_calendarbuttons[0].get_date() h_from = {'year': from_y, 'month': from_m, 'day': from_d} if type_s == self.config.constants['TV Show']: if self.glade.get_widget('FlexRSS_History_TVShow_Thru_Enabled').get_active(): thru_season = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_Thru_Season') thru_episode = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_Thru_Episode') h_thru = {'season': thru_season, 'episode': thru_episode} elif type_s == self.config.constants['TV Show (dated)']: if self.glade.get_widget('FlexRSS_History_TVShow_Dated_Thru_Enabled').get_active(): thru_y, thru_m, thru_d = self.history_calendarbuttons[1].get_date() h_thru = {'year': thru_y, 'month': thru_m, 'day': thru_d} return (h_from, h_thru) def configure_cb_filter_save(self, arg): # Which feed is selected? selection = self.glade.get_widget("FlexRSS_Filters_List").get_selection() model, iter = selection.get_selected() if not iter: return id = model.get_value(iter, 0) name = self.glade.get_widget('FlexRSS_Filters_Name').get_text() self.config.setFilter(id, 'name', name) iter = model.get_iter_first() while iter: if model.get_value(iter, 0) == id: model.set_value(iter, 1, name) iter = model.iter_next(iter) type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() if type == 1: type_s = self.config.constants['TV Show'] elif type == 2: type_s = self.config.constants['TV Show (dated)'] else: type_s = self.config.constants['Generic'] self.config.setFilter(id, 'type', type_s) model, paths = self.glade.get_widget('FlexRSS_Filters_Feed').get_selection().get_selected_rows() feeds = [] for path in paths: feeds.append(model.get_value(model.get_iter(path), 0)) if len(feeds) == 0: feeds.append(0) self.config.setFilter(id, 'feeds', feeds) patterns = [] filter_patterns = self.glade.get_widget('FlexRSS_Filter_Patterns_List') for i in filter_patterns.get_children(): data = i.get_children() pattern = data[0].get_text() if data[2].get_active() == 1: type = 'Link' else: type = 'Title' patterns.append((pattern, type)) self.config.setFilter(id, 'patterns', patterns) if self.glade.get_widget('FlexRSS_Filter_Output_Type_Custom').get_active(): path = self.glade.get_widget('FlexRSS_Filter_Output_Location').get_current_folder() else: path = None self.config.setFilter(id, 'path', path) self.config.setFilter(id, 'queue_top', self.glade.get_widget('FlexRSS_Filter_Download_QueueTop').get_active()) self.config.setFilter(id, 'pause', self.glade.get_widget('FlexRSS_Filter_Download_Pause').get_active()) self.config.setFilter(id, 'delete', self.glade.get_widget('FlexRSS_Filter_Download_Delete').get_active()) filter = self.config.getFilter(id) h_from, h_thru = self.configure_ui_get_history_restriction() if filter['type'] != self.config.constants['Generic']: if not filter['history'].has_key(filter['type']): filter['history'][filter['type']] = {} if h_from != None: filter['history'][filter['type']]['from'] = h_from else: if filter['history'][filter['type']].has_key('from'): del filter['history'][filter['type']]['from'] if h_thru != None: filter['history'][filter['type']]['thru'] = h_thru else: if filter['history'][filter['type']].has_key('thru'): del filter['history'][filter['type']]['thru'] filter['replace'] = { 'pattern': self.glade.get_widget('FlexRSS_Filter_Rewrite_Pattern').get_text(), 'with' : self.glade.get_widget('FlexRSS_Filter_Rewrite_Replacement').get_text() } self.write_config() def configure_cb_remove_pattern(self, arg): arg.get_parent().destroy() def configure_ui_add_pattern(self, pattern): import gtk, gobject filter_patterns = self.glade.get_widget('FlexRSS_Filter_Patterns_List') hbox = gtk.HBox() filter_patterns.pack_start(hbox) input = gtk.Entry() input.set_text(pattern[0]) input.connect("changed", self.configure_cb_test_filter) on = gtk.Label() on.set_text('On') on.show() combo = gtk.combo_box_new_text() combo.append_text('Title') combo.append_text('Link') if pattern[1] == 'Link': combo.set_active(1) else: combo.set_active(0) remove = gtk.Button(stock=gtk.STOCK_REMOVE) remove.connect("pressed", self.configure_cb_remove_pattern) hbox.pack_start(input) hbox.pack_start(on, expand=False) hbox.pack_start(combo, expand=False) hbox.pack_start(remove, expand=False) hbox.show_all() def configure_cb_add_pattern(self, args): self.configure_ui_add_pattern(('', 'Title')) def configure_ui_add_filter(self, filter, test_pattern=None): if not filter: print 'No filter to add' return None self.configure_ui_reset_filter() model = self.glade.get_widget("FlexRSS_Filters_List").get_model() iter = model.append((filter['id'], filter['name'], filter['enabled'])) if not iter: return view = self.glade.get_widget("FlexRSS_Filters_List") model = view.get_model() view.get_selection().select_iter(iter) if test_pattern: self.glade.get_widget('FlexRSS_Filters_Test_Pattern').set_text(test_pattern) self.configure_cb_test_filter(None) self.glade.get_widget('FlexRSS_MainNotebook').set_current_page(1) def configure_ui_test_result(self, result, h_match=False): if result and h_match: self.glade.get_widget('FlexRSS_Filters_Test_Result').set_text('Match') else: self.glade.get_widget('FlexRSS_Filters_Test_Result').set_text('Doesn\'t match') type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() if type == 0: # Generic self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').hide() self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').hide() self.glade.get_widget('FlexRSS_History_TVShow').hide() self.glade.get_widget('FlexRSS_History_TVShow_Dated').hide() elif type == 1: # TV Show self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').show() self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').hide() self.glade.get_widget('FlexRSS_History_TVShow').show() self.glade.get_widget('FlexRSS_History_TVShow_Dated').hide() if result: self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Series').set_text(str(result['series'])) self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Episode').set_text(str(result['episode'])) else: self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Series').set_text('0') self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Episode').set_text('0') else: # TV Show (dated) self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').hide() self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').show() self.glade.get_widget('FlexRSS_History_TVShow').hide() self.glade.get_widget('FlexRSS_History_TVShow_Dated').show() if result: self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Year').set_text(str(result['year'])) self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Month').set_text(str(result['month'])) self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Day').set_text(str(result['day'])) else: self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Year').set_text('0') self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Month').set_text('0') self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Day').set_text('0') def configure_cb_test_filter(self, source=None, date=None): subject = self.glade.get_widget('FlexRSS_Filters_Test_Pattern').get_text() type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() if type == 1: type_s = self.config.constants['TV Show'] elif type == 2: type_s = self.config.constants['TV Show (dated)'] else: type_s = self.config.constants['Generic'] filter_patterns = self.glade.get_widget('FlexRSS_Filter_Patterns_List') for i in filter_patterns.get_children(): data = i.get_children() pattern = data[0].get_text() result = self.test_pattern(type_s, subject, pattern) if result: # Pattern matched, let's try history restriction. h_from, h_thru = self.configure_ui_get_history_restriction() h_match = self.test_range(type_s, result, h_from, h_thru) self.configure_ui_test_result(result, h_match) return self.configure_ui_test_result(False) def configure_cb_delete_filter(self, arg): # Which filter is selected? selection = self.glade.get_widget("FlexRSS_Filters_List").get_selection() model, iter = selection.get_selected() if not iter: return id = model.get_value(iter, 0) # Remove from config if not self.config.deleteFilter(id): print 'Unable to delete filter #' + str(id) return self.write_config() # Remove from UI model.remove(iter) self.configure_ui_reset_filter() def configure_cb_feed_refresh(self, caller, id=None): if not id: selection = self.glade.get_widget("FlexRSS_Feeds").get_selection() model, iter = selection.get_selected() if not iter: return id = model.get_value(iter, 0) if id: if ( self.config.threaded_retrieval ): import threading threading.Thread(target=self.parse_feed, args=(id,)).start() else: self.parse_feed(id) def configure_cb_download_torrent(self, caller, url): self.download_torrent(url) def configure_cb_feed_popup(self, view, event): if event.button != 3: return model = view.get_model() coords = event.get_coords() path = view.get_path_at_pos(int(coords[0]), int(coords[1])) if path: iter = model.get_iter(path[0]) else: iter = None import gtk popup = gtk.Menu() if iter: id = model.get_value(iter, 0) if id: # Feed item_refresh = gtk.MenuItem(_("Refresh feed")) item_refresh.connect("activate", self.configure_cb_feed_refresh, id) popup.append(item_refresh) item_delete = gtk.MenuItem(_("Delete feed")) item_delete.connect("activate", self.configure_cb_feed_delete, id) popup.append(item_delete) else: # Filter item_filter = gtk.MenuItem(_("Create filter")) item_filter.connect("activate", self.configure_cb_filter_new, model.get_value(iter, 1)) popup.append(item_filter) item_download = gtk.MenuItem(_("Download torrent")) item_download.connect("activate", self.configure_cb_download_torrent, model.get_value(iter, 2)) popup.append(item_download) else: # Neither item_new = gtk.MenuItem("New feed") item_new.connect("activate", self.configure_cb_feed_new) popup.append(item_new) popup.popup(None, None, None, event.button, event.time) popup.show_all() def configure_cb_output_set(self, chooser): self.glade.get_widget('FlexRSS_Filter_Output_Type_Custom').set_active(True) def configure_ui_reset_filter(self): # Just resets the crap in the filter tab to defaults. self.glade.get_widget('FlexRSS_Filters_Name').set_text('') self.glade.get_widget('FlexRSS_Filters_Type').set_active(0) self.glade.get_widget('FlexRSS_Filters_Feed').get_selection().unselect_all() for filter in self.glade.get_widget('FlexRSS_Filter_Patterns_List').get_children(): filter.destroy() self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').hide() self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').hide() file_chooser = self.glade.get_widget('FlexRSS_Filter_Output_Location') file_chooser.set_current_folder(self.interface.config.get('default_download_path')) self.glade.get_widget('FlexRSS_Filter_Output_Type_Default').set_active(True) def strcasecmp(self, s1, s2): try: t1 = s1.lower() t2 = s2.lower() if s1 < s2: return -1 elif s1 > s2: return 1 except: pass return 0 def configure_ui_sort_cmp(self, model, iter1, iter2, user_data=None): if (model.get_value(iter1, 0) == 0) or (model.get_value(iter2, 0) == 0): return 0 return self.strcasecmp(model.get_value(iter1, 1), model.get_value(iter2, 1)) def configure_cb_filter_toggled(self, renderer, path): old_val = renderer.get_active() model = self.glade.get_widget('FlexRSS_Filters_List').get_model() iter = model.get_iter(path) if old_val: model.set_value(iter, 2, False) self.config.setFilter(model.get_value(iter, 0), 'enabled', False) else: model.set_value(iter, 2, True) self.config.setFilter(model.get_value(iter, 0), 'enabled', True) self.write_config() def configure_cb_cookie_new(self, src): self.configure_ui_cookie_reset() self.glade.get_widget("FlexRSS_Cookies_Editor").show() def configure_cb_cookie_save(self, src): import cookielib, time domain = self.glade.get_widget("FlexRSS_Cookie_Domain").get_text() path = self.glade.get_widget("FlexRSS_Cookie_Path").get_text() name = self.glade.get_widget("FlexRSS_Cookie_Name").get_text() value = self.glade.get_widget("FlexRSS_Cookie_Value").get_text() if (domain == ""): return if path == '': path = '/' # Fragile. self.cookies._policy._now = self.cookies._now = int(time.time()) cookie = self.cookies._cookie_from_cookie_tuple((name, value, {"domain": domain, "path":path, "expires":2147483647}, {}), None) self.cookies.set_cookie(cookie) self.configure_ui_add_cookie(None, cookie) self.configure_ui_cookie_reset() self.glade.get_widget("FlexRSS_Cookies_Editor").hide() self.write_config(True) def configure_ui_add_cookie(self, model, cookie): if cookie.domain[0] == '.': domain = cookie.domain[1:] else: domain = cookie.domain if model == None: model = self.glade.get_widget("FlexRSS_Cookies_List").get_model() parent = None iter = model.get_iter_first() while iter: t = model.get_value(iter, 0) if t == domain: parent = iter break iter = model.iter_next(iter) if parent == None: parent = model.append(iter, (domain, "", "", "")) model.append(parent, (cookie.domain, cookie.path, cookie.name, cookie.value)) def configure_ui_cookie_reset(self): self.glade.get_widget("FlexRSS_Cookie_Domain").set_text('') self.glade.get_widget("FlexRSS_Cookie_Path").set_text('/') self.glade.get_widget("FlexRSS_Cookie_Name").set_text('') self.glade.get_widget("FlexRSS_Cookie_Value").set_text('') def configure_cb_cookie_selected(self, selection): model, iter = selection.get_selected() self.configure_ui_cookie_reset() self.glade.get_widget("FlexRSS_Cookies_Editor").hide() def configure_cb_cookie_delete(self, src): selection = self.glade.get_widget("FlexRSS_Cookies_List").get_selection() model, iter = selection.get_selected() domain = None path = None name = None if not model.iter_has_child(iter): path = model.get_value(iter, 1) name = model.get_value(iter, 2) domain = model.get_value(iter, 0) try: self.cookies.clear("." + domain, path, name) except: pass try: self.cookies.clear(domain, path, name) except: pass # UI if model.iter_has_child(iter): i = model.iter_children(iter) while model.remove(i): pass model.remove(iter) else: p = model.iter_parent(iter) model.remove(iter) if not model.iter_has_child(p): model.remove(p) self.write_config(True) def configure_cb_toolbar_clicked(self, button): self.configure() def configure_ui_show_toolbar_button(self): if self.toolbar_button == None: import gtk icon = gtk.Image() icon.set_from_file(self.path + "/FlexRSS.png") self.toolbar_button = gtk.ToolButton(icon_widget=icon, label="FlexRSS") self.toolbar_button.connect("clicked", self.configure_cb_toolbar_clicked) self.interface.toolbar.add(self.toolbar_button) self.toolbar_button.show_all() def configure_cb_toolbar_toggled(self, box): if box.get_active(): self.configure_ui_show_toolbar_button() self.config.show_toolbar_button = True self.write_config() else: self.toolbar_button.destroy() self.toolbar_button = None self.config.show_toolbar_button = False self.write_config() def configure_cb_threaded_toggled(self, box): self.config.threaded_retrieval = box.get_active() self.write_config() def configure(self, widget=None): if self.glade: # Dialog already running return import gtk, gtk.glade, gobject self.glade = gtk.glade.XML(self.path + "/FlexRSS.glade") # Intialize feed lists feeds_model = gtk.TreeStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING) feeds_view = self.glade.get_widget("FlexRSS_Feeds") filters_feeds_view = self.glade.get_widget("FlexRSS_Filters_Feed") feeds_view.set_model(feeds_model) filters_feeds_view.set_model(feeds_model) feeds_model.set_sort_func(1, self.configure_ui_sort_cmp) feeds_model.set_sort_column_id(1, gtk.SORT_ASCENDING) # Setup columns for feeds tab renderer_name = gtk.CellRendererText() column_name = gtk.TreeViewColumn(_("Feed Name"), renderer_name, text=1) feeds_view.append_column(column_name) renderer_url = gtk.CellRendererText() column_url = gtk.TreeViewColumn(_("URL"), renderer_url, text=2) feeds_view.append_column(column_url) feeds_view.set_search_column(1) feeds_view.set_search_equal_func(gtk_treeview_search_cb_stristr) # Set callback for when selection is changed in feeds tab # I can't figure out how to do this in Glade feeds_view.get_selection().connect("changed", self.configure_cb_feed_selected) # Setup columns for feed list on filters tab renderer_name = gtk.CellRendererText() column_name = gtk.TreeViewColumn(_("Feed Name"), renderer_name, text=1) filters_feeds_view.append_column(column_name) # Allow multiple selections of feeds in filters tab # I can't figure out how to do this in Glade filters_feeds_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE) # Populate feed lists if self.config.feeds: for feed in self.config.feeds: this_feed = feeds_model.append(None, (feed['id'], feed['name'], feed['url'])) for item in self.feeds[feed['id']]['data']: feeds_model.append(this_feed, (0, item['title'], item['link'])) # Initialize filters list filters_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) filters_view = self.glade.get_widget("FlexRSS_Filters_List") filters_view.set_model(filters_model) feeds_model.set_sort_func(1, self.configure_ui_sort_cmp) filters_model.set_sort_column_id(1, gtk.SORT_ASCENDING) # Setup columns for filters list renderer_enabled = gtk.CellRendererToggle() column_enabled = gtk.TreeViewColumn(_("Enabled"), renderer_enabled, active=2) filters_view.append_column(column_enabled) renderer_enabled.connect('toggled', self.configure_cb_filter_toggled) renderer_name = gtk.CellRendererText() column_name = gtk.TreeViewColumn(_("Filter Name"), renderer_name, text=1) filters_view.append_column(column_name) # Set callback for when selection is changed in feeds tab # I can't figure out how to do this in Glade filters_view.get_selection().connect("changed", self.configure_cb_filter_selected) # Populate filters list if self.config.filters: for filter in self.config.filters: filters_model.append((filter['id'], filter['name'], filter['enabled'])) # Filter types filter_types = self.glade.get_widget('FlexRSS_Filters_Type') filter_types.append_text(_("Generic")) filter_types.append_text(_("TV Show")) filter_types.append_text(_("TV Show (dated)")) # Calendar buttons for dated tv show history restrictions from CalendarButton import CalendarButton dated_from = CalendarButton() dated_from.connect('date-selected', self.configure_cb_test_filter) dated_to = CalendarButton() dated_to.connect('date-selected', self.configure_cb_test_filter) dated_from.show() dated_to.show() history_table = self.glade.get_widget('FlexRSS_History_TVShow_Dated') history_table.attach(dated_from, 1, 2, 0, 1, gtk.EXPAND|gtk.FILL, gtk.FILL) history_table.attach(dated_to, 1, 2, 1, 2, gtk.EXPAND|gtk.FILL, gtk.FILL) self.history_calendarbuttons = (dated_from, dated_to) # Initialize cookies list cookies_model = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) cookies_view = self.glade.get_widget("FlexRSS_Cookies_List") cookies_view.set_model(cookies_model) cookies_view.get_selection().connect("changed", self.configure_cb_cookie_selected) # Setup column for cookies domain_renderer = gtk.CellRendererText() domain_column = gtk.TreeViewColumn(_("Domain"), domain_renderer, text=0) path_renderer = gtk.CellRendererText() path_column = gtk.TreeViewColumn(_("Path"), path_renderer, text=1) name_renderer = gtk.CellRendererText() name_column = gtk.TreeViewColumn(_("Name"), name_renderer, text=2) value_renderer = gtk.CellRendererText() value_column = gtk.TreeViewColumn(_("Value"), value_renderer, text=3) cookies_view.append_column(domain_column) cookies_view.append_column(path_column) cookies_view.append_column(name_column) cookies_view.append_column(value_column) for cookie in self.cookies: self.configure_ui_add_cookie(cookies_model, cookie) # Interface self.glade.get_widget("FlexRSS_Interface_ShowButton").set_active(self.config.show_toolbar_button) self.glade.get_widget("FlexRSS_Retrieval_Threaded").set_active(self.config.threaded_retrieval) # Callbacks for UI events actions = { # Feeds tab "on_FlexRSS_MainWindow_destroy" : self.configure_cb_closed, "on_FlexRSS_Feeds_New_pressed" : self.configure_cb_feed_new, "on_FlexRSS_Feeds_Save_pressed" : self.configure_cb_feed_save, "on_FlexRSS_Feeds_Delete_pressed" : self.configure_cb_feed_delete, "on_FlexRSS_Feeds_button_press_event" : self.configure_cb_feed_popup, # Filters tab "on_FlexRSS_Filters_Add_pressed" : self.configure_cb_filter_new, "on_FlexRSS_Action_Save_pressed" : self.configure_cb_filter_save, "on_FlexRSS_Filter_Patern_Add_pressed" : self.configure_cb_add_pattern, "on_FlexRSS_Filters_Type_changed" : self.configure_cb_test_filter, "on_FlexRSS_Filters_Test_Pattern" : self.configure_cb_test_filter, "on_FlexRSS_Filters_Delete_pressed" : self.configure_cb_delete_filter, "on_FlexRSS_History_TVShow_From_Enabled_toggled" : self.configure_cb_filter_history_toggle, "on_FlexRSS_History_TVShow_Thru_Enabled_toggled" : self.configure_cb_filter_history_toggle, "on_FlexRSS_History_TVShow_Dated_From_Enabled_toggled" : self.configure_cb_filter_history_toggle, "on_FlexRSS_History_TVShow_Dated_Thru_Enabled_toggled" : self.configure_cb_filter_history_toggle, "on_FlexRSS_History_TVShow_From_Season_changed" : self.configure_cb_test_filter, "on_FlexRSS_History_TVShow_From_Episode_changed" : self.configure_cb_test_filter, "on_FlexRSS_History_TVShow_Thru_Season_changed" : self.configure_cb_test_filter, "on_FlexRSS_History_TVShow_Thru_Episode_changed" : self.configure_cb_test_filter, # Configuration tab "on_FlexRSS_Cookie_New_pressed" : self.configure_cb_cookie_new, "on_FlexRSS_Cookie_Save_pressed" : self.configure_cb_cookie_save, "on_FlexRSS_Cookie_Delete_pressed" : self.configure_cb_cookie_delete, "on_FlexRSS_Interface_ShowButton_toggled" : self.configure_cb_toolbar_toggled, "on_FlexRSS_Retrieval_Threaded_toggled" : self.configure_cb_threaded_toggled } if hasattr(self.interface, 'interactive_add_torrent_path'): actions["on_FlexRSS_Filter_Output_Location_current_folder_changed"] = self.configure_cb_output_set else: self.glade.get_widget('FlexRSS_Filter_Output').hide() self.glade.signal_autoconnect(actions) self.glade.get_widget("FlexRSS_MainWindow").show() def cmp_history(a, b): try: if a.has_key('series'): if a['series'] > b['series']: return 1 elif a['series'] < b['series']: return -1 else: if a['episode'] > b['episode']: return 1 elif a['episode'] < b['episode']: return -1 else: return 0 except: return 0 def strptime2regex(self, input): # Does'n exactly live up to its name yet. Currently just # replaces %y,%Y,%m,%d with named patterns. In the future, it # would be nice to allow escaping (e.g., %%Y means literal %Y) # and expand it to support other formats. patterns = [('%Y', '(?P[0-9]{4})'), ('%y', '(?P[0-9]{2})'), ('%m', '(?P[0-9]{1,2})'), ('%d', '(?P[0-9]{1,2})')] out = input for p in patterns: out = out.replace(p[0], p[1]) return out def replace_tv_show_patterns(self, input): patterns = [('%s', '(?P[0-9]+)'), ('%e', '(?P[0-9]+)')] out = input for p in patterns: out = out.replace(p[0], p[1]) return out def test_range(self, type, data, h_from=None, h_thru=None): if type == self.config.constants['TV Show']: if h_from != None: if data['series'] < h_from['season']: return False elif data['series'] == h_from['season']: if data['episode'] < h_from['episode']: return False if h_thru != None: if data['series'] > h_thru['season']: return False elif data['series'] == h_thru['season']: if data['episode'] > h_thru['episode']: return False return True elif type == self.config.constants['TV Show (dated)']: if h_from != None: if data['year'] < h_from['year']: return False elif data['year'] == h_from['year']: if data['month'] < h_from['month']: return False elif data['month'] == h_from['month']: if data['day'] < h_from['day']: return False if h_thru != None: if data['year'] < h_thru['year']: return False elif data['year'] == h_thru['year']: if data['month'] < h_thru['month']: return False elif data['month'] == h_thru['month']: if data['day'] < h_thru['day']: return False return True else: return True def test_pattern(self, type, subject, pattern): import re, time result = False if len(pattern) < 1: return False if type == self.config.constants['TV Show (dated)']: pattern = self.strptime2regex(pattern) elif type == self.config.constants['TV Show']: pattern = self.replace_tv_show_patterns(pattern) # Wow, so this is lame... if pattern[0] != '^': pattern = '.*' + pattern try: exp = re.compile(pattern, re.IGNORECASE) except: print 'Broken expression: ' + pattern return False match = exp.match(subject) if match: # print 'Match: ' + subject # print ' ' + pattern if type == self.config.constants['TV Show']: try: series = int(match.group('s')) except: series = 0 try: episode = int(match.group('e')) except: episode = 0 result = { 'series' : series, 'episode' : episode } elif type == self.config.constants['TV Show (dated)']: try: year = int(match.group('Y')) except: try: year = int(match.group('y')) if year > 70: year += 1900 else: year += 2000 except: year = 0 try: month = int(match.group('m')) except: month = 0 try: day = int(match.group('d')) except: day = 0 result = { 'year' : year, 'month' : month, 'day' : day } else: result = True return result def make_opener(self): import urllib2 return urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookies)) def make_request(self, location, referer=None): import urllib2, deluge.common req = urllib2.Request(location) req.add_header("User-Agent", "FlexRSS/%d.%d.%d (%s/%s)" % (self.version[0], self.version[1], self.version[2], deluge.common.PROGRAM_NAME, deluge.common.PROGRAM_VERSION)) if referer != None: req.add_header('Referer', referer) return req def open_url(self, location): return self.make_opener().open(self.make_request(location)) def download_torrent(self, location, path=None, queue_top=False, pause=False, referer=None): import tempfile, os, deluge.core try: fd = self.open_url(location) except: return False inf = fd.info() if inf["content-type"] != "application/x-bittorrent": print "Warning: torrent content-type not application/x-bittorrent" (tmpfd, filename) = tempfile.mkstemp(".torrent", "flexrss-") tfd = os.fdopen(tmpfd, 'wb') tfd.write(fd.read()) fd.close() tfd.close() unique_id = False try: if path is None: path = self.interface.config.get('default_download_path') unique_id = self.interface.manager.add_torrent(filename, path, self.interface.config.get('use_compact_storage')) self.interface.torrent_model_append(unique_id) if queue_top == True: try: self.interface.manager.queue_top(unique_id) except: pass if pause == True: try: self.interface.manager.set_user_pause(unique_id, True) except: pass except deluge.core.DuplicateTorrentError, e: print 'FlexRSS: torrent already exists.' return True except: print '*** FlexRSS error: unable to add torrent.' return False return True def parse_feed(self, id): import time, feedparser, urllib2, cookielib feed = self.config.getFeed(id) #print 'Parsing feed: ' + feed['url'] try: parsed = feedparser.parse(self.open_url(feed['url'])) if (not parsed) or (not parsed.entries): print 'Unable to parse feed: ' + feed['url'] return except: print 'Unable to update feed: ' + feed['url'] return #print 'Retrieval successful: ' + feed['url'] data = [] for entry in parsed.entries: entryTitle = entry['title'] try: entryLink = entry.links[0]['href'] except: try: entryLink = entry.enclosures[0]['href'] except: print "Skipping %s\n" % entryTitle continue try: data.append({ 'title': entryTitle, 'link': entryLink }) except: continue if self.config.filters: for filter in self.config.filters: try: if not ((feed['id'] in filter['feeds']) or (0 in filter['feeds'])): continue except TypeError: filter['feeds'] = [0] if filter['enabled'] != True: continue for pattern in filter['patterns']: # (setq python-indent 4 # tab-width 4) # Okay, I dislike python substantially less now. # Edit (~a month later): I still dislike it a lot, though. try: if pattern[1] == 'Title': subject = entryTitle else: subject = entryLink except: print 'Unable to find subject.' match = self.test_pattern(filter['type'], subject, pattern[0]) if match: # Filter matched. Check history to see if # we should download it. if filter['type'] == self.config.constants['Generic']: # Dirty hack. match = { 'url' : entryLink } torrent_url = entryLink replace = filter.get('replace', {'pattern': '', 'with': ''}) if len(replace['pattern']) > 0: try: import re p = re.compile(replace['pattern'], re.IGNORECASE) torrent_url = p.sub(replace['with'], torrent_url) except: print '*** FlexRSS error: s/%s/%s/i failed.' % (replace['pattern'], replace['with']) return if not self.config.checkHistory(filter['id'], filter['type'], match): print filter if filter.has_key('history'): res = False if filter['type'] == self.config.constants['Generic']: if filter['history'].get(filter['type'], []).count(torrent_url) == 0: res = self.download_torrent(torrent_url, filter.get('path', None), filter['queue_top'], filter['pause'], feed['url']) else: h_from = filter['history'][filter['type']].get('from', None) h_thru = filter['history'][filter['type']].get('thru', None) if self.test_range(filter['type'], match, h_from, h_thru): res = self.download_torrent(torrent_url, filter.get('path', None), filter['queue_top'], filter['pause'], feed['url']) print res if res == True: if filter['delete'] == True: self.config.deleteFilter(filter['id']) self.write_config() model = self.glade.get_widget("FlexRSS_Filters_List").get_model() iter = model.get_iter_first(); while iter != None: if model.get_value(iter, 0) == filter['id']: model.remove(iter) break iter = model.iter_next(iter) else: self.config.addHistory(filter['id'], filter['type'], match) self.write_config() self.feeds[feed['id']]['data'] = data if self.glade: # Update config window... feeds_model = self.glade.get_widget("FlexRSS_Feeds").get_model() iter = feeds_model.get_iter_first() while iter != None: if id == feeds_model.get_value(iter, 0): break iter = feeds_model.iter_next(iter) i = feeds_model.iter_children(iter) if i != None: while feeds_model.remove(i): pass for item in data: feeds_model.append(iter, (0, item['title'], item['link'])) def update(self): import time, threading current_time = time.time() # I feel dirty for this. Oh, how I miss C. for id in self.feeds: if self.feeds[id]['cfg']['enabled'] == True: if (current_time - self.feeds[id]['cfg']['interval']) > self.feeds[id]['updated']: self.feeds[id]['updated'] = current_time if ( self.config.threaded_retrieval ): threading.Thread(target=self.parse_feed, args=(self.feeds[id]['cfg']['id'],)).start() else: self.parse_feed(self.feeds[id]['cfg']['id']) def unload(self): if self.toolbar_button: self.toolbar_button.destroy() self.toolbar_button = None def deluge_version_compare(self, version): import deluge.common va = deluge.common.PROGRAM_VERSION.split('.') dv = int(va[0]) * 1000000 dv = dv + (int(va[1]) * 10000) dv = dv + (int(va[2]) * 100) if len(va) >= 4: dv = dv + int(va[3]) if dv < version: return -1 elif dv > version: return 1 else: return 0 def __init__(self, path, core, interface, defaults): self.path = path self.core = core self.interface = interface self.version = defaults['VERSION'] self.load_config() if self.config.show_toolbar_button == True: self.configure_ui_show_toolbar_button() self.feeds = {} if self.config.feeds: for feed in self.config.feeds: self.feeds[feed['id']] = { 'cfg' : feed, 'updated' : 0, 'data' : [] } # Debugging # self.configure()