4
from flexget.plugin import register_plugin, PluginWarning
5
from flexget.manager import Base
6
from sqlalchemy import Column, Integer, String, DateTime
8
log = logging.getLogger('make_rss')
19
__tablename__ = 'make_rss'
21
id = Column(Integer, primary_key=True)
22
title = Column(String)
23
description = Column(String)
25
rsslink = Column(String)
27
published = Column(DateTime, default=datetime.datetime.utcnow())
30
class OutputRSS(object):
32
Write RSS containing succeeded (downloaded) entries.
36
make_rss: ~/public_html/flexget.rss
38
You may write into same file in multiple feeds.
43
make_rss: ~/public_html/series.rss
47
make_rss: ~/public_html/series.rss
51
With this example file series.rss would contain succeeded
52
entries from both feeds.
54
Number of days / items:
55
-----------------------
57
By default output contains items from last 7 days. You can specify
58
different perioid, number of items or both. Value -1 means unlimited.
63
file: ~/public_html/series.rss
67
Generate RSS that will containg last two days and no more than 10 items.
72
file: ~/public_html/series.rss
76
Generate RSS that will contain last 50 items, regardless of dates.
80
You can specify the url location of the rss file.
85
file: ~/public_html/series.rss
86
rsslink: http://my.server.net/series.rss
91
You can specify what field from entry is used as a link in generated rss feed.
96
file: ~/public_html/series.rss
100
List should contain a list of fields in order of preference.
101
Note that the url field is always used as last possible fallback
102
even without explicitly adding it into the list.
104
Default list: imdb_url, input_url, url
112
"""Validate given configuration"""
113
from flexget import validator
114
root = validator.factory()
115
root.accept('text') # TODO: path / file
116
rss = root.accept('dict')
117
rss.accept('text', key='file', required=True)
118
rss.accept('integer', key='days')
119
rss.accept('integer', key='items')
120
rss.accept('boolean', key='history')
121
rss.accept('text', key='rsslink')
122
rss.accept('text', key='encoding') # TODO: only valid choices
123
links = rss.accept('list', key='link')
127
def on_feed_output(self, feed):
128
# makes this plugin count as output (stops warnings about missing outputs)
131
def get_config(self, feed):
132
config = feed.config['make_rss']
133
if not isinstance(config, dict):
134
config = {'file': config}
135
config.setdefault('days', 7)
136
config.setdefault('items', -1)
137
config.setdefault('history', True)
138
config.setdefault('encoding', 'iso-8859-1')
139
config.setdefault('link', ['imdb_url', 'input_url'])
140
# add url as last resort
141
config['link'].append('url')
144
def on_feed_exit(self, feed):
145
"""Store finished / downloaded entries at exit"""
147
raise PluginWarning('plugin make_rss requires PyRSS2Gen library.')
148
config = self.get_config(feed)
150
# don't run with --test
151
if feed.manager.options.test:
154
# when history is disabled, remove everything from backlog on every run (a bit hackish, rarely usefull)
155
if not config['history']:
156
log.debug('disabling history')
157
for item in feed.session.query(RSSEntry).filter(RSSEntry.file == config['file']).all():
158
feed.session.delete(item)
160
# save entries into db for RSS generation
161
for entry in feed.accepted:
163
rss.title = entry['title']
164
for field in config['link']:
166
rss.link = entry[field]
169
# TODO: just a quick hack, implement better :)
171
if 'imdb_score' in entry:
172
description += 'Score: %s / 10 | ' % entry['imdb_score']
173
if 'imdb_votes' in entry:
174
description += 'Votes: %s | ' % entry['imdb_votes']
175
if 'imdb_genres' in entry:
176
description += 'Genres: %s | ' % ', '.join(entry['imdb_genres'])
177
if 'imdb_plot_outline' in entry:
178
description += 'Description: %s' % entry['imdb_plot_outline']
180
description += entry.get('description', '')
182
rss.description = description
183
rss.file = config['file']
185
# TODO: check if this exists and suggest disabling history if it does since it shouldn't happen normally ...
186
log.debug('Saving %s into rss database' % entry['title'])
187
feed.session.add(rss)
189
def on_process_end(self, feed):
190
"""Write RSS file at application terminate."""
193
# don't generate rss when learning
194
if feed.manager.options.learn:
197
config = self.get_config(feed)
198
if config['file'] in self.written:
199
log.debugall('skipping already written file %s' % config['file'])
202
# in terminate phase there is no open session in feed, so open new one
203
from flexget.manager import Session
206
db_items = session.query(RSSEntry).filter(RSSEntry.file == config['file']).\
207
order_by(RSSEntry.published.desc()).all()
211
for db_item in db_items:
213
if config['items'] != -1:
214
if len(rss_items) > config['items']:
216
if config['days'] != -1:
217
if datetime.datetime.today() - datetime.timedelta(days=config['days']) > db_item.published:
220
# add into generated feed
222
gen['title'] = db_item.title
223
gen['description'] = db_item.description
224
gen['link'] = db_item.link
225
gen['pubDate'] = db_item.published
226
log.debugall('Adding %s into rss %s' % (gen['title'], config['file']))
227
rss_items.append(PyRSS2Gen.RSSItem(**gen))
230
session.delete(db_item)
236
rss = PyRSS2Gen.RSS2(title='FlexGet',
237
link=config.get('rsslink', 'http://flexget.com'),
238
description='FlexGet generated RSS feed',
239
lastBuildDate=datetime.datetime.utcnow(),
242
fn = os.path.expanduser(config['file'])
244
rss.write_xml(open(fn, 'w'), encoding=config['encoding'])
246
log.critical('Unknown encoding %s' % config['encoding'])
249
# TODO: plugins cannot raise PluginWarnings in terminate event ..
250
log.critical('Unable to write %s' % fn)
252
self.written[config['file']] = True
255
register_plugin(OutputRSS, 'make_rss')