RSS Plugin - Final Release

Suggest, post, or discuss plugins for Deluge
Mait

Re: RSS Plugin - Final Release

Post by Mait »

When I am checking this feed (http://isohunt.com/js/rss/?iht=), found errors in .xsession-errors.

Code: Select all

Attempting to parse isohunt new torrents
Parsed isoHunt All
Traceback (most recent call last):
  File "/usr/share/deluge/plugins/SimpleRSS/plugin.py", line 283, in chkfeeds_clicked
    self.checkfeeds()
  File "/usr/share/deluge/plugins/SimpleRSS/plugin.py", line 305, in checkfeeds
    tmplist = [(entry["date_parsed"], name, entry["title"], entry.enclosures[0].href) for entry in entries]
  File "/usr/share/deluge/plugins/SimpleRSS/feedparser.py", line 236, in __getattr__
    raise AttributeError, "object has no attribute '%s'" % key
AttributeError: object has no attribute 'enclosures'
checking for valid crashreport now
How can I help to solve this problem?
daddy
Seeder
Seeder
Posts: 100
Joined: Sun Jul 22, 2007 12:14 am

Re: RSS Plugin - Final Release

Post by daddy »

Mait,

Open up /usr/share/deluge/plugins/SimpleRSS/plugin.py and change every occurrence of "entry.enclosures[0].href" to "entry.links[0].href" (without the quotes, obviously).
Mait

Re: RSS Plugin - Final Release

Post by Mait »

daddy wrote:Mait,

Open up /usr/share/deluge/plugins/SimpleRSS/plugin.py and change every occurrence of "entry.enclosures[0].href" to "entry.links[0].href" (without the quotes, obviously).
Thanks to reply. But still not solved.

I see similar error in .xsession-errors with this feed fetching.

http://www.torrentz.com/feed?q=site%3Averified

Code: Select all

Attempting to parse torrentz
Parsed Torrentz
Traceback (most recent call last):
  File "/usr/share/deluge/plugins/SimpleRSS/plugin.py", line 283, in chkfeeds_clicked
    self.checkfeeds()
  File "/usr/share/deluge/plugins/SimpleRSS/plugin.py", line 305, in checkfeeds
    tmplist = [(entry["date_parsed"], name, entry["title"], entry.links[0].href) for entry in entries]
  File "/usr/share/deluge/plugins/SimpleRSS/feedparser.py", line 236, in __getattr__
    raise AttributeError, "object has no attribute '%s'" % key
AttributeError: object has no attribute 'links'
checking for valid crashreport now
I'm using Ubuntu Gutsy 7.10

'apt-cache show deluge-torrent' tells deluge version '0.5.4.1-1ubuntu1'

This is my modified '/usr/share/deluge/plugins/SimpleRSS/plugin.py'

Code: Select all

class plugin_SimpleRSS:
    def __init__(self, path, deluge_core, deluge_interface):
        #set up system thingies
        import gtk, gtk.glade, os, ConfigParser, feedparser
        import deluge.common, deluge.dgtk, deluge.pref
        from time import asctime
        self.path = path
        self.core = deluge_core
        self.interface = deluge_interface
        #set up feeds file
        self.feeds_config = ConfigParser.ConfigParser()
        self.feeds_file = deluge.common.CONFIG_DIR + "/feeds.conf"
        if not os.path.isfile(self.feeds_file):
            f = open(self.feeds_file, mode='w')
            f.flush()
            f.close()
        self.feeds_config.read(self.feeds_file)
        #set up filters file
        self.filters_config = ConfigParser.ConfigParser()
        self.filters_file = deluge.common.CONFIG_DIR + "/filters.conf"
        if not os.path.isfile(self.filters_file):
            f = open(self.filters_file, mode='w')
            f.flush()
            f.close()
        self.filters_config.read(self.filters_file)
        #set up the preferences dialog
        glade = gtk.glade.XML(path + "/rss.glade")
        self.dlg = glade.get_widget("dialog")
        self.dlg.set_position(gtk.WIN_POS_CENTER)
        self.dlg.set_icon_from_file(self.path + "/rss.png")
        #set up the feeds list viewer
        self.feeds_view = glade.get_widget("feeds_view")
        model = gtk.ListStore(str, str, str)
        self.feeds_view.set_model(model)
        deluge.dgtk.add_text_column(self.feeds_view, _("Name"), 0)
        deluge.dgtk.add_text_column(self.feeds_view, _("URL"), 1)
        deluge.dgtk.add_text_column(self.feeds_view, _("Last Entry Date"), 2)
        #set up the torrents list viewer
        self.torrents_view = glade.get_widget("torrents_view")
        model = gtk.ListStore(str, str, str, str)
        self.torrents_view.set_model(model)
        deluge.dgtk.add_text_column(self.torrents_view, _("Feed"), 0)
        deluge.dgtk.add_text_column(self.torrents_view, _("Name"), 1)
        deluge.dgtk.add_text_column(self.torrents_view, _("URL"), 2)
        deluge.dgtk.add_text_column(self.torrents_view, _("Date"), 3)
        # Setup the filters list viewer
        self.filters_view = glade.get_widget("filters_view")
        model = gtk.ListStore(str)
        self.filters_view.set_model(model)
        deluge.dgtk.add_text_column(self.filters_view, _("Name"), 0)
        # set up the feed choice combobox
        self.feedchoice_combo = glade.get_widget("feedchoice_combo")
        model = gtk.ListStore(str)
        self.feedchoice_combo.set_model(model)
        cell = gtk.CellRendererText()
        self.feedchoice_combo.pack_start(cell, True)
        self.feedchoice_combo.add_attribute(cell, 'text', 0) 
        # set up the torrents feed choice combobox
        self.torrents_fcc = glade.get_widget("torrents_fcc")
        model = gtk.ListStore(str)
        self.torrents_fcc.set_model(model)
        cell = gtk.CellRendererText()
        self.torrents_fcc.pack_start(cell, True)
        self.torrents_fcc.add_attribute(cell, 'text', 0) 
        #set up the rest of the GUI elements
        self.name_entry = glade.get_widget("name_entry")        
        self.url_entry = glade.get_widget("url_entry")
        self.button_addfeed = glade.get_widget("button_addfeed")
        self.button_delfeed = glade.get_widget("button_delfeed")
        self.chkfeeds = glade.get_widget("chkfeeds")
        self.filtername_entry = glade.get_widget("filtername_entry")
        self.filterexp_entry = glade.get_widget("filterexp_entry")
        self.button_delfilter = glade.get_widget("button_delfilter")
        self.checkonstart_button = glade.get_widget("checkonstart_button")
        self.update_entry = glade.get_widget("update_entry")
        #Connect event signals
        self.filters_view.connect("cursor-changed", self.filter_row_clicked)
        dic = {    "addfeed_clicked" : self.addfeed_clicked,
                "delfeed_clicked" : self.delfeed_clicked,
                "addfilter_clicked" : self.addfilter_clicked,
                "delfilter_clicked" : self.delfilter_clicked,
                "row_clicked" : self.row_clicked,
                "feedtext_changed" : self.feedtext_changed,
                "filtername_lostfocus" : self.filtername_lostfocus,
                "filterexp_lostfocus" : self.filterexp_lostfocus,
                "feedchoice_combo_changed" : self.feedchoice_combo_changed,
                "torrents_fcc_changed" : self.torrents_fcc_changed,
                "torrents_view_row_activated" : self.torrents_view_row_activated,
                "chkfeeds_clicked" : self.chkfeeds_clicked,
                "cancel_clicked" : self.dialog_cancel,
                "ok_clicked" : self.dialog_ok }
        glade.signal_autoconnect(dic)
        self.feeds_view.get_selection().set_select_function(self.row_clicked)
        self.timer = 0
        self.torrents_list = []
        #self.checkfeeds()
        # Access the interface's toolbar
        self.toolbar = self.interface.toolbar
        # Make a toolbar button
        icon = gtk.Image()
        icon.set_from_file(self.path + "/rss.png") # Toolbar items should be 22x22 pixel images
        self.button = gtk.ToolButton(icon_widget=icon, label=_("RSS"))
        self.ttips = gtk.Tooltips()
        self.button.set_tooltip(self.ttips, _("SimpleRSS Broadcatcher"))
        self.button.connect("clicked", self.rss_clicked) # Connect the signal handler for the button
        self.toolbar.add(self.button) # Add button to toolbar
        self.button.show_all() # Show the button
        self.checkonstart = False
        #load options
        if self.feeds_config.has_option("DEFAULT", "interval"):
            self.interval = self.feeds_config.getint("DEFAULT", "interval")
            self.update_entry.set_text(self.feeds_config.get("DEFAULT", "interval"))
        else:
            self.interval = 900
            self.feeds_config.set("DEFAULT", "interval", 900)
        if self.feeds_config.has_option("DEFAULT", "checkonstart"):
            self.checkonstart = self.feeds_config.getboolean("DEFAULT", "checkonstart")
            self.checkonstart_button.set_active(self.checkonstart)
        else:
            self.checkonstart = False
            self.feeds_config.set("DEFAULT", "checkonstart", False)
        if self.checkonstart_button.get_active():
            self.timer = self.interval - 5

    def rss_clicked(self, button):
        self.configure(self)
    
    def unload(self):
        self.toolbar.remove(self.button) # Remove the button from the toolbar
        f = open(self.feeds_file, "w")
        self.feeds_config.write(f)
        f.close()
    
    def feedtext_changed(self, args):
        a = (self.name_entry.get_text() != "")
        b = (self.url_entry.get_text() != "")
        if(a and b):
            self.button_addfeed.set_sensitive(1)
        else:
            self.button_addfeed.set_sensitive(0)

    def addfeed_clicked(self, args):
        self.feeds_view.get_model().append([self.name_entry.get_text(),
                    self.url_entry.get_text(), ""])
        self.feedchoice_combo.append_text(self.name_entry.get_text())
        self.torrents_fcc.append_text(self.name_entry.get_text())
        self.feeds_config.add_section(self.name_entry.get_text())
        self.feeds_config.set(self.name_entry.get_text(), "url", self.url_entry.get_text())
        self.feeds_config.set(self.name_entry.get_text(), "lastchecked", "")
        self.name_entry.set_text("")
        self.url_entry.set_text("")

    def delfeed_clicked(self, args):
        (model, selection) = self.feeds_view.get_selection().get_selected()
        text = self.feeds_view.get_model().get_value(selection, 0)
        model2 = self.feedchoice_combo.get_model()
        model3 = self.torrents_fcc.get_model()
        the_iter = model2.get_iter_first()
        print text
        while the_iter is not None:
            print model2.get_value(the_iter, 0)
            if (model2.get_value(the_iter, 0) == text):
                remove_iter = the_iter
            the_iter = model2.iter_next(the_iter)
        model2.remove(remove_iter)
        the_iter = model3.get_iter_first()
        while the_iter is not None:
            print model3.get_value(the_iter, 0)
            if (model3.get_value(the_iter, 0) == text):
                remove_iter = the_iter
            the_iter = model3.iter_next(the_iter)
        model3.remove(remove_iter)
        model.remove(selection)
        for filt in self.filters_config.sections():
            if self.filters_config.get(filt, "feed") == text:
                self.filters_config.set(filt, "feed", "All")
        self.feeds_config.remove_section(text)
        self.button_delfeed.set_sensitive(0)
        
    def row_clicked(self, args):
        self.button_delfeed.set_sensitive(1)
        return True

    def addfilter_clicked(self, args):
        unique = True
        for filt in self.filters_config.sections():
            if filt == _("New Filter"):
                unique = False

        if unique:
            self.current_filter = _("New Filter")
            self.filters_config.add_section(_("New Filter"))
            new_iter = self.filters_view.get_model().append([_("New Filter")])
            self.filters_view.get_selection().select_iter(new_iter)
            self.filters_config.set(_("New Filter"), "filterexp", "")
            self.filters_config.set(_("New Filter"), "feed", "All")
            self.filtername_entry.set_text(_("New Filter"))
            self.feedchoice_combo.set_active(0)

            self.filtername_entry.set_sensitive(1)
            self.filterexp_entry.set_sensitive(1)
            self.feedchoice_combo.set_sensitive(1)
            self.filterexp_entry.set_text("")
            self.filtername_entry.grab_focus()
            self.button_delfilter.set_sensitive(1)

    def delfilter_clicked(self, args):
        model, selection = self.filters_view.get_selection().get_selected()
        self.filters_config.remove_section(self.current_filter)
        model.remove(selection)
        self.current_filter = None

        self.filtername_entry.set_text("")
        self.filterexp_entry.set_text("")
        self.feedchoice_combo.set_active(-1)
        self.filtername_entry.set_sensitive(0)
        self.filterexp_entry.set_sensitive(0)
        self.feedchoice_combo.set_sensitive(0)
        self.button_delfilter.set_sensitive(0)

    def filter_row_clicked(self, widget):
        selection = self.filters_view.get_selection()
        model, selection_iter = selection.get_selected()
        print model
        print selection_iter
        self.current_filter = self.filters_view.get_model().get_value(selection_iter, 0)
        self.filtername_entry.set_text(self.current_filter)
        self.filterexp_entry.set_text(self.filters_config.get(self.current_filter, "filterexp"))
        feed = self.filters_config.get(self.current_filter, "feed")
        model2 = self.feedchoice_combo.get_model()
        the_iter = model2.get_iter_first()
        while the_iter is not None:
            #print model2.get_value(the_iter, 0)
            if (model2.get_value(the_iter, 0) == feed):
                set_iter = the_iter
            the_iter = model2.iter_next(the_iter)
        self.feedchoice_combo.set_active_iter(set_iter)

        self.filtername_entry.set_sensitive(1)
        self.filterexp_entry.set_sensitive(1)
        self.feedchoice_combo.set_sensitive(1)
        self.button_delfilter.set_sensitive(1)

    def filtername_lostfocus(self, args, spare):
        (model, selection) = self.filters_view.get_selection().get_selected()
        old_filtername = self.filters_view.get_model().get_value(selection, 0)
        self.filters_config.remove_section(old_filtername)
        model.remove(selection)

        self.current_filter = self.filtername_entry.get_text()
        new_iter = self.filters_view.get_model().append([self.current_filter])
        self.filters_view.get_selection().select_iter(new_iter)
        self.filters_config.add_section(self.current_filter)
        self.filters_config.set(self.current_filter, "filterexp", self.filterexp_entry.get_text())
        self.filters_config.set(self.current_filter, "feed", self.feedchoice_combo.get_active_text())

    def filterexp_lostfocus(self, args, spare):
        self.filters_config.set(self.current_filter, "filterexp", self.filterexp_entry.get_text())

    def feedchoice_combo_changed(self, args):
        self.filters_config.set(self.current_filter, "feed", self.feedchoice_combo.get_active_text())

    def torrents_fcc_changed(self, args):
        model = self.torrents_view.get_model()
        model.clear()
        if self.torrents_fcc.get_active_text() == _("All"):
            for (date, feed, title, link) in self.torrents_list:
                self.torrents_view.get_model().append((feed, title, link, date))
        else:
            for (date, feed, title, link) in self.torrents_list:
                if feed == self.torrents_fcc.get_active_text():
                    self.torrents_view.get_model().append((feed, title, link, date))

    def torrents_view_row_activated(self, widget, spare1, spare2):
        selection = widget.get_selection()
        model, selection_iter = selection.get_selected()
        self.interface.interactive_add_torrent_url(widget.get_model().get_value(selection_iter, 2))
        

    def chkfeeds_clicked(self, args):
        self.checkfeeds()

    def checkfeeds(self):
        import feedparser, datetime
        from time import asctime, strptime

        avail = {}
        sorted = {}
        self.torrents_list = []
        for name in self.feeds_config.sections():
            print "Attempting to parse " + name
            tmp = feedparser.parse(self.feeds_config.get(name, "url"))
            try:
                print "Parsed " + tmp['feed']['title']
                avail[name] = True
            except:
                print "Failed to download/parse " + name
                avail[name] = False
            if avail[name]:
                entries = []
                entries.extend( tmp[ "items" ] )
                decorated = [(entry["date_parsed"], entry) for entry in entries]
                tmplist = [(entry["date_parsed"], name, entry["title"], entry.links[0].href) for entry in entries]
                decorated.sort()
                self.torrents_list.extend(tmplist)
                #decorated.reverse() # for most recent entries first
                sorted[name] = [entry for (date,entry) in decorated]

        model = self.torrents_view.get_model()
        model.clear()
        self.torrents_list.sort()
        self.torrents_list.reverse()
        #self.torrents_view.get_model().append([entry for entry in self.torrents_list])
        for (date,feed,title,link) in self.torrents_list:
            self.torrents_view.get_model().append((feed, title, link, date))
        #for key in sorted.keys():
        #    print "listing entries in " + key
        #    
        #    for entry in sorted[key]:
        #        print entry.title
        #        for enclosure in entry.enclosures:
        #            self.torrents_view.get_model().append( (key, entry.title, enclosure.href, entry.date_parsed) )

        checked = {}
        for name in self.filters_config.sections():
            checkfiltername = name
            checkfilterexp = self.filters_config.get(name, "filterexp")
            checkfilterfeed = self.filters_config.get(name, "feed")
            print "filter: " + checkfiltername
            print "search: " + checkfilterexp
            print "feed: " + checkfilterfeed
            if checkfilterfeed == "All":
                #print "made it to 'All'"
                for feedname in sorted.keys():
                    if avail[feedname]:
                        print feedname + " last checked: " + self.feeds_config.get(feedname, "lastchecked")
                        if self.feeds_config.get(feedname, "lastchecked") != "":
                            lastchecked = strptime(self.feeds_config.get(feedname, "lastchecked"))
                        else:
                            lastchecked = strptime(asctime(sorted[feedname][0].date_parsed))
                        #print "searching feed: " + feedname
                        for entry in sorted[feedname]:
                            #print entry.title + ": " + asctime(entry.date_parsed)
                            if (strptime(asctime(entry.date_parsed)) > lastchecked):
                                #print entry.date_parsed
                                #print " > "
                                #print lastchecked
                                if entry.title.find(checkfilterexp) != -1:
                                    #print "contains" + checkfilterexp
                                    for enclosure in entry.enclosures:
                                        print enclosure.href
                                        self.interface.interactive_add_torrent_url(enclosure.href)
                                        #self.feeds_config.set(feedname, "lastchecked", asctime(entry.date_parsed))
            else:
                if avail[checkfilterfeed]:
                    print "searching feed: " + checkfilterfeed
                    if self.feeds_config.get(checkfilterfeed, "lastchecked") != "":
                        lastchecked = strptime(self.feeds_config.get(checkfilterfeed, "lastchecked"))
                    else:
                        #print sorted[checkfilterfeed][1].date_parsed
                        lastchecked = strptime(asctime(sorted[checkfilterfeed][0].date_parsed))
                    print "lastchecked: " + asctime(lastchecked)
                    for entry in sorted[checkfilterfeed]:
                        #print entry.title + ": " + asctime(entry.date_parsed)
                        if (strptime(asctime(entry.date_parsed)) > lastchecked):
                            #print entry.date_parsed
                            #print " > "
                            #print lastchecked
                            if (entry.title.find(checkfilterexp) != -1):
                                #print "contains" + checkfilterexp
                                for enclosure in entry.enclosures:
                                    print enclosure.href
                                    self.interface.interactive_add_torrent_url(enclosure.href)
                                    #self.feeds_config.set(checkfilterfeed, "lastchecked", asctime(entry.date_parsed))

        for name in avail.keys():
            if avail[name]:
                self.feeds_config.set(name, "lastchecked", asctime(sorted[name][len(sorted[name])-1].date_parsed))

        self.timer = 0




    def configure(self, widget=None):
        import gtk, gtk.glade
        from deluge import common
        self.dlg.show_all()
        model = self.feeds_view.get_model()
        model.clear()
        model2 = self.feedchoice_combo.get_model()
        model2.clear()
        model3 = self.filters_view.get_model()
        model3.clear()
        model4 = self.torrents_fcc.get_model()
        model4.clear()
        self.filtername_entry.set_text("")
        self.filterexp_entry.set_text("")
        self.name_entry.set_text("")
        self.url_entry.set_text("")
        self.feedchoice_combo.append_text(_("All"))
        self.torrents_fcc.append_text(_("All"))
        self.torrents_fcc.set_active(0)
        for name in self.feeds_config.sections():
            self.feeds_view.get_model().append( (name, self.feeds_config.get(name, "url"), self.feeds_config.get(name, "lastchecked") ) )
            self.feedchoice_combo.append_text(name)
            self.torrents_fcc.append_text(name)
        for filters in self.filters_config.sections():
            self.filters_view.get_model().append( ([filters]) )
        #self.checkfeeds()
        self.button_addfeed.set_sensitive(0)
        self.button_delfeed.set_sensitive(0)
        self.filtername_entry.set_sensitive(0)
        self.filterexp_entry.set_sensitive(0)
        self.feedchoice_combo.set_sensitive(0)
        self.button_delfilter.set_sensitive(0)
        self.update_entry.set_text(str(self.interval))
        self.checkonstart_button.set_active(self.checkonstart)

    def dialog_ok(self, source):
        self.dlg.hide_all()
        self.interval = int(self.update_entry.get_text())
        self.feeds_config.set("DEFAULT", "interval", self.update_entry.get_text())
        self.feeds_config.set("DEFAULT", "checkonstart", self.checkonstart_button.get_active())
        f = open(self.filters_file, "w")
        self.filters_config.write(f)
        f.close()
        f = open(self.feeds_file, "w")
        self.feeds_config.write(f)
        f.close()

    def dialog_cancel(self, source):
        self.dlg.hide_all()

    def update(self):
        self.timer += 1
        if self.timer >= self.interval:
            import threading

            print "BONG!"
            threading.Thread(target=self.checkfeeds).start
            self.timer = 0
daddy
Seeder
Seeder
Posts: 100
Joined: Sun Jul 22, 2007 12:14 am

Re: RSS Plugin - Final Release

Post by daddy »

What are your feeds? Feel free to PM them to me if you don't feel like sharing with the world.
crazygoatidol
New User
New User
Posts: 4
Joined: Thu Oct 25, 2007 1:25 pm

Re: RSS Plugin - Final Release

Post by crazygoatidol »

I need a little help with a filter, I think. I have a couple of feeds, and I want to grab every torrent in them. Under the Torrents tab, all of the feeds have a list of torrent files, and double clicking them loads them like normal. I created a filter, using all feeds, and searching for * under the filter exp. I've also tried leaving it blank, but it doesn't seem to make the torrents load. Any ideas?

Thanks.
daddy
Seeder
Seeder
Posts: 100
Joined: Sun Jul 22, 2007 12:14 am

Re: RSS Plugin - Final Release

Post by daddy »

crazygoatidol wrote:I need a little help with a filter, I think. I have a couple of feeds, and I want to grab every torrent in them. Under the Torrents tab, all of the feeds have a list of torrent files, and double clicking them loads them like normal. I created a filter, using all feeds, and searching for * under the filter exp. I've also tried leaving it blank, but it doesn't seem to make the torrents load. Any ideas?
Do the items have a character common to all of them? A dot? A space? A hyphen? "avi"?
crazygoatidol
New User
New User
Posts: 4
Joined: Thu Oct 25, 2007 1:25 pm

Re: RSS Plugin - Final Release

Post by crazygoatidol »

They should all probably have a dot in them. If I change the filter now, should it download everything in the backlog, or just new stuff that comes in?

Actually, I went ahead and made the change, and nothing happened, which I think is the expected behavior, if I'm reading the prior posts correctly.
Post Reply