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 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)
Exemple #4
0
 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')
Exemple #11
0
 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 __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
Exemple #18
0
    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
Exemple #21
0
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)
Exemple #22
0
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)
Exemple #23
0
    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()
Exemple #24
0
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)
Exemple #27
0
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)