def test_add_torrent_with_subscription_data(self): handler = TorrentHandler(self.log) subscription_data = yarss2.yarss_config.get_fresh_subscription_config() subscription_data["move_completed"] = "move/path" subscription_data["download_location"] = "download/path" subscription_data[ "add_torrents_in_paused_state"] = GeneralSubsConf.DEFAULT download = TorrentDownload() torrent_info = { "link": "http://url.com/file.torrent", "site_cookies_dict": {}, "subscription_data": subscription_data, "torrent_download": download } d = handler.add_torrent(torrent_info) self.assertTrue(d.success) added = test_component.added.pop() self.assertTrue(added.options["move_completed"]) self.assertEquals(added.options["move_completed_path"], subscription_data["move_completed"]) self.assertEquals(added.options["download_location"], subscription_data["download_location"]) # When using DEFAULT, the default value for add_paused on TorrentSettings is False self.assertEquals(added.options["add_paused"], False)
def test_add_torrent_magnet_link(self): handler = TorrentHandler(self.log) torrent_url = "magnet:blbalba/url.magnet.link" torrent_info = {"link": torrent_url, "site_cookies_dict": {}} download = handler.add_torrent(torrent_info) self.assertTrue(download.success) self.assertTrue(download.is_magnet) self.assertEquals(test_component.added.pop().magnet, torrent_url)
def enable(self, config=None): self.log = yarss2.logger.Logger() self.torrent_handler = TorrentHandler(self.log) if config is None: self.yarss_config = YARSSConfig(self.log) else: self.yarss_config = config self.rssfeed_timer = RSSFeedTimer(self.yarss_config, self.log) self.rssfeed_timer.enable_timers() self.log.info("Enabled YaRSS2 %s" % yarss2.common.get_version())
def test_add_torrent_raise_AddTorrentError(self): # noqa: N802 handler = TorrentHandler(self.log) filename = yarss2.util.common.get_resource( "FreeBSD-9.0-RELEASE-amd64-dvd1.torrent", path="tests/data/") torrent_info = {"link": filename, "site_cookies_dict": {}} with mock.patch.object(TestComponent, 'add') as test_component_add: test_component_add.side_effect = AddTorrentError( 'Torrent already in session (%s).' % 1) torrent_added = handler.add_torrent(torrent_info) self.assertFalse(torrent_added.success)
def test_add_torrent(self): handler = TorrentHandler(self.log) filename = yarss2.util.common.get_resource("FreeBSD-9.0-RELEASE-amd64-dvd1.torrent", path="tests/data/") torrent_info = {"link": filename, "site_cookies_dict": {}} torrent_download = handler.add_torrent(torrent_info) torrent_added = test_component.added.pop() self.assertTrue(torrent_added.success) self.assertFalse(torrent_added.filedump is None, "Filedump is not None") self.assertEquals(torrent_added.filename, os.path.split(filename)[1]) self.assertFalse(torrent_added.filedump is None) self.assertEquals(torrent_download.url, filename)
def test_add_torrent(self): handler = TorrentHandler(self.log) filename = yarss2.util.common.get_resource( "FreeBSD-9.0-RELEASE-amd64-dvd1.torrent", path="tests/data/") torrent_info = {"link": filename, "site_cookies_dict": {}} torrent_download = handler.add_torrent(torrent_info) torrent_added = test_component.added.pop() self.assertTrue(torrent_added.success) self.assertFalse(torrent_added.filedump is None, "Filedump is not None") self.assertEquals(torrent_added.filename, os.path.split(filename)[1]) self.assertFalse(torrent_added.filedump is None) self.assertEquals(torrent_download.url, filename)
def test_add_torrent_ret_false(self): handler = TorrentHandler(self.log) torrent_url = "http://url.com/file.torrent" cookies_dict = {} global test_component test_component.download_success = False handler.download_torrent_file = test_component.download_torrent_file torrent_info = {"link": torrent_url, "site_cookies_dict": cookies_dict} torrent_download = handler.add_torrent(torrent_info) self.assertFalse(torrent_download.success) # Set by download_torrent_file self.assertEquals(torrent_download.torrent_url, torrent_url) self.assertEquals(torrent_download.cookies_dict, cookies_dict) test_component.download_success = True
def test_add_torrent_ret_false(self): handler = TorrentHandler(self.log) torrent_url = "http://url.com/file.torrent" cookies = {} global test_component test_component.download_success = False handler.download_torrent_file = test_component.download_torrent_file torrent_info = {"link": torrent_url, "site_cookies_dict": cookies} torrent_download = handler.add_torrent(torrent_info) self.assertFalse(torrent_download.success) # Set by download_torrent_file self.assertEquals(torrent_download.torrent_url, torrent_url) self.assertEquals(torrent_download.cookies, cookies) test_component.download_success = True
def setUp(self): # NOQA self.handler = TorrentHandler(log) smtplib.SMTP = DummySMTP self.email_config = yarss2.yarss_config.get_fresh_email_config() self.email_config["from_address"] = "*****@*****.**" self.email = {} self.email["to_address"] = "*****@*****.**" self.email["subject"] = "Test Subject" self.email["message"] = "Hi\n\nThis is a test message.\n\n\nRegards" self.email["name"] = "Test Message Name" self.expected_messsage = [] self.expected_messsage.append('Content-Type: text/plain; charset="utf-8"') self.expected_messsage.append('MIME-Version: 1.0') self.expected_messsage.append('Content-Transfer-Encoding: base64') self.expected_messsage.append("Subject: %s") self.expected_messsage.append("From: %s") self.expected_messsage.append("To: %s") self.expected_messsage_multipart = [] self.expected_messsage_multipart.append('Content-Type: multipart/alternative;') self.expected_messsage_multipart.append('MIME-Version: 1.0') self.expected_messsage_multipart.append("Subject: %s") self.expected_messsage_multipart.append("From: %s") self.expected_messsage_multipart.append("To: %s") self.expected_messsage_multipart.append('Content-Type: text/plain; charset="utf-8"') self.expected_messsage_multipart.append('MIME-Version: 1.0') self.expected_messsage_multipart.append('Content-Transfer-Encoding: base64') self.expected_messsage_multipart.append('Content-Type: text/html; charset="utf-8"') self.expected_messsage_multipart.append('MIME-Version: 1.0') self.expected_messsage_multipart.append('Content-Transfer-Encoding: base64')
def __init__(self, config, logger): self.yarss_config = config self.rssfeed_timers = {} self.run_queue = RSSFeedRunQueue() self.log = logger self.rssfeedhandler = RSSFeedHandler(logger) self.torrent_handler = TorrentHandler(logger) self.add_torrent_func = self.torrent_handler.add_torrents # To make it possible to disable adding torrents in testing
def test_get_torrent(self): handler = TorrentHandler(self.log) handler.download_torrent_file = test_component.download_torrent_file filename = yarss2.util.common.get_resource( "FreeBSD-9.0-RELEASE-amd64-dvd1.torrent", path="tests/data/") test_component.use_filedump = read_file(filename) torrent_info = { "link": "http://url.com/file.torrent", "site_cookies_dict": { "cookiekey": "cookievalue" }, "user_agent": "test" } download = handler.get_torrent(torrent_info) self.assertEquals(download.headers, {'User-Agent': 'test'}) self.assertEquals(download.cookies, {'cookiekey': 'cookievalue'}) self.assertFalse(download.is_magnet)
def enable(self, config=None): self.log = yarss2.util.logger.Logger() self.torrent_handler = TorrentHandler(self.log) if config is None: self.yarss_config = YARSSConfig(self.log) else: self.yarss_config = config self.rssfeed_scheduler = RSSFeedScheduler(self.yarss_config, self.log) self.rssfeed_scheduler.enable_timers() self.log.info("Enabled YaRSS2 %s" % yarss2.util.common.get_version())
def createUI(self): self.glade = gtk.glade.XML(get_resource("yarss_main.glade")) self.glade.signal_autoconnect({ "on_button_add_subscription_clicked": self.on_button_add_subscription_clicked, "on_button_delete_subscription_clicked": self.on_button_delete_subscription_clicked, "on_button_edit_subscription_clicked" : self.on_button_edit_subscription_clicked, "on_button_add_rssfeed_clicked": self.on_button_add_rssfeed_clicked, "on_button_delete_rssfeed_clicked": self.on_button_delete_rssfeed_clicked, "on_button_edit_rssfeed_clicked" : self.on_button_edit_rssfeed_clicked, "on_button_add_cookie_clicked" : self.on_button_add_cookie_clicked, "on_button_edit_cookie_clicked" : self.on_button_edit_cookie_clicked, "on_button_delete_cookie_clicked": self.on_button_delete_cookie_clicked, "on_button_add_message_clicked" : self.on_button_add_message_clicked, "on_button_edit_message_clicked" : self.on_button_edit_message_clicked, "on_button_delete_message_clicked": self.on_button_delete_message_clicked, "on_checkbox_email_authentication_toggled": self.on_checkbox_email_authentication_toggled, "on_checkbutton_send_email_on_torrent_events_toggled": self.on_checkbutton_send_email_on_torrent_events_toggled }) component.get("Preferences").add_page("YaRSS2", self.glade.get_widget("notebook_main")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) self.gtkui_log = GTKUI_logger(self.glade.get_widget('textview_log')) self.log = Logger(gtkui_logger=self.gtkui_log) self.torrent_handler = TorrentHandler(self.log) self.subscriptions = {} self.rssfeeds = {} self.selected_path_subscriptions = None self.selected_path_rssfeeds = None self.selected_path_email_message = None self.selected_path_cookies = None # key, enabled, name, site, download_location self.subscriptions_store = gtk.ListStore(str, bool, str, str, str, str, str) # key, active, name, site, Update interval, Last update, subscripions, URL self.rssfeeds_store = gtk.ListStore(str, bool, str, str, str, str, str, str) # key, active, site, value self.cookies_store = gtk.ListStore(str, bool, str, str) # key, active, name, to-address, subject, message-content self.email_messages_store = gtk.ListStore(str, bool, str, str, str, str) self.create_subscription_pane() self.create_rssfeeds_pane() self.create_cookies_pane() self.create_email_messages_pane()
def test_add_torrent_with_subscription_data(self): handler = TorrentHandler(self.log) subscription_data = yarss2.yarss_config.get_fresh_subscription_config() subscription_data["move_completed"] = "move/path" subscription_data["download_location"] = "download/path" subscription_data["add_torrents_in_paused_state"] = GeneralSubsConf.DEFAULT download = TorrentDownload() torrent_info = { "link": "http://url.com/file.torrent", "site_cookies_dict": {}, "subscription_data": subscription_data, "torrent_download": download, } d = handler.add_torrent(torrent_info) self.assertTrue(d.success) added = test_component.added.pop() self.assertTrue(added.options["move_completed"]) self.assertEquals(added.options["move_completed_path"], subscription_data["move_completed"]) self.assertEquals(added.options["download_location"], subscription_data["download_location"]) # When using DEFAULT, the default value for add_paused on TorrentSettings is False self.assertEquals(added.options["add_paused"], False)
def test_add_torrents(self): handler = TorrentHandler(self.log) from yarss2.rssfeed_handling import RSSFeedHandler self.rssfeedhandler = RSSFeedHandler(self.log) # Override method download_torrent_file handler.download_torrent_file = test_component.download_torrent_file filename = yarss2.util.common.get_resource("FreeBSD-9.0-RELEASE-amd64-dvd1.torrent", path="tests/data/") test_component.use_filedump = read_file(filename) config = get_test_config_dict() # 0 is the rssfeed key match_result = self.rssfeedhandler.fetch_feed_torrents(config, "0") matching_torrents = match_result["matching_torrents"] saved_subscriptions = [] def save_subscription_func(subscription_data): saved_subscriptions.append(subscription_data) handler.add_torrents(save_subscription_func, matching_torrents, self.config.get_config()) self.assertEquals(len(saved_subscriptions), 1) handler.use_filedump = None
def setUp(self): # NOQA defer.setDebugging(True) self.config = common.get_test_config() # get_test_config will load a new core.conf with the default values. # Must save to save to file so that torrent.py.TorrentOptions loads the default values self.config.core_config.save() test_component = TestComponent() self.torrent_handler = TorrentHandler(LOG) self.torrent_handler.download_torrent_file = test_component.download_torrent_file # Might be necessary for changes in master branch # yarss2.core.component = test_component self.core = Core("test") self.core.enable(config=self.config) self.core.torrent_handler = self.torrent_handler
def test_add_torrents(self): handler = TorrentHandler(self.log) from yarss2.rssfeed_handling import RSSFeedHandler self.rssfeedhandler = RSSFeedHandler(self.log) # Override method download_torrent_file handler.download_torrent_file = test_component.download_torrent_file filename = yarss2.util.common.get_resource( "FreeBSD-9.0-RELEASE-amd64-dvd1.torrent", path="tests/data/") test_component.use_filedump = read_file(filename) config = get_test_config_dict() # 0 is the rssfeed key match_result = self.rssfeedhandler.fetch_feed_torrents(config, "0") matching_torrents = match_result["matching_torrents"] saved_subscriptions = [] def save_subscription_func(subscription_data): saved_subscriptions.append(subscription_data) handler.add_torrents(save_subscription_func, matching_torrents, self.config.get_config()) self.assertEquals(len(saved_subscriptions), 3) handler.use_filedump = None
class RSSFeedScheduler(object): """Handles scheduling the RSS Feed fetches.""" def __init__(self, config, logger): self.yarss_config = config self.rssfeed_timers = {} self.run_queue = RSSFeedRunQueue() self.log = logger self.rssfeedhandler = RSSFeedHandler(logger) self.torrent_handler = TorrentHandler(logger) self.add_torrent_func = self.torrent_handler.add_torrents # To make it possible to disable adding torrents in testing def enable_timers(self): """Creates the LoopingCall timers, one for each RSS Feed""" config = self.yarss_config.get_config() for key in config["rssfeeds"]: self.set_timer(config["rssfeeds"][key]["key"], config["rssfeeds"][key]['update_interval']) self.log.info("Scheduled RSS Feed '%s' with interval %s" % (config["rssfeeds"][key]["name"], config["rssfeeds"][key]["update_interval"])) def disable_timers(self): for key in self.rssfeed_timers.keys(): self.rssfeed_timers[key]["timer"].stop() del self.rssfeed_timers[key] def set_timer(self, key, interval): """Schedule a timer for the specified interval.""" try: interval = int(interval) except: self.log.error("Failed to convert interval '%s' to int!" % str(interval)) # Already exists, so reschedule if interval has changed if self.rssfeed_timers.has_key(key): # Interval is the same, so return if self.rssfeed_timers[key]["update_interval"] == interval: return False self.rssfeed_timers[key]["timer"].stop() self.rssfeed_timers[key]["update_interval"] = interval else: # New timer # Second argument, the rssfeedkey is passed as argument in the callback method #timer = LoopingCall(self.rssfeed_update_handler, (key)) timer = LoopingCall(self.queue_rssfeed_update, key) self.rssfeed_timers[key] = {"timer": timer, "update_interval": interval} self.rssfeed_timers[key]["timer"].start(interval * 60, now=False) # Multiply to get seconds return True def delete_timer(self, key): """Delete timer with the specified key.""" if not self.rssfeed_timers.has_key(key): self.log.warn("Cannot delete timer. No timer with key %s" % key) return False self.rssfeed_timers[key]["timer"].stop() del self.rssfeed_timers[key] return True def rssfeed_update_handler(self, rssfeed_key=None, subscription_key=None): """Goes through all the feeds and runs the active ones. Multiple subscriptions on one RSS Feed will download the RSS feed page only once """ if subscription_key: self.log.info("Manually running Subscription '%s'" % (self.yarss_config.get_config()["subscriptions"][subscription_key]["name"])) elif rssfeed_key: if self.yarss_config.get_config()["rssfeeds"][rssfeed_key]["active"] is False: return #self.log.info("Running RSS Feed '%s'" % (self.yarss_config.get_config()["rssfeeds"][rssfeed_key]["name"])) fetch_result = self.rssfeedhandler.fetch_feed_torrents(self.yarss_config.get_config(), rssfeed_key, subscription_key=subscription_key) matching_torrents = fetch_result["matching_torrents"] # Fetching the torrent files. Do this slow task in non-main thread. for torrent in matching_torrents: torrent["torrent_download"] = self.torrent_handler.get_torrent(torrent) # Update TTL value? if fetch_result.has_key("ttl"): # Subscription is run directly. Get RSS Feed key if not rssfeed_key: rssfeed_key = self.yarss_config.get_config()["subscriptions"][subscription_key]["rssfeed_key"] self.log.info("Rescheduling RSS Feed '%s' with interval '%s' according to TTL." % (self.yarss_config.get_config()["rssfeeds"][rssfeed_key]["name"], fetch_result["ttl"])) self.set_timer(rssfeed_key, fetch_result["ttl"]) # Set new interval in config self.yarss_config.get_config()["rssfeeds"][rssfeed_key]["update_interval"] = fetch_result["ttl"] # Send YARSSConfigChangedEvent to GUI with updated config. try: # Tests throws KeyError for EventManager when running this method, so wrap this in try/except component.get("EventManager").emit(YARSSConfigChangedEvent(self.yarss_config.get_config())) except KeyError: pass def save_subscription_func(subscription_data): self.yarss_config.generic_save_config("subscriptions", data_dict=subscription_data) return (self.add_torrent_func, save_subscription_func, fetch_result["matching_torrents"], self.yarss_config.get_config()) def add_torrents_callback(self, args): """This i called with the results from rssfeed_update_handler add_torrent_func must be called on the main thread """ if args is None: return add_torrent_func, save_subscription_func, matching_torrents, config = args add_torrent_func(save_subscription_func, matching_torrents, config) def queue_rssfeed_update(self, *args, **kwargs): d = self.run_queue.push(self.rssfeed_update_handler, *args, **kwargs) d.addCallback(self.add_torrents_callback) return d
class Core(CorePluginBase): def enable(self, config=None): self.log = yarss2.logger.Logger() self.torrent_handler = TorrentHandler(self.log) if config is None: self.yarss_config = YARSSConfig(self.log) else: self.yarss_config = config self.rssfeed_timer = RSSFeedTimer(self.yarss_config, self.log) self.rssfeed_timer.enable_timers() self.log.info("Enabled YaRSS2 %s" % yarss2.common.get_version()) def disable(self): self.yarss_config.save() self.rssfeed_timer.disable_timers() def update(self): pass @export def initiate_rssfeed_update(self, rssfeed_key, subscription_key=None): self.rssfeed_timer.rssfeed_update_handler(rssfeed_key, subscription_key=subscription_key) @export def set_config(self, config): self.yarss_config.set_config(config) @export def get_config(self): "Returns the config dictionary" return self.yarss_config.get_config() @export def save_email_configurations(self, email_configurations): conf = {"email_configurations": email_configurations} try: self.yarss_config.set_config(conf) except ValueError as (v): self.log.error("Failed to save email configurations:" + str(v)) @export def save_subscription(self, dict_key=None, subscription_data=None, delete=False): """Saves the subscription in subscription_data. If subscription_data is None and delete=True, delete subscription with key==dict_key """ if delete: if subscription_data is not None: self.log.warn("save_subscription called with delete=True, but rssfeed_data is not None!") else: self.log.info("Deleting Subscription '%s'" % self.yarss_config.get_config()["subscriptions"][dict_key]["name"]) try: return self.yarss_config.generic_save_config("subscriptions", dict_key=dict_key, data_dict=subscription_data, delete=delete) except ValueError as (v): self.log.error("Failed to save subscription:" + str(v)) @export def save_rssfeed(self, dict_key=None, rssfeed_data=None, delete=False): """Saves the rssfeed in rssfeed_data. If rssfeed_data is None and delete=True, delete rssfeed with key==dict_key """ try: if delete: if rssfeed_data is not None: self.log.warn("save_rssfeed called with delete=True, but rssfeed_data is not None!") else: self.log.info("Stopping and deleting RSS Feed '%s'" % self.yarss_config.get_config()["rssfeeds"][dict_key]["name"]) config = self.yarss_config.generic_save_config("rssfeeds", dict_key=dict_key, data_dict=rssfeed_data, delete=delete) if delete is True: self.rssfeed_timer.delete_timer(dict_key) # Successfully saved rssfeed, check if timer was changed elif config: if self.rssfeed_timer.set_timer(rssfeed_data["key"], rssfeed_data["update_interval"]): self.log.info("Scheduled RSS Feed '%s' with interval %s" % (rssfeed_data["name"], rssfeed_data["update_interval"])) return config except ValueError as (v): self.log.error("Failed to save rssfeed:" + str(v)) @export def save_cookie(self, dict_key=None, cookie_data=None, delete=False): """Save cookie to config. If cookie_data is None and delete=True, delete cookie with key==dict_key""" try: return self.yarss_config.generic_save_config("cookies", dict_key=dict_key, data_dict=cookie_data, delete=delete) except ValueError as (v): self.log.error("Failed to save cookie:" + str(v)) @export def save_email_message(self, dict_key=None, message_data=None, delete=False): """Save email message to config. If message_data is None, delete message with key==dict_key""" try: return self.yarss_config.generic_save_config("email_messages", dict_key=dict_key, data_dict=message_data, delete=delete) except ValueError as (v): self.log.error("Failed to save email message:" + str(v)) @export def add_torrent(self, torrent_url): cookie_header = get_cookie_header(self.yarss_config.get_config()["cookies"], torrent_url) id = self.torrent_handler.add_torrent(torrent_url, cookie_header=cookie_header)
class Core(CorePluginBase): def enable(self, config=None): self.log = yarss2.logger.Logger() self.torrent_handler = TorrentHandler(self.log) if config is None: self.yarss_config = YARSSConfig(self.log) else: self.yarss_config = config self.rssfeed_timer = RSSFeedTimer(self.yarss_config, self.log) self.rssfeed_timer.enable_timers() self.log.info("Enabled YaRSS2 %s" % yarss2.common.get_version()) def disable(self): self.yarss_config.save() self.rssfeed_timer.disable_timers() def update(self): pass @export def initiate_rssfeed_update(self, rssfeed_key, subscription_key=None): self.rssfeed_timer.rssfeed_update_handler( rssfeed_key, subscription_key=subscription_key) @export def set_config(self, config): self.yarss_config.set_config(config) @export def get_config(self): "Returns the config dictionary" return self.yarss_config.get_config() @export def save_email_configurations(self, email_configurations): conf = {"email_configurations": email_configurations} try: self.yarss_config.set_config(conf) except ValueError as (v): self.log.error("Failed to save email configurations:" + str(v)) @export def save_subscription(self, dict_key=None, subscription_data=None, delete=False): """Saves the subscription in subscription_data. If subscription_data is None and delete=True, delete subscription with key==dict_key """ if delete: if subscription_data is not None: self.log.warn( "save_subscription called with delete=True, but rssfeed_data is not None!" ) else: self.log.info("Deleting Subscription '%s'" % self.yarss_config.get_config()["subscriptions"] [dict_key]["name"]) try: return self.yarss_config.generic_save_config( "subscriptions", dict_key=dict_key, data_dict=subscription_data, delete=delete) except ValueError as (v): self.log.error("Failed to save subscription:" + str(v)) @export def save_rssfeed(self, dict_key=None, rssfeed_data=None, delete=False): """Saves the rssfeed in rssfeed_data. If rssfeed_data is None and delete=True, delete rssfeed with key==dict_key """ try: if delete: if rssfeed_data is not None: self.log.warn( "save_rssfeed called with delete=True, but rssfeed_data is not None!" ) else: self.log.info("Stopping and deleting RSS Feed '%s'" % self.yarss_config.get_config()["rssfeeds"] [dict_key]["name"]) config = self.yarss_config.generic_save_config( "rssfeeds", dict_key=dict_key, data_dict=rssfeed_data, delete=delete) if delete is True: self.rssfeed_timer.delete_timer(dict_key) # Successfully saved rssfeed, check if timer was changed elif config: if self.rssfeed_timer.set_timer( rssfeed_data["key"], rssfeed_data["update_interval"]): self.log.info("Scheduled RSS Feed '%s' with interval %s" % (rssfeed_data["name"], rssfeed_data["update_interval"])) return config except ValueError as (v): self.log.error("Failed to save rssfeed:" + str(v)) @export def save_cookie(self, dict_key=None, cookie_data=None, delete=False): """Save cookie to config. If cookie_data is None and delete=True, delete cookie with key==dict_key""" try: return self.yarss_config.generic_save_config("cookies", dict_key=dict_key, data_dict=cookie_data, delete=delete) except ValueError as (v): self.log.error("Failed to save cookie:" + str(v)) @export def save_email_message(self, dict_key=None, message_data=None, delete=False): """Save email message to config. If message_data is None, delete message with key==dict_key""" try: return self.yarss_config.generic_save_config( "email_messages", dict_key=dict_key, data_dict=message_data, delete=delete) except ValueError as (v): self.log.error("Failed to save email message:" + str(v)) @export def add_torrent(self, torrent_url): cookie_header = get_cookie_header( self.yarss_config.get_config()["cookies"], torrent_url) id = self.torrent_handler.add_torrent(torrent_url, cookie_header=cookie_header)
def createUI(self): self.glade = gtk.glade.XML(get_resource("yarss_main.glade")) self.glade.signal_autoconnect({ "on_button_add_subscription_clicked": self.on_button_add_subscription_clicked, "on_button_delete_subscription_clicked": self.on_button_delete_subscription_clicked, "on_button_edit_subscription_clicked": self.on_button_edit_subscription_clicked, "on_button_add_rssfeed_clicked": self.on_button_add_rssfeed_clicked, "on_button_delete_rssfeed_clicked": self.on_button_delete_rssfeed_clicked, "on_button_edit_rssfeed_clicked": self.on_button_edit_rssfeed_clicked, "on_button_add_cookie_clicked": self.on_button_add_cookie_clicked, "on_button_edit_cookie_clicked": self.on_button_edit_cookie_clicked, "on_button_delete_cookie_clicked": self.on_button_delete_cookie_clicked, "on_button_add_message_clicked": self.on_button_add_message_clicked, "on_button_edit_message_clicked": self.on_button_edit_message_clicked, "on_button_delete_message_clicked": self.on_button_delete_message_clicked, "on_checkbox_email_authentication_toggled": self.on_checkbox_email_authentication_toggled, "on_checkbutton_send_email_on_torrent_events_toggled": self.on_checkbutton_send_email_on_torrent_events_toggled }) component.get("Preferences").add_page( "YaRSS2", self.glade.get_widget("notebook_main")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) self.gtkui_log = GTKUI_logger(self.glade.get_widget('textview_log')) self.log = Logger(gtkui_logger=self.gtkui_log) self.torrent_handler = TorrentHandler(self.log) self.subscriptions = {} self.rssfeeds = {} self.selected_path_subscriptions = None self.selected_path_rssfeeds = None self.selected_path_email_message = None self.selected_path_cookies = None # key, enabled, name, site, download_location self.subscriptions_store = gtk.ListStore(str, bool, str, str, str, str, str) # key, active, name, site, Update interval, Last update, subscripions, URL self.rssfeeds_store = gtk.ListStore(str, bool, str, str, str, str, str, str) # key, active, site, value self.cookies_store = gtk.ListStore(str, bool, str, str) # key, active, name, to-address, subject, message-content self.email_messages_store = gtk.ListStore(str, bool, str, str, str, str) self.create_subscription_pane() self.create_rssfeeds_pane() self.create_cookies_pane() self.create_email_messages_pane()
class GtkUI(GtkPluginBase): def enable(self): self.createUI() self.on_show_prefs( ) # Necessary for the first time when the plugin is installed client.register_event_handler("YARSSConfigChangedEvent", self.cb_on_config_changed_event) client.register_event_handler("GtkUILogMessageEvent", self.cb_on_log_message_arrived_event) def disable(self): component.get("Preferences").remove_page("YaRSS2") component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs) def createUI(self): self.glade = gtk.glade.XML(get_resource("yarss_main.glade")) self.glade.signal_autoconnect({ "on_button_add_subscription_clicked": self.on_button_add_subscription_clicked, "on_button_delete_subscription_clicked": self.on_button_delete_subscription_clicked, "on_button_edit_subscription_clicked": self.on_button_edit_subscription_clicked, "on_button_add_rssfeed_clicked": self.on_button_add_rssfeed_clicked, "on_button_delete_rssfeed_clicked": self.on_button_delete_rssfeed_clicked, "on_button_edit_rssfeed_clicked": self.on_button_edit_rssfeed_clicked, "on_button_add_cookie_clicked": self.on_button_add_cookie_clicked, "on_button_edit_cookie_clicked": self.on_button_edit_cookie_clicked, "on_button_delete_cookie_clicked": self.on_button_delete_cookie_clicked, "on_button_add_message_clicked": self.on_button_add_message_clicked, "on_button_edit_message_clicked": self.on_button_edit_message_clicked, "on_button_delete_message_clicked": self.on_button_delete_message_clicked, "on_checkbox_email_authentication_toggled": self.on_checkbox_email_authentication_toggled, "on_checkbutton_send_email_on_torrent_events_toggled": self.on_checkbutton_send_email_on_torrent_events_toggled }) component.get("Preferences").add_page( "YaRSS2", self.glade.get_widget("notebook_main")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) self.gtkui_log = GTKUI_logger(self.glade.get_widget('textview_log')) self.log = Logger(gtkui_logger=self.gtkui_log) self.torrent_handler = TorrentHandler(self.log) self.subscriptions = {} self.rssfeeds = {} self.selected_path_subscriptions = None self.selected_path_rssfeeds = None self.selected_path_email_message = None self.selected_path_cookies = None # key, enabled, name, site, download_location self.subscriptions_store = gtk.ListStore(str, bool, str, str, str, str, str) # key, active, name, site, Update interval, Last update, subscripions, URL self.rssfeeds_store = gtk.ListStore(str, bool, str, str, str, str, str, str) # key, active, site, value self.cookies_store = gtk.ListStore(str, bool, str, str) # key, active, name, to-address, subject, message-content self.email_messages_store = gtk.ListStore(str, bool, str, str, str, str) self.create_subscription_pane() self.create_rssfeeds_pane() self.create_cookies_pane() self.create_email_messages_pane() ############################## # Save data and delete data from core ############################### def save_subscription(self, subscription_data, subscription_key=None, delete=False): """Called by the RSSFeed Dialog""" self.selected_path_subscriptions = self.get_selection_path( self.subscriptions_treeview) client.yarss2.save_subscription(dict_key=subscription_key, subscription_data=subscription_data, delete=delete).addCallback( self.cb_get_config) def save_rssfeed(self, rssfeed_data, rssfeed_key=None, delete=False): """Called by the RSSFeed Dialog""" self.selected_path_rssfeeds = self.get_selection_path( self.rssfeeds_treeview) client.yarss2.save_rssfeed(dict_key=rssfeed_key, rssfeed_data=rssfeed_data, delete=delete).addCallback( self.cb_get_config) def save_email_message(self, message_data, email_message_key=None, delete=False): self.selected_path_email_message = self.get_selection_path( self.email_messages_treeview) client.yarss2.save_email_message(dict_key=email_message_key, message_data=message_data, delete=delete).addCallback( self.cb_get_config) def save_cookie(self, cookie_data, cookie_key=None, delete=False): self.selected_path_cookies = self.get_selection_path( self.cookies_treeview) client.yarss2.save_cookie(dict_key=cookie_key, cookie_data=cookie_data, delete=delete).addCallback( self.cb_get_config) def save_email_config(self, email_config): client.yarss2.save_email_configurations(email_config) def add_torrent(self, torrent_link): client.yarss2.add_torrent(torrent_link) ############################## # Update config and lists data ############################### def on_apply_prefs(self): """Called when the 'Apply' button is pressed""" self.save_configuration_data() def on_checkbutton_send_email_on_torrent_events_toggled(self, button): """Called when email notification button is toggled""" self.save_configuration_data() def save_configuration_data(self): # Save: # Settings -> Email Notifications -> Enable/Disable email notifcations # Settings -> Email configuration -> all fields # Settings -> Default values -> All fields send_emails = self.glade.get_widget( "checkbutton_send_email_on_torrent_events").get_active() from_addr = self.glade.get_widget("txt_email_from").get_text() smtp_server = self.glade.get_widget("txt_email_server").get_text() smtp_port = self.glade.get_widget("txt_email_port").get_text() smtp_username = self.glade.get_widget("txt_email_username").get_text() smtp_password = self.glade.get_widget("txt_email_password").get_text() enable_auth = self.glade.get_widget( "checkbox_email_enable_authentication").get_active() default_to_address = self.glade.get_widget( "txt_default_to_address").get_text() default_subject = self.glade.get_widget( "txt_default_subject").get_text() textbuffer = self.glade.get_widget( "textview_default_message").get_buffer() default_message = textbuffer.get_text(textbuffer.get_start_iter(), textbuffer.get_end_iter()) self.email_config["send_email_on_torrent_events"] = send_emails self.email_config["from_address"] = from_addr self.email_config["smtp_server"] = smtp_server self.email_config["smtp_port"] = smtp_port self.email_config["smtp_authentication"] = enable_auth self.email_config["smtp_username"] = smtp_username self.email_config["smtp_password"] = smtp_password self.email_config["default_email_to_address"] = default_to_address self.email_config["default_email_subject"] = default_subject self.email_config["default_email_message"] = default_message self.save_email_config(self.email_config) def on_show_prefs(self): """Called when showing preferences window""" client.yarss2.get_config().addCallback(self.cb_get_config) def cb_on_config_changed_event(self, config): """Callback function called on YARSSConfigChangedEvent events""" # Tried to fix error where glade.get_widget("label_status") in dialog_subscription returns None. (Why??) # DeferToThread actually works, but it seems to add a new error, where Deluge crashes, probably # caused by the GUI being updated in another thread than the main thread. # d = threads.deferToThread(self.cb_get_config, config) self.cb_get_config(config) def cb_on_log_message_arrived_event(self, message): """Callback function called on GtkUILogMessageEvent events""" self.gtkui_log.gtkui_log_message(message) def cb_get_config(self, config): """Callback function called after saving data to core""" if config is None: self.log.error( "An error has occured. Cannot load data from config") else: self.update_data_from_config(config) def update_data_from_config(self, config): self.subscriptions = config.get('subscriptions', {}) self.rssfeeds = config.get('rssfeeds', {}) self.cookies = config.get('cookies', {}) self.email_messages = config.get('email_messages', {}) self.email_config = config.get('email_configurations', {}) # When connecting to a second host, the glade object returns None for all the fields, # so reload the glade file here to avoid this problem. if self.glade.get_widget("textview_default_message") is None: self.glade = gtk.glade.XML(get_resource("yarss_main.glade")) # Update GUI self.update_subscription_list(self.subscriptions_store) self.update_rssfeeds_list(self.rssfeeds_store) self.update_cookies_list(self.cookies_store) self.update_email_messages_list(self.email_messages_store) # Set selection for each treeview if self.selected_path_subscriptions and self.subscriptions_treeview.get_selection( ): self.subscriptions_treeview.get_selection().select_path( self.selected_path_subscriptions) if self.selected_path_rssfeeds and self.rssfeeds_treeview.get_selection( ): self.rssfeeds_treeview.get_selection().select_path( self.selected_path_rssfeeds) if self.selected_path_email_message and self.email_messages_treeview.get_selection( ): self.email_messages_treeview.get_selection().select_path( self.selected_path_email_message) if self.selected_path_cookies and self.cookies_treeview.get_selection( ): self.cookies_treeview.get_selection().select_path( self.selected_path_cookies) # Email configurations send_email_checkbox = self.glade.get_widget( "checkbutton_send_email_on_torrent_events") from_addr = self.glade.get_widget("txt_email_from") smtp_server = self.glade.get_widget("txt_email_server") smtp_port = self.glade.get_widget("txt_email_port") smtp_username = self.glade.get_widget("txt_email_username") smtp_password = self.glade.get_widget("txt_email_password") enable_auth = self.glade.get_widget( "checkbox_email_enable_authentication") default_to_address = self.glade.get_widget("txt_default_to_address") default_subject = self.glade.get_widget("txt_default_subject") default_message = self.glade.get_widget("textview_default_message") default_message = default_message.get_buffer() from_addr.set_text(self.email_config["from_address"]) smtp_server.set_text(self.email_config["smtp_server"]) smtp_port.set_text(self.email_config["smtp_port"]) enable_auth.set_active(self.email_config["smtp_authentication"]) smtp_username.set_text(self.email_config["smtp_username"]) smtp_password.set_text(self.email_config["smtp_password"]) default_to_address.set_text( self.email_config["default_email_to_address"]) default_subject.set_text(self.email_config["default_email_subject"]) default_message.set_text(self.email_config["default_email_message"]) # Must be last, since it will cause callback on # method on_checkbutton_send_email_on_torrent_events_toggled send_email_checkbox.set_active( self.email_config["send_email_on_torrent_events"]) def update_subscription_list(self, subscriptions_store): subscriptions_store.clear() for key in self.subscriptions.keys(): rssfeed_key = self.subscriptions[key]["rssfeed_key"] subscriptions_store.append([ self.subscriptions[key]["key"], self.subscriptions[key]["active"], self.subscriptions[key]["name"], self.rssfeeds[rssfeed_key]["name"], self.rssfeeds[rssfeed_key]["site"], self.subscriptions[key]["last_match"], self.subscriptions[key]["move_completed"] ]) def update_rssfeeds_list(self, rssfeeds_store): rssfeeds_store.clear() active_subscriptions = self.get_subscription_count_for_feeds() for key in self.rssfeeds.keys(): active_subs = "0" if active_subscriptions.has_key(key): tmp = active_subscriptions[key] active_subs = "%s (%s)" % (tmp[0], tmp[1]) rssfeeds_store.append([ self.rssfeeds[key]["key"], self.rssfeeds[key]["active"], self.rssfeeds[key]["name"], self.rssfeeds[key]["site"], self.rssfeeds[key]["update_interval"], self.rssfeeds[key]["last_update"], active_subs, self.rssfeeds[key]["url"] ]) def update_cookies_list(self, cookies_store): cookies_store.clear() # key, active, site, value for key in self.cookies.keys(): cookies_store.append([ key, self.cookies[key]["active"], self.cookies[key]["site"], encode_cookie_values(self.cookies[key]["value"]) ]) def update_email_messages_list(self, store): store.clear() # key, active, name, to-address, subject, message-content for key in self.email_messages.keys(): store.append([ key, self.email_messages[key]["active"], self.email_messages[key]["name"], self.email_messages[key]["to_address"], self.email_messages[key]["subject"], self.email_messages[key]["message"], ]) def get_subscription_count_for_feeds(self): """Creates the subscription count for each RSS Feed shown in the RSS Feeds list""" result = {} for key in self.rssfeeds.keys(): result[key] = [0, 0] for key in self.subscriptions.keys(): rssfeed_key = self.subscriptions[key]["rssfeed_key"] index = 0 if self.subscriptions[key]["active"] == True else 1 result[rssfeed_key][index] += 1 return result def get_selection_path(self, treeview): """Returns the (first) selected path from a treeview""" tree_selection = treeview.get_selection() model, tree_paths = tree_selection.get_selected_rows() if len(tree_paths) > 0: return tree_paths[0] return None ######################### # Create Subscription list ######################### def on_tooltip_subscription(self, widget, x, y, keyboard_tip, tooltip): if not widget.get_tooltip_context(x, y, keyboard_tip): return False elif widget.get_path_at_pos(x, y) is None: return False model, path2, iter = widget.get_tooltip_context(x, y, keyboard_tip) path, treeColumn, t, r = widget.get_path_at_pos(x, y) if treeColumn.get_title() == "Active": tooltip.set_markup("<b>Double click to toggle</b>") elif treeColumn.get_title() == "Last Matched": tooltip.set_markup( "<b>The publish time of the last torrent that was added by this subscription.</b>" ) else: return False widget.set_tooltip_cell(tooltip, path2, None, None) return True def create_subscription_pane(self): subscriptions_box = self.glade.get_widget("subscriptions_box") subscriptions_window = gtk.ScrolledWindow() subscriptions_window.set_shadow_type(gtk.SHADOW_ETCHED_IN) subscriptions_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) subscriptions_box.pack_start(subscriptions_window, True, True, 0) self.subscriptions_treeview = gtk.TreeView(self.subscriptions_store) self.subscriptions_treeview.get_selection().connect( "changed", self.on_subscription_listitem_activated) self.subscriptions_treeview.connect( "row-activated", self.on_button_edit_subscription_clicked) self.subscriptions_treeview.set_rules_hint(True) self.subscriptions_treeview.connect( 'button-press-event', self.on_subscription_list_button_press_event) self.subscriptions_treeview.connect('query-tooltip', self.on_tooltip_subscription) self.subscriptions_treeview.set_has_tooltip(True) self.create_subscription_columns(self.subscriptions_treeview) #tooltipTreeView = TooltipTreeView(self.subscriptions_treeview) #subscriptions_window.add(tooltipTreeView) subscriptions_window.add(self.subscriptions_treeview) subscriptions_window.show_all() def create_subscription_columns(self, subscriptions_treeView): rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Name", rendererText, text=2) column.set_sort_column_id(2) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Feed name", rendererText, text=3) column.set_sort_column_id(3) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Site", rendererText, text=4) column.set_sort_column_id(4) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Last Matched", rendererText, text=5) column.set_sort_column_id(5) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Move Completed", rendererText, text=6) column.set_sort_column_id(6) subscriptions_treeView.append_column(column) self.run_subscription_menu = gtk.Menu() menuitem = gtk.MenuItem("Run this subscription") self.run_subscription_menu.append(menuitem) menuitem.connect("activate", self.on_button_run_subscription_clicked) def on_button_run_subscription_clicked(self, menuitem): key = get_value_in_selected_row(self.subscriptions_treeview, self.subscriptions_store) if key: self.subscriptions[key]["last_match"] = "" self.save_subscription(self.subscriptions[key]) client.yarss2.initiate_rssfeed_update(None, subscription_key=key) def on_subscription_list_button_press_event(self, treeview, event): """Shows popup on selected row when right clicking""" if event.button != 3: return False x = int(event.x) y = int(event.y) time = event.time pthinfo = treeview.get_path_at_pos(x, y) if pthinfo is not None: path, col, cellx, celly = pthinfo treeview.grab_focus() treeview.set_cursor(path, col, 0) self.run_subscription_menu.popup(None, None, None, event.button, time, data=path) self.run_subscription_menu.show_all() return True ######################### # Create RSS Feeds list ######################### def on_tooltip_rssfeed(self, widget, x, y, keyboard_tip, tooltip): if not widget.get_tooltip_context(x, y, keyboard_tip): return False elif widget.get_path_at_pos(x, y) is None: return False model, path2, iter = widget.get_tooltip_context(x, y, keyboard_tip) path, treeColumn, t, r = widget.get_path_at_pos(x, y) if treeColumn.get_title() == "Active": tooltip.set_markup("<b>Double click to toggle</b>") elif treeColumn.get_title() == "Subscriptions": tooltip.set_markup("<b>Active (Not active)</b>") elif treeColumn.get_title() == "Last Update": tooltip.set_markup("<b>When this RSS Feed was last run</b>") elif treeColumn.get_title() == "Update Interval": tooltip.set_markup( "<b>The time in minutes between each time this RSS Feed is run</b>" ) else: return False widget.set_tooltip_cell(tooltip, path2, None, None) return True def create_rssfeeds_pane(self): rssfeeds_box = self.glade.get_widget("rssfeeds_box") self.rssfeeds_treeview = gtk.TreeView(self.rssfeeds_store) self.rssfeeds_treeview.connect("row-activated", self.on_button_edit_rssfeed_clicked) self.rssfeeds_treeview.get_selection().connect( "changed", self.on_rssfeed_listitem_activated) self.rssfeeds_treeview.set_rules_hint(True) self.rssfeeds_treeview.connect('query-tooltip', self.on_tooltip_rssfeed) self.rssfeeds_treeview.set_has_tooltip(True) self.create_feeds_columns(self.rssfeeds_treeview) rssfeeds_box.add(self.rssfeeds_treeview) rssfeeds_box.show_all() def create_feeds_columns(self, treeView): # key, active, name, site, Update interval, Last update, subscriptions, URL rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Feed Name", rendererText, text=2) column.set_sort_column_id(2) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Site", rendererText, text=3) column.set_sort_column_id(3) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Update Interval", rendererText, text=4) column.set_sort_column_id(4) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Last Update", rendererText, text=5) column.set_sort_column_id(5) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Subscriptions", rendererText, text=6) column.set_sort_column_id(6) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("URL", rendererText, text=7) column.set_sort_column_id(7) treeView.append_column(column) ######################### # Create Messages list ######################### def create_email_messages_pane(self): viewport = self.glade.get_widget("viewport_email_messages_list") self.email_messages_treeview = gtk.TreeView(self.email_messages_store) self.email_messages_treeview.connect( "row-activated", self.on_button_edit_message_clicked) self.email_messages_treeview.get_selection().connect( "changed", self.on_notification_list_listitem_activated) self.email_messages_treeview.connect( 'button-press-event', self.on_notification_list_button_press_event) self.create_messages_columns(self.email_messages_treeview) viewport.add(self.email_messages_treeview) viewport.show_all() def create_messages_columns(self, treeview): #Store: key, active, name, to-address, subject, message-content rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) treeview.append_column(column) tt = gtk.Tooltip() tt.set_text('Double-click to toggle') treeview.set_tooltip_cell(tt, None, None, rendererToggle) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Name", rendererText, text=2) column.set_sort_column_id(2) treeview.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("To address", rendererText, text=3) column.set_sort_column_id(3) treeview.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Subject", rendererText, text=4) column.set_sort_column_id(4) treeview.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Message", rendererText, text=5) column.set_sort_column_id(5) treeview.append_column(column) self.test_email_send_menu = gtk.Menu() menuitem = gtk.MenuItem("Send test email now!") self.test_email_send_menu.append(menuitem) menuitem.connect("activate", self.on_button_send_email_clicked) def on_button_send_email_clicked(self, menuitem): key = get_value_in_selected_row(self.email_messages_treeview, self.email_messages_store) # Send email torrents = ["Torrent title"] self.torrent_handler.send_torrent_email( self.email_config, self.email_messages[key], torrent_name_list=torrents, defered=True, callback_func=self.test_email_callback) def test_email_callback(self, return_value): if return_value: self.log.warn("Test email successfully sent!") else: self.log.warn("Failed to send test email!") def on_notification_list_button_press_event(self, treeview, event): """Shows popup on selected row""" if event.button == 3: x = int(event.x) y = int(event.y) time = event.time pthinfo = treeview.get_path_at_pos(x, y) if pthinfo is not None: path, col, cellx, celly = pthinfo treeview.grab_focus() treeview.set_cursor(path, col, 0) self.test_email_send_menu.popup(None, None, None, event.button, time, data=path) self.test_email_send_menu.show_all() return True ######################### # Create Cookies list ######################### def create_cookies_pane(self): viewport = self.glade.get_widget("viewport_cookies_list") self.cookies_treeview = gtk.TreeView(self.cookies_store) self.cookies_treeview.connect("row-activated", self.on_button_edit_cookie_clicked) self.cookies_treeview.get_selection().connect( "changed", self.on_cookies_listitem_activated) self.create_cookies_columns(self.cookies_treeview) viewport.add(self.cookies_treeview) viewport.show_all() def create_cookies_columns(self, treeview): # store: key, active, site, value rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) treeview.append_column(column) tt = gtk.Tooltip() tt.set_text('Double-click to toggle') treeview.set_tooltip_cell(tt, None, None, rendererToggle) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Site", rendererText, text=2) column.set_sort_column_id(2) treeview.append_column(column) tt2 = gtk.Tooltip() tt2.set_text('Double-click to edit') #treeview.set_tooltip_cell(tt2, None, column, None) treeview.set_has_tooltip(True) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Value", rendererText, text=3) column.set_sort_column_id(3) treeview.append_column(column) ######################################################## ### CALLBACK FUNCTIONS from Glade GUI ######################################################## ############################# # SUBSCRIPTION callbacks ############################# def on_button_add_subscription_clicked(self, Event=None, a=None, col=None): # Check if any RSS Feeds exists, if not, show popup if len(self.rssfeeds.keys()) == 0: md = gtk.MessageDialog( component.get("Preferences").pref_dialog, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "You need to add a RSS Feed before creating subscriptions!") md.run() md.destroy() return fresh_subscription_config = yarss_config.get_fresh_subscription_config( ) subscription_dialog = DialogSubscription( self, self.log, fresh_subscription_config, self.rssfeeds, self.get_move_completed_list(), self.get_download_location_list(), self.email_messages, self.cookies) subscription_dialog.show() def get_move_completed_list(self): values = [] for key in self.subscriptions.keys(): value = self.subscriptions[key]["move_completed"].strip() if len(value) > 0 and not value in values: values.append(value) return values def get_download_location_list(self): values = [] for key in self.subscriptions.keys(): value = self.subscriptions[key]["download_location"].strip() if len(value) > 0 and not value in values: values.append(value) return values def on_button_delete_subscription_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.subscriptions_treeview, self.subscriptions_store) if key: self.save_subscription(None, subscription_key=key, delete=True) def on_button_edit_subscription_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.subscriptions_treeview, self.subscriptions_store) if key: if col and col.get_title() == 'Active': self.subscriptions[key][ "active"] = not self.subscriptions[key]["active"] self.save_subscription(self.subscriptions[key]) else: edit_subscription_dialog = DialogSubscription( self, self.log, self.subscriptions[key], self.rssfeeds, self.get_move_completed_list(), self.get_download_location_list(), self.email_messages, self.cookies) edit_subscription_dialog.show() def on_subscription_listitem_activated(self, treeview): tree, tree_id = self.subscriptions_treeview.get_selection( ).get_selected() if tree_id: self.glade.get_widget('button_edit_subscription').set_sensitive( True) self.glade.get_widget('button_delete_subscription').set_sensitive( True) else: self.glade.get_widget('button_edit_subscription').set_sensitive( False) self.glade.get_widget('button_delete_subscription').set_sensitive( False) ############################# # RSS Feed callbacks ############################# def on_button_add_rssfeed_clicked(self, Event=None, a=None, col=None): # Get fresh config fresh_subscription_config = yarss_config.get_fresh_rssfeed_config( obey_ttl=True) rssfeed_dialog = DialogRSSFeed(self, fresh_subscription_config) rssfeed_dialog.show() def on_button_delete_rssfeed_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.rssfeeds_treeview, self.rssfeeds_store) if not key: return # Check that this rss feed has no subscriptions feed_subscriptions = self.get_subscription_count_for_feeds() # Any registered subscriptions? if sum(feed_subscriptions[key]) > 0: md = gtk.MessageDialog( component.get("Preferences").pref_dialog, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "This RSS Feed have subscriptions registered. Delete subscriptions first!" ) md.run() md.destroy() return else: self.save_rssfeed(None, rssfeed_key=key, delete=True) def on_button_edit_rssfeed_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.rssfeeds_treeview, self.rssfeeds_store) if key: if col and col.get_title() == 'Active': # Check if dummy if key == yarss_config.DUMMY_RSSFEED_KEY: return # Save to config self.rssfeeds[key]["active"] = not self.rssfeeds[key]["active"] self.save_rssfeed(self.rssfeeds[key]) else: edit_rssfeed_dialog = DialogRSSFeed(self, self.rssfeeds[key]) edit_rssfeed_dialog.show() def on_rssfeed_listitem_activated(self, treeview): tree, tree_id = self.rssfeeds_treeview.get_selection().get_selected() if tree_id: self.glade.get_widget('button_edit_rssfeed').set_sensitive(True) self.glade.get_widget('button_delete_rssfeed').set_sensitive(True) else: self.glade.get_widget('button_edit_rssfeed').set_sensitive(False) self.glade.get_widget('button_delete_rssfeed').set_sensitive(False) ############################# # EMAIL MESSAGE callbacks ############################# def on_button_add_message_clicked(self, button): fresh_message_config = yarss_config.get_fresh_message_config() fresh_message_config["to_address"] = self.email_config[ "default_email_to_address"] fresh_message_config["subject"] = self.email_config[ "default_email_subject"] fresh_message_config["message"] = self.email_config[ "default_email_message"] dialog = DialogEmailMessage(self, fresh_message_config) dialog.show() def on_button_edit_message_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.email_messages_treeview, self.email_messages_store) if key: if col and col.get_title() == 'Active': # Save to config self.email_messages[key][ "active"] = not self.email_messages[key]["active"] self.save_email_message(self.email_messages[key]) else: edit_message_dialog = DialogEmailMessage( self, self.email_messages[key]) edit_message_dialog.show() def on_button_delete_message_clicked(self, button): message_key = get_value_in_selected_row(self.email_messages_treeview, self.email_messages_store) if not message_key: return # Check that this message is not used by any subscriptions subscriptions_with_notification = [] # Go through subscriptions and find those with this notification for key in self.subscriptions.keys(): if message_key in self.subscriptions[key][ "email_notifications"].keys(): subscriptions_with_notification.append( self.subscriptions[key]["name"]) # Any subscriptions that use this message? if subscriptions_with_notification: subscription_titles = ''.join([ "* %s\n" % title for title in subscriptions_with_notification ]) md = gtk.MessageDialog( component.get("Preferences").pref_dialog, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE) md.set_markup( "This Email Message is used by the following subscriptions:\n<b>%s</b>" "You must first remove the notication from the subscriptions " "before deleting the email message!" % subscription_titles) md.run() md.destroy() return # Delete from core config self.save_email_message(None, email_message_key=message_key, delete=True) def on_checkbox_email_authentication_toggled(self, button): auth_enable = self.glade.get_widget( "checkbox_email_enable_authentication") self.glade.get_widget("txt_email_username").set_sensitive( auth_enable.get_active()) self.glade.get_widget("txt_email_password").set_sensitive( auth_enable.get_active()) def on_notification_list_listitem_activated(self, treeview): tree, tree_id = self.email_messages_treeview.get_selection( ).get_selected() if tree_id: self.glade.get_widget('button_edit_message').set_sensitive(True) self.glade.get_widget('button_delete_message').set_sensitive(True) else: self.glade.get_widget('button_edit_message').set_sensitive(False) self.glade.get_widget('button_delete_message').set_sensitive(False) ############################## # COOKIE callbacks ############################## def on_button_add_cookie_clicked(self, button): fresh_subscription_config = yarss_config.get_fresh_cookie_config() dialog = DialogCookie(self, fresh_subscription_config) dialog.show() def on_button_edit_cookie_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.cookies_treeview, self.cookies_store) if key: if col and col.get_title() == 'Active': # Save to config self.cookies[key]["active"] = not self.cookies[key]["active"] self.save_cookie(self.cookies[key]) else: dialog_cookie = DialogCookie(self, self.cookies[key]) dialog_cookie.show() def on_button_delete_cookie_clicked(self, button): key = get_value_in_selected_row(self.cookies_treeview, self.cookies_store) if key: # Delete from core config self.save_cookie(None, cookie_key=key, delete=True) def on_cookies_listitem_activated(self, treeview): tree, tree_id = self.cookies_treeview.get_selection().get_selected() if tree_id: self.glade.get_widget('button_edit_cookie').set_sensitive(True) self.glade.get_widget('button_delete_cookie').set_sensitive(True) else: self.glade.get_widget('button_edit_cookie').set_sensitive(False) self.glade.get_widget('button_delete_cookie').set_sensitive(False)
class GtkUI(GtkPluginBase): def enable(self): self.createUI() self.on_show_prefs() # Necessary for the first time when the plugin is installed client.register_event_handler("YARSSConfigChangedEvent", self.cb_on_config_changed_event) client.register_event_handler("GtkUILogMessageEvent", self.cb_on_log_message_arrived_event) def disable(self): component.get("Preferences").remove_page("YaRSS2") component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs) def createUI(self): self.glade = gtk.glade.XML(get_resource("yarss_main.glade")) self.glade.signal_autoconnect({ "on_button_add_subscription_clicked": self.on_button_add_subscription_clicked, "on_button_delete_subscription_clicked": self.on_button_delete_subscription_clicked, "on_button_edit_subscription_clicked" : self.on_button_edit_subscription_clicked, "on_button_add_rssfeed_clicked": self.on_button_add_rssfeed_clicked, "on_button_delete_rssfeed_clicked": self.on_button_delete_rssfeed_clicked, "on_button_edit_rssfeed_clicked" : self.on_button_edit_rssfeed_clicked, "on_button_add_cookie_clicked" : self.on_button_add_cookie_clicked, "on_button_edit_cookie_clicked" : self.on_button_edit_cookie_clicked, "on_button_delete_cookie_clicked": self.on_button_delete_cookie_clicked, "on_button_add_message_clicked" : self.on_button_add_message_clicked, "on_button_edit_message_clicked" : self.on_button_edit_message_clicked, "on_button_delete_message_clicked": self.on_button_delete_message_clicked, "on_checkbox_email_authentication_toggled": self.on_checkbox_email_authentication_toggled, "on_checkbutton_send_email_on_torrent_events_toggled": self.on_checkbutton_send_email_on_torrent_events_toggled }) component.get("Preferences").add_page("YaRSS2", self.glade.get_widget("notebook_main")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) self.gtkui_log = GTKUI_logger(self.glade.get_widget('textview_log')) self.log = Logger(gtkui_logger=self.gtkui_log) self.torrent_handler = TorrentHandler(self.log) self.subscriptions = {} self.rssfeeds = {} self.selected_path_subscriptions = None self.selected_path_rssfeeds = None self.selected_path_email_message = None self.selected_path_cookies = None # key, enabled, name, site, download_location self.subscriptions_store = gtk.ListStore(str, bool, str, str, str, str, str) # key, active, name, site, Update interval, Last update, subscripions, URL self.rssfeeds_store = gtk.ListStore(str, bool, str, str, str, str, str, str) # key, active, site, value self.cookies_store = gtk.ListStore(str, bool, str, str) # key, active, name, to-address, subject, message-content self.email_messages_store = gtk.ListStore(str, bool, str, str, str, str) self.create_subscription_pane() self.create_rssfeeds_pane() self.create_cookies_pane() self.create_email_messages_pane() ############################## # Save data and delete data from core ############################### def save_subscription(self, subscription_data, subscription_key=None, delete=False): """Called by the RSSFeed Dialog""" self.selected_path_subscriptions = self.get_selection_path(self.subscriptions_treeview) client.yarss2.save_subscription(dict_key=subscription_key, subscription_data=subscription_data, delete=delete).addCallback(self.cb_get_config) def save_rssfeed(self, rssfeed_data, rssfeed_key=None, delete=False): """Called by the RSSFeed Dialog""" self.selected_path_rssfeeds = self.get_selection_path(self.rssfeeds_treeview) client.yarss2.save_rssfeed(dict_key=rssfeed_key, rssfeed_data=rssfeed_data, delete=delete).addCallback(self.cb_get_config) def save_email_message(self, message_data, email_message_key=None, delete=False): self.selected_path_email_message = self.get_selection_path(self.email_messages_treeview) client.yarss2.save_email_message(dict_key=email_message_key, message_data=message_data, delete=delete).addCallback(self.cb_get_config) def save_cookie(self, cookie_data, cookie_key=None, delete=False): self.selected_path_cookies = self.get_selection_path(self.cookies_treeview) client.yarss2.save_cookie(dict_key=cookie_key, cookie_data=cookie_data, delete=delete).addCallback(self.cb_get_config) def save_email_config(self, email_config): client.yarss2.save_email_configurations(email_config) def add_torrent(self, torrent_link): client.yarss2.add_torrent(torrent_link) ############################## # Update config and lists data ############################### def on_apply_prefs(self): """Called when the 'Apply' button is pressed""" self.save_configuration_data() def on_checkbutton_send_email_on_torrent_events_toggled(self, button): """Called when email notification button is toggled""" self.save_configuration_data() def save_configuration_data(self): # Save: # Settings -> Email Notifications -> Enable/Disable email notifcations # Settings -> Email configuration -> all fields # Settings -> Default values -> All fields send_emails = self.glade.get_widget("checkbutton_send_email_on_torrent_events").get_active() from_addr = self.glade.get_widget("txt_email_from").get_text() smtp_server = self.glade.get_widget("txt_email_server").get_text() smtp_port = self.glade.get_widget("txt_email_port").get_text() smtp_username = self.glade.get_widget("txt_email_username").get_text() smtp_password = self.glade.get_widget("txt_email_password").get_text() enable_auth = self.glade.get_widget("checkbox_email_enable_authentication").get_active() default_to_address = self.glade.get_widget("txt_default_to_address").get_text() default_subject = self.glade.get_widget("txt_default_subject").get_text() textbuffer = self.glade.get_widget("textview_default_message").get_buffer() default_message = textbuffer.get_text(textbuffer.get_start_iter(), textbuffer.get_end_iter()) self.email_config["send_email_on_torrent_events"] = send_emails self.email_config["from_address"] = from_addr self.email_config["smtp_server"] = smtp_server self.email_config["smtp_port"] = smtp_port self.email_config["smtp_authentication"] = enable_auth self.email_config["smtp_username"] = smtp_username self.email_config["smtp_password"] = smtp_password self.email_config["default_email_to_address"] = default_to_address self.email_config["default_email_subject"] = default_subject self.email_config["default_email_message"] = default_message self.save_email_config(self.email_config) def on_show_prefs(self): """Called when showing preferences window""" client.yarss2.get_config().addCallback(self.cb_get_config) def cb_on_config_changed_event(self, config): """Callback function called on YARSSConfigChangedEvent events""" # Tried to fix error where glade.get_widget("label_status") in dialog_subscription returns None. (Why??) # DeferToThread actually works, but it seems to add a new error, where Deluge crashes, probably # caused by the GUI being updated in another thread than the main thread. # d = threads.deferToThread(self.cb_get_config, config) self.cb_get_config(config) def cb_on_log_message_arrived_event(self, message): """Callback function called on GtkUILogMessageEvent events""" self.gtkui_log.gtkui_log_message(message) def cb_get_config(self, config): """Callback function called after saving data to core""" if config is None: self.log.error("An error has occured. Cannot load data from config") else: self.update_data_from_config(config) def update_data_from_config(self, config): self.subscriptions = config.get('subscriptions', {}) self.rssfeeds = config.get('rssfeeds', {}) self.cookies = config.get('cookies', {}) self.email_messages = config.get('email_messages', {}) self.email_config = config.get('email_configurations', {}) # When connecting to a second host, the glade object returns None for all the fields, # so reload the glade file here to avoid this problem. if self.glade.get_widget("textview_default_message") is None: self.glade = gtk.glade.XML(get_resource("yarss_main.glade")) # Update GUI self.update_subscription_list(self.subscriptions_store) self.update_rssfeeds_list(self.rssfeeds_store) self.update_cookies_list(self.cookies_store) self.update_email_messages_list(self.email_messages_store) # Set selection for each treeview if self.selected_path_subscriptions and self.subscriptions_treeview.get_selection(): self.subscriptions_treeview.get_selection().select_path(self.selected_path_subscriptions) if self.selected_path_rssfeeds and self.rssfeeds_treeview.get_selection(): self.rssfeeds_treeview.get_selection().select_path(self.selected_path_rssfeeds) if self.selected_path_email_message and self.email_messages_treeview.get_selection(): self.email_messages_treeview.get_selection().select_path(self.selected_path_email_message) if self.selected_path_cookies and self.cookies_treeview.get_selection(): self.cookies_treeview.get_selection().select_path(self.selected_path_cookies) # Email configurations send_email_checkbox = self.glade.get_widget("checkbutton_send_email_on_torrent_events") from_addr = self.glade.get_widget("txt_email_from") smtp_server = self.glade.get_widget("txt_email_server") smtp_port = self.glade.get_widget("txt_email_port") smtp_username = self.glade.get_widget("txt_email_username") smtp_password = self.glade.get_widget("txt_email_password") enable_auth = self.glade.get_widget("checkbox_email_enable_authentication") default_to_address = self.glade.get_widget("txt_default_to_address") default_subject = self.glade.get_widget("txt_default_subject") default_message = self.glade.get_widget("textview_default_message") default_message = default_message.get_buffer() from_addr.set_text(self.email_config["from_address"]) smtp_server.set_text(self.email_config["smtp_server"]) smtp_port.set_text(self.email_config["smtp_port"]) enable_auth.set_active(self.email_config["smtp_authentication"]) smtp_username.set_text(self.email_config["smtp_username"]) smtp_password.set_text(self.email_config["smtp_password"]) default_to_address.set_text(self.email_config["default_email_to_address"]) default_subject.set_text(self.email_config["default_email_subject"]) default_message.set_text(self.email_config["default_email_message"]) # Must be last, since it will cause callback on # method on_checkbutton_send_email_on_torrent_events_toggled send_email_checkbox.set_active(self.email_config["send_email_on_torrent_events"]) def update_subscription_list(self, subscriptions_store): subscriptions_store.clear() for key in self.subscriptions.keys(): rssfeed_key = self.subscriptions[key]["rssfeed_key"] subscriptions_store.append([self.subscriptions[key]["key"], self.subscriptions[key]["active"], self.subscriptions[key]["name"], self.rssfeeds[rssfeed_key]["name"], self.rssfeeds[rssfeed_key]["site"], self.subscriptions[key]["last_match"], self.subscriptions[key]["move_completed"]]) def update_rssfeeds_list(self, rssfeeds_store): rssfeeds_store.clear() active_subscriptions = self.get_subscription_count_for_feeds() for key in self.rssfeeds.keys(): active_subs = "0" if active_subscriptions.has_key(key): tmp = active_subscriptions[key] active_subs = "%s (%s)" % (tmp[0], tmp[1]) rssfeeds_store.append([self.rssfeeds[key]["key"], self.rssfeeds[key]["active"], self.rssfeeds[key]["name"], self.rssfeeds[key]["site"], self.rssfeeds[key]["update_interval"], self.rssfeeds[key]["last_update"], active_subs, self.rssfeeds[key]["url"]]) def update_cookies_list(self, cookies_store): cookies_store.clear() # key, active, site, value for key in self.cookies.keys(): cookies_store.append([key, self.cookies[key]["active"], self.cookies[key]["site"], encode_cookie_values(self.cookies[key]["value"])]) def update_email_messages_list(self, store): store.clear() # key, active, name, to-address, subject, message-content for key in self.email_messages.keys(): store.append([key, self.email_messages[key]["active"], self.email_messages[key]["name"], self.email_messages[key]["to_address"], self.email_messages[key]["subject"], self.email_messages[key]["message"], ]) def get_subscription_count_for_feeds(self): """Creates the subscription count for each RSS Feed shown in the RSS Feeds list""" result = {} for key in self.rssfeeds.keys(): result[key] = [0, 0] for key in self.subscriptions.keys(): rssfeed_key = self.subscriptions[key]["rssfeed_key"] index = 0 if self.subscriptions[key]["active"] == True else 1 result[rssfeed_key][index] += 1 return result def get_selection_path(self, treeview): """Returns the (first) selected path from a treeview""" tree_selection = treeview.get_selection() model, tree_paths = tree_selection.get_selected_rows() if len(tree_paths) > 0: return tree_paths[0] return None ######################### # Create Subscription list ######################### def on_tooltip_subscription(self, widget, x, y, keyboard_tip, tooltip): if not widget.get_tooltip_context(x, y, keyboard_tip): return False elif widget.get_path_at_pos(x, y) is None: return False model, path2, iter = widget.get_tooltip_context(x, y, keyboard_tip) path, treeColumn, t, r = widget.get_path_at_pos(x, y) if treeColumn.get_title() == "Active": tooltip.set_markup("<b>Double click to toggle</b>") elif treeColumn.get_title() == "Last Matched": tooltip.set_markup("<b>The publish time of the last torrent that was added by this subscription.</b>") else: return False widget.set_tooltip_cell(tooltip, path2, None, None) return True def create_subscription_pane(self): subscriptions_box = self.glade.get_widget("subscriptions_box") subscriptions_window = gtk.ScrolledWindow() subscriptions_window.set_shadow_type(gtk.SHADOW_ETCHED_IN) subscriptions_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) subscriptions_box.pack_start(subscriptions_window, True, True, 0) self.subscriptions_treeview = gtk.TreeView(self.subscriptions_store) self.subscriptions_treeview.get_selection().connect("changed", self.on_subscription_listitem_activated) self.subscriptions_treeview.connect("row-activated", self.on_button_edit_subscription_clicked) self.subscriptions_treeview.set_rules_hint(True) self.subscriptions_treeview.connect('button-press-event', self.on_subscription_list_button_press_event) self.subscriptions_treeview.connect('query-tooltip', self.on_tooltip_subscription) self.subscriptions_treeview.set_has_tooltip(True) self.create_subscription_columns(self.subscriptions_treeview) #tooltipTreeView = TooltipTreeView(self.subscriptions_treeview) #subscriptions_window.add(tooltipTreeView) subscriptions_window.add(self.subscriptions_treeview) subscriptions_window.show_all() def create_subscription_columns(self, subscriptions_treeView): rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Name", rendererText, text=2) column.set_sort_column_id(2) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Feed name", rendererText, text=3) column.set_sort_column_id(3) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Site", rendererText, text=4) column.set_sort_column_id(4) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Last Matched", rendererText, text=5) column.set_sort_column_id(5) subscriptions_treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Move Completed", rendererText, text=6) column.set_sort_column_id(6) subscriptions_treeView.append_column(column) self.run_subscription_menu = gtk.Menu() menuitem = gtk.MenuItem("Run this subscription") self.run_subscription_menu.append(menuitem) menuitem.connect("activate", self.on_button_run_subscription_clicked) def on_button_run_subscription_clicked(self, menuitem): key = get_value_in_selected_row(self.subscriptions_treeview, self.subscriptions_store) if key: self.subscriptions[key]["last_match"] = "" self.save_subscription(self.subscriptions[key]) client.yarss2.initiate_rssfeed_update(None, subscription_key=key) def on_subscription_list_button_press_event(self, treeview, event): """Shows popup on selected row when right clicking""" if event.button != 3: return False x = int(event.x) y = int(event.y) time = event.time pthinfo = treeview.get_path_at_pos(x, y) if pthinfo is not None: path, col, cellx, celly = pthinfo treeview.grab_focus() treeview.set_cursor(path, col, 0) self.run_subscription_menu.popup(None, None, None, event.button, time, data=path) self.run_subscription_menu.show_all() return True ######################### # Create RSS Feeds list ######################### def on_tooltip_rssfeed(self, widget, x, y, keyboard_tip, tooltip): if not widget.get_tooltip_context(x, y, keyboard_tip): return False elif widget.get_path_at_pos(x, y) is None: return False model, path2, iter = widget.get_tooltip_context(x, y, keyboard_tip) path, treeColumn, t, r = widget.get_path_at_pos(x, y) if treeColumn.get_title() == "Active": tooltip.set_markup("<b>Double click to toggle</b>") elif treeColumn.get_title() == "Subscriptions": tooltip.set_markup("<b>Active (Not active)</b>") elif treeColumn.get_title() == "Last Update": tooltip.set_markup("<b>When this RSS Feed was last run</b>") elif treeColumn.get_title() == "Update Interval": tooltip.set_markup("<b>The time in minutes between each time this RSS Feed is run</b>") else: return False widget.set_tooltip_cell(tooltip, path2, None, None) return True def create_rssfeeds_pane(self): rssfeeds_box = self.glade.get_widget("rssfeeds_box") self.rssfeeds_treeview = gtk.TreeView(self.rssfeeds_store) self.rssfeeds_treeview.connect("row-activated", self.on_button_edit_rssfeed_clicked) self.rssfeeds_treeview.get_selection().connect("changed", self.on_rssfeed_listitem_activated) self.rssfeeds_treeview.set_rules_hint(True) self.rssfeeds_treeview.connect('query-tooltip', self.on_tooltip_rssfeed) self.rssfeeds_treeview.set_has_tooltip(True) self.create_feeds_columns(self.rssfeeds_treeview) rssfeeds_box.add(self.rssfeeds_treeview) rssfeeds_box.show_all() def create_feeds_columns(self, treeView): # key, active, name, site, Update interval, Last update, subscriptions, URL rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Feed Name", rendererText, text=2) column.set_sort_column_id(2) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Site", rendererText, text=3) column.set_sort_column_id(3) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Update Interval", rendererText, text=4) column.set_sort_column_id(4) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Last Update", rendererText, text=5) column.set_sort_column_id(5) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Subscriptions", rendererText, text=6) column.set_sort_column_id(6) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("URL", rendererText, text=7) column.set_sort_column_id(7) treeView.append_column(column) ######################### # Create Messages list ######################### def create_email_messages_pane(self): viewport = self.glade.get_widget("viewport_email_messages_list") self.email_messages_treeview = gtk.TreeView(self.email_messages_store) self.email_messages_treeview.connect("row-activated", self.on_button_edit_message_clicked) self.email_messages_treeview.get_selection().connect("changed", self.on_notification_list_listitem_activated) self.email_messages_treeview.connect('button-press-event', self.on_notification_list_button_press_event) self.create_messages_columns(self.email_messages_treeview) viewport.add(self.email_messages_treeview) viewport.show_all() def create_messages_columns(self, treeview): #Store: key, active, name, to-address, subject, message-content rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) treeview.append_column(column) tt = gtk.Tooltip() tt.set_text('Double-click to toggle') treeview.set_tooltip_cell(tt, None, None, rendererToggle) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Name", rendererText, text=2) column.set_sort_column_id(2) treeview.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("To address", rendererText, text=3) column.set_sort_column_id(3) treeview.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Subject", rendererText, text=4) column.set_sort_column_id(4) treeview.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Message", rendererText, text=5) column.set_sort_column_id(5) treeview.append_column(column) self.test_email_send_menu = gtk.Menu() menuitem = gtk.MenuItem("Send test email now!") self.test_email_send_menu.append(menuitem) menuitem.connect("activate", self.on_button_send_email_clicked) def on_button_send_email_clicked(self, menuitem): key = get_value_in_selected_row(self.email_messages_treeview, self.email_messages_store) # Send email torrents = ["Torrent title"] self.torrent_handler.send_torrent_email(self.email_config, self.email_messages[key], torrent_name_list=torrents, defered=True, callback_func=self.test_email_callback) def test_email_callback(self, return_value): if return_value: self.log.warn("Test email successfully sent!") else: self.log.warn("Failed to send test email!") def on_notification_list_button_press_event(self, treeview, event): """Shows popup on selected row""" if event.button == 3: x = int(event.x) y = int(event.y) time = event.time pthinfo = treeview.get_path_at_pos(x, y) if pthinfo is not None: path, col, cellx, celly = pthinfo treeview.grab_focus() treeview.set_cursor(path, col, 0) self.test_email_send_menu.popup(None, None, None, event.button, time, data=path) self.test_email_send_menu.show_all() return True ######################### # Create Cookies list ######################### def create_cookies_pane(self): viewport = self.glade.get_widget("viewport_cookies_list") self.cookies_treeview = gtk.TreeView(self.cookies_store) self.cookies_treeview.connect("row-activated", self.on_button_edit_cookie_clicked) self.cookies_treeview.get_selection().connect("changed", self.on_cookies_listitem_activated) self.create_cookies_columns(self.cookies_treeview) viewport.add(self.cookies_treeview) viewport.show_all() def create_cookies_columns(self, treeview): # store: key, active, site, value rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("Active", rendererToggle, activatable=1, active=1) column.set_sort_column_id(1) treeview.append_column(column) tt = gtk.Tooltip() tt.set_text('Double-click to toggle') treeview.set_tooltip_cell(tt, None, None, rendererToggle) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Site", rendererText, text=2) column.set_sort_column_id(2) treeview.append_column(column) tt2 = gtk.Tooltip() tt2.set_text('Double-click to edit') #treeview.set_tooltip_cell(tt2, None, column, None) treeview.set_has_tooltip(True) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Value", rendererText, text=3) column.set_sort_column_id(3) treeview.append_column(column) ######################################################## ### CALLBACK FUNCTIONS from Glade GUI ######################################################## ############################# # SUBSCRIPTION callbacks ############################# def on_button_add_subscription_clicked(self,Event=None, a=None, col=None): # Check if any RSS Feeds exists, if not, show popup if len(self.rssfeeds.keys()) == 0: md = gtk.MessageDialog(component.get("Preferences").pref_dialog, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "You need to add a RSS Feed before creating subscriptions!") md.run() md.destroy() return fresh_subscription_config = yarss_config.get_fresh_subscription_config() subscription_dialog = DialogSubscription(self, self.log, fresh_subscription_config, self.rssfeeds, self.get_move_completed_list(), self.get_download_location_list(), self.email_messages, self.cookies) subscription_dialog.show() def get_move_completed_list(self): values = [] for key in self.subscriptions.keys(): value = self.subscriptions[key]["move_completed"].strip() if len(value) > 0 and not value in values: values.append(value) return values def get_download_location_list(self): values = [] for key in self.subscriptions.keys(): value = self.subscriptions[key]["download_location"].strip() if len(value) > 0 and not value in values: values.append(value) return values def on_button_delete_subscription_clicked(self,Event=None, a=None, col=None): key = get_value_in_selected_row(self.subscriptions_treeview, self.subscriptions_store) if key: self.save_subscription(None, subscription_key=key, delete=True) def on_button_edit_subscription_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.subscriptions_treeview, self.subscriptions_store) if key: if col and col.get_title() == 'Active': self.subscriptions[key]["active"] = not self.subscriptions[key]["active"] self.save_subscription(self.subscriptions[key]) else: edit_subscription_dialog = DialogSubscription(self, self.log, self.subscriptions[key], self.rssfeeds, self.get_move_completed_list(), self.get_download_location_list(), self.email_messages, self.cookies) edit_subscription_dialog.show() def on_subscription_listitem_activated(self, treeview): tree, tree_id = self.subscriptions_treeview.get_selection().get_selected() if tree_id: self.glade.get_widget('button_edit_subscription').set_sensitive(True) self.glade.get_widget('button_delete_subscription').set_sensitive(True) else: self.glade.get_widget('button_edit_subscription').set_sensitive(False) self.glade.get_widget('button_delete_subscription').set_sensitive(False) ############################# # RSS Feed callbacks ############################# def on_button_add_rssfeed_clicked(self,Event=None, a=None, col=None): # Get fresh config fresh_subscription_config = yarss_config.get_fresh_rssfeed_config(obey_ttl=True) rssfeed_dialog = DialogRSSFeed(self, fresh_subscription_config) rssfeed_dialog.show() def on_button_delete_rssfeed_clicked(self,Event=None, a=None, col=None): key = get_value_in_selected_row(self.rssfeeds_treeview, self.rssfeeds_store) if not key: return # Check that this rss feed has no subscriptions feed_subscriptions = self.get_subscription_count_for_feeds() # Any registered subscriptions? if sum(feed_subscriptions[key]) > 0: md = gtk.MessageDialog(component.get("Preferences").pref_dialog, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "This RSS Feed have subscriptions registered. Delete subscriptions first!") md.run() md.destroy() return else: self.save_rssfeed(None, rssfeed_key=key, delete=True) def on_button_edit_rssfeed_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.rssfeeds_treeview, self.rssfeeds_store) if key: if col and col.get_title() == 'Active': # Check if dummy if key == yarss_config.DUMMY_RSSFEED_KEY: return # Save to config self.rssfeeds[key]["active"] = not self.rssfeeds[key]["active"] self.save_rssfeed(self.rssfeeds[key]) else: edit_rssfeed_dialog = DialogRSSFeed(self, self.rssfeeds[key]) edit_rssfeed_dialog.show() def on_rssfeed_listitem_activated(self, treeview): tree, tree_id = self.rssfeeds_treeview.get_selection().get_selected() if tree_id: self.glade.get_widget('button_edit_rssfeed').set_sensitive(True) self.glade.get_widget('button_delete_rssfeed').set_sensitive(True) else: self.glade.get_widget('button_edit_rssfeed').set_sensitive(False) self.glade.get_widget('button_delete_rssfeed').set_sensitive(False) ############################# # EMAIL MESSAGE callbacks ############################# def on_button_add_message_clicked(self, button): fresh_message_config = yarss_config.get_fresh_message_config() fresh_message_config["to_address"] = self.email_config["default_email_to_address"] fresh_message_config["subject"] = self.email_config["default_email_subject"] fresh_message_config["message"] = self.email_config["default_email_message"] dialog = DialogEmailMessage(self, fresh_message_config) dialog.show() def on_button_edit_message_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.email_messages_treeview, self.email_messages_store) if key: if col and col.get_title() == 'Active': # Save to config self.email_messages[key]["active"] = not self.email_messages[key]["active"] self.save_email_message(self.email_messages[key]) else: edit_message_dialog = DialogEmailMessage(self, self.email_messages[key]) edit_message_dialog.show() def on_button_delete_message_clicked(self, button): message_key = get_value_in_selected_row(self.email_messages_treeview, self.email_messages_store) if not message_key: return # Check that this message is not used by any subscriptions subscriptions_with_notification = [] # Go through subscriptions and find those with this notification for key in self.subscriptions.keys(): if message_key in self.subscriptions[key]["email_notifications"].keys(): subscriptions_with_notification.append(self.subscriptions[key]["name"]) # Any subscriptions that use this message? if subscriptions_with_notification: subscription_titles = ''.join(["* %s\n" % title for title in subscriptions_with_notification]) md = gtk.MessageDialog(component.get("Preferences").pref_dialog, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE) md.set_markup("This Email Message is used by the following subscriptions:\n<b>%s</b>" "You must first remove the notication from the subscriptions " "before deleting the email message!" % subscription_titles) md.run() md.destroy() return # Delete from core config self.save_email_message(None, email_message_key=message_key, delete=True) def on_checkbox_email_authentication_toggled(self, button): auth_enable = self.glade.get_widget("checkbox_email_enable_authentication") self.glade.get_widget("txt_email_username").set_sensitive(auth_enable.get_active()) self.glade.get_widget("txt_email_password").set_sensitive(auth_enable.get_active()) def on_notification_list_listitem_activated(self, treeview): tree, tree_id = self.email_messages_treeview.get_selection().get_selected() if tree_id: self.glade.get_widget('button_edit_message').set_sensitive(True) self.glade.get_widget('button_delete_message').set_sensitive(True) else: self.glade.get_widget('button_edit_message').set_sensitive(False) self.glade.get_widget('button_delete_message').set_sensitive(False) ############################## # COOKIE callbacks ############################## def on_button_add_cookie_clicked(self, button): fresh_subscription_config = yarss_config.get_fresh_cookie_config() dialog = DialogCookie(self, fresh_subscription_config) dialog.show() def on_button_edit_cookie_clicked(self, Event=None, a=None, col=None): key = get_value_in_selected_row(self.cookies_treeview, self.cookies_store) if key: if col and col.get_title() == 'Active': # Save to config self.cookies[key]["active"] = not self.cookies[key]["active"] self.save_cookie(self.cookies[key]) else: dialog_cookie = DialogCookie(self, self.cookies[key]) dialog_cookie.show() def on_button_delete_cookie_clicked(self, button): key = get_value_in_selected_row(self.cookies_treeview, self.cookies_store) if key: # Delete from core config self.save_cookie(None, cookie_key=key, delete=True) def on_cookies_listitem_activated(self, treeview): tree, tree_id = self.cookies_treeview.get_selection().get_selected() if tree_id: self.glade.get_widget('button_edit_cookie').set_sensitive(True) self.glade.get_widget('button_delete_cookie').set_sensitive(True) else: self.glade.get_widget('button_edit_cookie').set_sensitive(False) self.glade.get_widget('button_delete_cookie').set_sensitive(False)
class Core(CorePluginBase): def __init__(self, name): """Used for tests only""" if name is not "test": super(Core, self).__init__(name) else: # To avoid warnings when running tests self._component_name = name def enable(self, config=None): self.log = yarss2.util.logger.Logger() self.torrent_handler = TorrentHandler(self.log) if config is None: self.yarss_config = YARSSConfig(self.log) else: self.yarss_config = config self.rssfeed_scheduler = RSSFeedScheduler(self.yarss_config, self.log) self.rssfeed_scheduler.enable_timers() self.log.info("Enabled YaRSS2 %s" % yarss2.util.common.get_version()) def disable(self): self.yarss_config.save() self.rssfeed_scheduler.disable_timers() def update(self): pass @export def initiate_rssfeed_update(self, rssfeed_key, subscription_key=None): return self.rssfeed_scheduler.queue_rssfeed_update(rssfeed_key, subscription_key=subscription_key) @export def get_config(self): "Returns the config dictionary" return self.yarss_config.get_config() @export def save_email_configurations(self, email_configurations): conf = {"email_configurations": email_configurations} try: self.yarss_config.set_config(conf) except ValueError as (v): self.log.error("Failed to save email configurations:" + str(v)) @export def save_subscription(self, dict_key=None, subscription_data=None, delete=False): """Saves the subscription in subscription_data. If subscription_data is None and delete=True, delete subscription with key==dict_key """ if delete: if subscription_data is not None: self.log.warn("save_subscription called with delete=True, but rssfeed_data is not None!") else: self.log.info("Deleting Subscription '%s'" % self.yarss_config.get_config()["subscriptions"][dict_key]["name"]) try: return self.yarss_config.generic_save_config("subscriptions", dict_key=dict_key, data_dict=subscription_data, delete=delete) except ValueError as (v): self.log.error("Failed to save subscription:" + str(v)) return None @export def save_rssfeed(self, dict_key=None, rssfeed_data=None, delete=False): """Saves the rssfeed in rssfeed_data. If rssfeed_data is None and delete=True, delete rssfeed with key==dict_key """ try: if delete: if rssfeed_data is not None: self.log.warn("save_rssfeed called with delete=True, but rssfeed_data is not None!") else: self.log.info("Stopping and deleting RSS Feed '%s'" % self.yarss_config.get_config()["rssfeeds"][dict_key]["name"]) config = self.yarss_config.generic_save_config("rssfeeds", dict_key=dict_key, data_dict=rssfeed_data, delete=delete) if delete is True: self.rssfeed_scheduler.delete_timer(dict_key) # Successfully saved rssfeed, check if timer was changed elif config: if self.rssfeed_scheduler.set_timer(rssfeed_data["key"], rssfeed_data["update_interval"]): self.log.info("Scheduled RSS Feed '%s' with interval %s" % (rssfeed_data["name"], rssfeed_data["update_interval"])) return config except ValueError as (v): self.log.error("Failed to save rssfeed:" + str(v)) @export def save_cookie(self, dict_key=None, cookie_data=None, delete=False): """Save cookie to config. If cookie_data is None and delete=True, delete cookie with key==dict_key""" if cookie_data: if type(cookie_data["value"]) is not dict: self.log.error("Cookie value must be a dictionary!") return None try: return self.yarss_config.generic_save_config("cookies", dict_key=dict_key, data_dict=cookie_data, delete=delete) except ValueError as (v): self.log.error("Failed to save cookie:" + str(v)) @export def save_email_message(self, dict_key=None, message_data=None, delete=False): """Save email message to config. If message_data is None, delete message with key==dict_key""" try: return self.yarss_config.generic_save_config("email_messages", dict_key=dict_key, data_dict=message_data, delete=delete) except ValueError as (v): self.log.error("Failed to save email message:" + str(v)) @export def add_torrent(self, torrent_info): site_cookies_dict = get_matching_cookies_dict(self.yarss_config.get_config()["cookies"], torrent_info["link"]) torrent_info["site_cookies_dict"] = site_cookies_dict torrent_download = self.torrent_handler.add_torrent(torrent_info) return torrent_download.to_dict() @export def get_path_completion(self, value): """ Returns the available path completions for the input value. """ return yarss2.util.common.get_path_completion(value)
class Core(CorePluginBase): def __init__(self, name): """Used for tests only""" if name is not "test": super(Core, self).__init__(name) else: # To avoid warnings when running tests self._component_name = name def enable(self, config=None): self.log = yarss2.util.logger.Logger() self.torrent_handler = TorrentHandler(self.log) if config is None: self.yarss_config = YARSSConfig(self.log) else: self.yarss_config = config self.rssfeed_scheduler = RSSFeedScheduler(self.yarss_config, self.log) self.rssfeed_scheduler.enable_timers() self.log.info("Enabled YaRSS2 %s" % yarss2.util.common.get_version()) def disable(self): self.yarss_config.save() self.rssfeed_scheduler.disable_timers() def update(self): pass @export def initiate_rssfeed_update(self, rssfeed_key, subscription_key=None): return self.rssfeed_scheduler.queue_rssfeed_update( rssfeed_key, subscription_key=subscription_key) @export def get_config(self): "Returns the config dictionary" return self.yarss_config.get_config() @export def save_general_config(self, conf): conf = {"general": conf} try: self.yarss_config.set_config(conf) except ValueError as (v): self.log.error("Failed to save general configurations:" + str(v)) @export def save_email_configurations(self, email_configurations): conf = {"email_configurations": email_configurations} try: self.yarss_config.set_config(conf) except ValueError as (v): self.log.error("Failed to save email configurations:" + str(v)) @export def save_subscription(self, dict_key=None, subscription_data=None, delete=False): """Saves the subscription in subscription_data. If subscription_data is None and delete=True, delete subscription with key==dict_key """ if delete: if subscription_data is not None: self.log.warn( "save_subscription called with delete=True, but rssfeed_data is not None!" ) else: self.log.info("Deleting Subscription '%s'" % self.yarss_config.get_config()["subscriptions"] [dict_key]["name"]) try: return self.yarss_config.generic_save_config( "subscriptions", dict_key=dict_key, data_dict=subscription_data, delete=delete) except ValueError as (v): self.log.error("Failed to save subscription:" + str(v)) return None @export def save_rssfeed(self, dict_key=None, rssfeed_data=None, delete=False): """Saves the rssfeed in rssfeed_data. If rssfeed_data is None and delete=True, delete rssfeed with key==dict_key """ try: if delete: if rssfeed_data is not None: self.log.warn( "save_rssfeed called with delete=True, but rssfeed_data is not None!" ) else: self.log.info("Stopping and deleting RSS Feed '%s'" % self.yarss_config.get_config()["rssfeeds"] [dict_key]["name"]) config = self.yarss_config.generic_save_config( "rssfeeds", dict_key=dict_key, data_dict=rssfeed_data, delete=delete) if delete is True: self.rssfeed_scheduler.delete_timer(dict_key) # Successfully saved rssfeed, check if timer was changed elif config: if self.rssfeed_scheduler.set_timer( rssfeed_data["key"], rssfeed_data["update_interval"], rssfeed_data["update_on_startup"]): self.log.info("Scheduled RSS Feed '%s' with interval %s" % (rssfeed_data["name"], rssfeed_data["update_interval"])) return config except ValueError as (v): self.log.error("Failed to save rssfeed:" + str(v)) @export def save_cookie(self, dict_key=None, cookie_data=None, delete=False): """Save cookie to config. If cookie_data is None and delete=True, delete cookie with key==dict_key""" if cookie_data: if type(cookie_data["value"]) is not dict: self.log.error("Cookie value must be a dictionary!") return None try: return self.yarss_config.generic_save_config("cookies", dict_key=dict_key, data_dict=cookie_data, delete=delete) except ValueError as (v): self.log.error("Failed to save cookie:" + str(v)) @export def save_email_message(self, dict_key=None, message_data=None, delete=False): """Save email message to config. If message_data is None, delete message with key==dict_key""" try: return self.yarss_config.generic_save_config( "email_messages", dict_key=dict_key, data_dict=message_data, delete=delete) except ValueError as (v): self.log.error("Failed to save email message:" + str(v)) @export def send_test_email(self, email_key): """ Send a test email """ self.email_config = self.yarss_config.get_config().get( 'email_configurations', {}) self.email_messages = self.yarss_config.get_config().get( 'email_messages', {}) torrents = ["Torrent title"] return send_torrent_email( self.email_config, self.email_messages[email_key], subscription_data={"name": "Test subscription"}, torrent_name_list=torrents, deferred=True) @export def add_torrent(self, torrent_info): site_cookies_dict = get_matching_cookies_dict( self.yarss_config.get_config()["cookies"], torrent_info["link"]) torrent_info["site_cookies_dict"] = site_cookies_dict if "rssfeed_key" in torrent_info: rssfeed_data = self.yarss_config.get_config()["rssfeeds"][ torrent_info["rssfeed_key"]] torrent_info["user_agent"] = get_user_agent( rssfeed_data=rssfeed_data) torrent_download = self.torrent_handler.add_torrent(torrent_info) return torrent_download.to_dict() @export def get_completion_paths(self, value): """ Returns the available path completions for the input value. """ return yarss2.util.common.get_completion_paths(value)
def test_get_torrent_magnet(self): handler = TorrentHandler(self.log) torrent_info = {"link": "magnet:hash"} download = handler.get_torrent(torrent_info) self.assertTrue(download.is_magnet)