~entertainer-releases/entertainer/trunk

« back to all changes in this revision

Viewing changes to entertainerlib/backend/components/feeds/feed_utils.py

  • Committer: Matt Layman
  • Date: 2010-04-03 15:10:28 UTC
  • mfrom: (403.1.12 bye-feedz)
  • Revision ID: laymansterms.dev@gmail.com-20100403151028-fxbe7g64z129ohu6
All feed code is now removed. Lots of pylint cleanup too. (Matt Layman)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
2
 
'''Utilities for fetching feeds'''
3
 
 
4
 
import os
5
 
import urllib
6
 
from xml.dom import minidom
7
 
 
8
 
import gtk
9
 
 
10
 
from entertainerlib.configuration import Configuration
11
 
 
12
 
 
13
 
class FeedEntryParser:
14
 
    """Will handle encoding and html for displaying feed entries"""
15
 
 
16
 
    def strip_tags(self, text, valid_tags=None):
17
 
        """
18
 
        Strips a text string of all markup tags except the tags specified
19
 
        @param text the text to be stripped
20
 
        @param valid_tags a list of the allowed tags
21
 
        """
22
 
 
23
 
        #setup variables
24
 
        valid_tag_list = []
25
 
        output = ""
26
 
        in_tag = False
27
 
        in_tag_name = False
28
 
        tag = ""
29
 
        tag_attributes = ""
30
 
 
31
 
        if valid_tags is None:
32
 
            valid_tags = []
33
 
 
34
 
        #append closing tags to tag list
35
 
        for next_tag in valid_tags:
36
 
            valid_tag_list.append(next_tag)
37
 
            valid_tag_list.append("/"+next_tag)
38
 
 
39
 
        #setup a list to parse from input
40
 
        parse_list = list(text)
41
 
 
42
 
        i = 0
43
 
        while i < len(parse_list):
44
 
            c = parse_list[i]
45
 
            if c == "<":
46
 
                #we are into the tag and the tag name
47
 
                in_tag = True
48
 
                in_tag_name = True
49
 
                parse_list.pop(i)
50
 
            elif in_tag:
51
 
                #we are in a tag
52
 
                if c == " " and in_tag_name:
53
 
                    #tag name has ended we are now into tag_attributes
54
 
                    in_tag_name = False
55
 
                    tag_attributes += parse_list.pop(i)
56
 
                elif c == ">":
57
 
                    #tag has finished let's clean up
58
 
                    in_tag = False
59
 
                    parse_list.pop(i)
60
 
                    #check if tag matches
61
 
                    if tag in valid_tag_list:
62
 
                        output += ("<" + tag + tag_attributes + ">")
63
 
                    tag = ""
64
 
                    tag_attributes = ""
65
 
                elif in_tag_name:
66
 
                    #we are in a tag name lets append current char to tag
67
 
                    tag += parse_list.pop(i)
68
 
                else:
69
 
                    #we are in tag attributes lets append current char to
70
 
                    #attributes
71
 
                    tag_attributes += parse_list.pop(i)
72
 
            else:
73
 
                #not in a tag so append current char to output
74
 
                output += parse_list.pop(i)
75
 
 
76
 
        return output
77
 
 
78
 
    def strip_non_pango_tags(self, text):
79
 
        """
80
 
        Strips a text string of all non-pango tags
81
 
        @param text the text to be stripped
82
 
        """
83
 
        return self.strip_tags(text,
84
 
            ["span", "b", "big", "i", "s", "sub", "sup", "small", "tt", "u"])
85
 
 
86
 
    def convert(self, text):
87
 
        """
88
 
        This converts a text string into a format acceptable by a clutter
89
 
        label object
90
 
 
91
 
        @param text the text to be converted
92
 
        """
93
 
 
94
 
        return self.strip_non_pango_tags(text).replace('&nbsp;', ' ')
95
 
 
96
 
 
97
 
class OPMLParser:
98
 
    """Enables handling and parsing of opml files"""
99
 
 
100
 
    def get_rss_feeds(self, filename):
101
 
        """
102
 
        returns list of rss feeds in the opml file
103
 
        @param filename The OPML file
104
 
        @return list(String) List of RSS feed urls
105
 
        """
106
 
        feeds = []
107
 
        if os.path.isfile(filename):
108
 
            #this loads the xml from the opml file into xmldoc
109
 
            xmldoc = minidom.parse(filename)
110
 
        else:
111
 
            xmldoc = minidom.parse(urllib.urlopen(filename))
112
 
        #the rss feeds are in the xmlUrl attributes of the outline tags
113
 
        #we loop through all the outline nodes in the opml file and add
114
 
        #the contents of any xmlUrl attributes to the feeds variable
115
 
        for node in xmldoc.getElementsByTagName('outline'):
116
 
            url = node.getAttribute('xmlUrl')
117
 
            #drop any items which are .opml files or empty string
118
 
            #We do not recursively parse opml links as we could end up with an
119
 
            #infinite loop
120
 
            if (url.strip() != "") and ((url.strip() [-5:]) != ".opml"):
121
 
                feeds.append(url)
122
 
        #returns the list of rss feeds from the opml file
123
 
        return feeds
124
 
 
125
 
    def get_liferea_opml(self, home_dir=os.path.expanduser("~")):
126
 
        """
127
 
        this returns either a empty string or the path to the current liferea
128
 
        opml file
129
 
 
130
 
        @param home_dir String defaults to ~
131
 
        @return String Path to opml file
132
 
        """
133
 
        #we'll be storing the latest liferea config folder in path and the
134
 
        #version number, if any, in curVersion
135
 
        path = ""
136
 
        curVersion = float(0.0)
137
 
 
138
 
        #loop through home and pick out any config folders matching .liferea*
139
 
        filenames = [filename for filename in os.listdir(home_dir)
140
 
            if filename.startswith(".liferea")]
141
 
 
142
 
        if (len(filenames) <= 0):
143
 
            #if there aren't any folders return an empty string
144
 
            return ""
145
 
        elif (len(filenames) == 1):
146
 
            #if there's only 1 path found set it as the path
147
 
            path = filenames[0]
148
 
        else:
149
 
            #in this case we have multiple posibilities
150
 
            #liferea will store the config folder as .liferea or .liferea_9.9
151
 
            #with 9.9 being the version number
152
 
            #all we have todo is pick the largest version number or just the
153
 
            #.liferea folder in that older
154
 
            for fname in filenames:
155
 
                if (fname [-3:] == "rea"):
156
 
                    if (curVersion == 0.0):
157
 
                        path = fname
158
 
                elif (float(fname [-3:])> curVersion):
159
 
                    curVersion = float(fname [-3:])
160
 
                    path = fname
161
 
 
162
 
        #check if the path variable gives us a valid path and return it if it
163
 
        #does or an empty string if it doesn't
164
 
        if os.path.isfile(home_dir + "/" + path + "/feedlist.opml"):
165
 
            return home_dir + "/" + path + "/feedlist.opml"
166
 
        else:
167
 
            return ""
168
 
 
169
 
class FeedConfigTools:
170
 
    """Enables Handling of Feed Config Widgets"""
171
 
 
172
 
    def __init__(self):
173
 
        """Initialize to get access to the Configuration object"""
174
 
        self.config = Configuration()
175
 
 
176
 
    def add_file_feeds_to_widget(self, files, model, feeds, check=True):
177
 
        """
178
 
        This changes the input values so that the feeds in the files update
179
 
        the other inputs
180
 
 
181
 
        @param files list(String)
182
 
        @param model GTKModel?
183
 
        @param feeds list(String)
184
 
        """
185
 
        feed_list = []
186
 
        for opml_file in files:
187
 
            #get the list of feeds from each file
188
 
            opml_feeds = OPMLParser().get_rss_feeds(opml_file)
189
 
            #add the feeds to the rss_list
190
 
            for feed in opml_feeds:
191
 
                feed_list.append(feed)
192
 
        #only check if check is set to True
193
 
        if(check):
194
 
            #check if the user really wants to add
195
 
            dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
196
 
                gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL,
197
 
                "This will add " + str(len(feed_list)) +
198
 
                " feeds to your feed list. Continue?")
199
 
 
200
 
            status = dialog.run()
201
 
            #If user has ok'd the request we can now add the feeds properly,
202
 
            #else leave it
203
 
            if(status == gtk.RESPONSE_OK):
204
 
                #now we need append the feeds to self.feeds and content manager
205
 
                self.add_feeds_to_widget(feed_list, model, feeds)
206
 
            dialog.destroy()
207
 
        else:
208
 
            #now we need append the feeds to self.feeds and content manager
209
 
            self.add_feeds_to_widget(feed_list, model, feeds)
210
 
 
211
 
    def add_feeds_to_widget(self, feed_list, model, feeds):
212
 
        """
213
 
        This changes the input values so that the feeds in feed_list update
214
 
        the other inputs
215
 
 
216
 
        @param feed_list list(String)
217
 
        @param model GTKModel?
218
 
        @param feeds list(String)
219
 
        """
220
 
        try:
221
 
            for feed in feed_list:
222
 
                #drop any items which are .opml files
223
 
                #We do not recursively parse opml links as we could end up
224
 
                #with an infinite loop
225
 
                if (feed [-5:]) != ".opml":
226
 
                    #this is adding the feed to the content manager widget
227
 
                    model.append([feed])
228
 
                    feeds.append(feed)
229
 
            #now we can parse the new feeds and add them
230
 
            str_folders = ";".join(feeds)
231
 
            self.config.write_content_value("RSS", "feeds", str_folders)
232
 
        except IOError:
233
 
            #Catching IOError
234
 
            error = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
235
 
                gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
236
 
                "IOError: There seems to be a problem with your selection.")
237
 
            error.run()
238
 
            error.destroy()
239