6
from datetime import datetime
7
from sqlalchemy import Column, Integer, String, DateTime
8
from flexget import schema
9
from flexget.plugin import register_plugin, DependencyError, PluginWarning
13
from flexget.plugins.api_tvdb import lookup_series
15
raise DependencyError(issued_by='myepisodes', missing='api_tvdb',
16
message='myepisodes requires the `api_tvdb` plugin')
19
log = logging.getLogger('myepisodes')
20
Base = schema.versioned_base('myepisodes', 0)
23
class MyEpisodesInfo(Base):
24
__tablename__ = 'myepisodes'
26
id = Column(Integer, primary_key=True)
27
series_name = Column(String, unique=True) # don't know if unique is correct python syntax for saying there must only be one entry with the same content
28
myepisodes_id = Column(Integer, unique=True)
29
updated = Column(DateTime)
31
def __init__(self, series_name, myepisodes_id):
32
self.series_name = series_name
33
self.myepisodes_id = myepisodes_id
34
self.updated = datetime.now()
37
return '<MyEpisodesInfo(series_name=%s, myepisodes_id=%s)>' % (self.series_name, self.myepisodes_id)
40
class MyEpisodes(object):
42
Marks a series episode as acquired in your myepisodes.com account.
46
Most shows are recognized automatically from their TVDBname.
47
And of course the plugin needs to know your MyEpisodes.com account details.
60
In some cases, the TVDB name is either not unique or won't even be discovered.
61
In that case you need to specify the MyEpisodes id manually using the set plugin.
74
How to find the MyEpisodes id: http://matrixagents.org/screencasts/myep_example-20110507-131555.png
78
from flexget import validator
79
root = validator.factory('dict')
80
root.accept('text', key='username', required=True)
81
root.accept('text', key='password', required=True)
84
def on_feed_exit(self, feed, config):
85
"""Mark all accepted episodes as acquired on MyEpisodes"""
87
# Nothing accepted, don't do anything
90
username = config['username']
91
password = config['password']
93
cookiejar = cookielib.CookieJar()
94
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
95
baseurl = urllib2.Request('http://myepisodes.com/login.php?')
96
loginparams = urllib.urlencode({'username': username,
100
logincon = opener.open(baseurl, loginparams)
101
loginsrc = logincon.read()
102
except urllib2.URLError, e:
103
log.error('Error logging in to myepisodes: %s' % e)
106
if str(username) not in loginsrc:
107
raise PluginWarning(('Login to myepisodes.com failed, please check '
108
'your account data or see if the site is down.'), log)
110
for entry in feed.accepted:
112
self.mark_episode(feed, entry, opener)
113
except PluginWarning, w:
116
def lookup_myepisodes_id(self, entry, opener, session):
117
"""Populates myepisodes_id field for an entry, and returns the id.
119
Call will also set entry field `myepisode_id` if successful.
125
LookupError if entry does not have field series_name
128
# Don't need to look it up if we already have it.
129
if entry.get('myepisodes_id'):
130
return entry['myepisodes_id']
132
if not entry.get('series_name'):
133
raise LookupError('Cannot lookup myepisodes id for entries without series_name')
134
series_name = entry['series_name']
136
# First check if we already have a myepisodes id stored for this series
137
myepisodes_info = session.query(MyEpisodesInfo).filter(MyEpisodesInfo.series_name == series_name.lower()).first()
139
entry['myepisodes_id'] = myepisodes_info.myepisodes_id
140
return myepisodes_info.myepisodes_id
142
# Get the series name from thetvdb to increase match chance on myepisodes
143
if entry.get('series_name_tvdb'):
144
query_name = entry['series_name_tvdb']
147
series = lookup_series(name=series_name, tvdb_id=entry.get('thetvdb_id'))
148
query_name = series.seriesname
149
except LookupError, e:
150
log.warning('Unable to lookup series `%s` from tvdb, using raw name.' % series_name)
151
query_name = series_name
153
baseurl = urllib2.Request('http://myepisodes.com/search.php?')
154
params = urllib.urlencode({'tvshow': query_name, 'action': 'Search myepisodes.com'})
156
con = opener.open(baseurl, params)
158
except urllib2.URLError, e:
159
log.error('Error searching for myepisodes id: %s' % e)
161
matchObj = re.search(r'&showid=([0-9]*)">' + query_name + '</a>', txt, re.MULTILINE | re.IGNORECASE)
163
myepisodes_id = matchObj.group(1)
164
db_item = session.query(MyEpisodesInfo).filter(MyEpisodesInfo.myepisodes_id == myepisodes_id).first()
166
log.info('Changing name to `%s` for series with myepisodes_id %s' %
167
(series_name.lower(), myepisodes_id))
168
db_item.series_name = series_name.lower()
170
session.add(MyEpisodesInfo(series_name.lower(), myepisodes_id))
171
entry['myepisodes_id'] = myepisodes_id
174
def mark_episode(self, feed, entry, opener):
175
"""Mark episode as acquired.
177
Required entry fields:
183
PluginWarning if operation fails
186
if 'series_season' not in entry or 'series_episode' not in entry or 'series_name' not in entry:
187
raise PluginWarning('Can\'t mark entry `%s` in myepisodes without series_season, series_episode and series_name fields' %
190
if not self.lookup_myepisodes_id(entry, opener, session=feed.session):
191
raise PluginWarning('Couldn\'t get myepisodes id for `%s`' % entry['title'], log)
193
myepisodes_id = entry['myepisodes_id']
194
season = entry['series_season']
195
episode = entry['series_episode']
197
if feed.manager.options.test:
198
log.info('Would mark %s of `%s` as acquired.' % (entry['series_id'], entry['series_name']))
200
baseurl2 = urllib2.Request('http://myepisodes.com/myshows.php?action=Update&showid=%s&season=%s&episode=%s&seen=0' %
201
(myepisodes_id, season, episode))
202
opener.open(baseurl2)
203
log.info('Marked %s of `%s` as acquired.' % (entry['series_id'], entry['series_name']))
206
register_plugin(MyEpisodes, 'myepisodes', api_ver=2)