def __init__(self, verbose=False): super(ItasaDownloader, self).__init__(verbose) db = current.w2p_tvseries.database self.main_url = "http://www.italiansubs.net/" self.req = req.Session() self.req.headers = {'Referer': self.main_url, 'User-Agent' : 'w2p_tvdb'} gs = w2p_tvseries_settings().global_settings() self.username = gs.itasa_username self.password = gs.itasa_password self.logged_in = False #<input type="hidden" name="return" value="aHR0cDovL3d3dy5pdGFsaWFuc3Vicy5uZXQv" /><input type="hidden" name="c10b48443ee5730c9b5a0927736bd09f" value="1" /> self.unique_pattern = '<input type="hidden" name="return" value="([^\n\r\t ]+?)" /><input type="hidden" name="([^\n\r\t ]+?)" value="([^\n\r\t ]+?)" />' #<a href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=select&id=1170"> Castle</a> self.show_pattern = '<a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+&func=select&id=[^\n\r\t ]+?)"> %s</a>' #href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=select&id=1171"> Stagione 1</a> self.season_pattern = '<a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+?&func=select&id=[^\n\r\t ]+?)"> Stagione %s</a>' #<img src='http://www.italiansubs.net/components/com_remository/images/folder_icons/category.gif' width=20 height=20><a name="1172"><a href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=select&id=1172"> 720p</a> self.category_pattern = '<img src=\'http://www\.italiansubs\.net/components/com_remository/images/folder_icons/category\.gif\' width=20 height=20><a name="[^\n\r\t ]+?"><a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+?&func=select&id=[^\n\r\t ]+?)"> ([^\n\r\t]+?)</a>' #<a href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=fileinfo&id=7348">Dexter 3x02</a> self.subtitle_pattern = '<a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+?&func=fileinfo&id=([^\n\r\t ]+?))">(%s %sx%02d.*?)</a>' #<a href='http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=download&id=7228&chk=5635630f675375afbdd6eec317d8d688&no_html=1'> self.subtitle_download_pattern = '<a href=\'http://www\.italiansubs\.net/(index\.php\?option=com_remository&Itemid=\d+?&func=download&id=%s&chk=[^\n\r\t ]+?&no_html=1\')>' self.verbose = verbose if not self.username or not self.password: self.error('No username or password found in settings, please check them')
def index(): settings_ = w2p_tvseries_settings() gsettings = settings_.global_settings() if len(gsettings) < 7: session.flash = "Please adjust your preferences" redirect(URL('settings')) return dict()
def check_path(self, seriesid, seasonnumber, create=False): db = current.w2p_tvseries.database se_tb = db.series ss_tb = db.seasons_settings gs = w2p_tvseries_settings().global_settings() path_format = gs.path_format or '%(seasonnumber).2d' #check path existance and writability season = db( (se_tb.id == seriesid) & (ss_tb.series_id == se_tb.id) & (ss_tb.seasonnumber == seasonnumber) ).select().first() name = season and season.series.name or '' series_basepath = season and season.series.basepath or '' if series_basepath == '': self.error('check_path', "No basepath found for %s season %s" % (name, seasonnumber)) return dict(err='no basepath', series=season.series.name, seasonnumber=seasonnumber) season_path = os.path.join(series_basepath, path_format % dict(seasonnumber=int(seasonnumber))) if os.path.exists(season_path) and os.access(season_path, os.W_OK): return dict(ok='1') else: if create: try: os.makedirs(season_path) self.log('check_path', 'Created folder %s' % (season_path)) return dict(ok='1') except OSError, e: self.error('check_path', 'error creating folder %s (%s)' % (season_path, e)) return dict(err='error creating folder %s (%s)' % (season_path, e) , series=season.series.name, seasonnumber=seasonnumber ) return dict(dir=season_path, message="dir %s doesn't exist, can I create it?" % season_path, series=season.series.name, seasonnumber=seasonnumber, seriesid=seriesid)
def __init__(self, verbose=False): super(ItasaDownloader, self).__init__(verbose) db = current.w2p_tvseries.database self.main_url = "http://www.italiansubs.net/" self.req = req.Session() self.req.headers = {'Referer': self.main_url, 'User-Agent': 'w2p_tvdb'} gs = w2p_tvseries_settings().global_settings() self.username = gs.itasa_username self.password = gs.itasa_password self.logged_in = False #<input type="hidden" name="return" value="aHR0cDovL3d3dy5pdGFsaWFuc3Vicy5uZXQv" /><input type="hidden" name="c10b48443ee5730c9b5a0927736bd09f" value="1" /> self.unique_pattern = '<input type="hidden" name="return" value="([^\n\r\t ]+?)" /><input type="hidden" name="([^\n\r\t ]+?)" value="([^\n\r\t ]+?)" />' #<a href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=select&id=1170"> Castle</a> self.show_pattern = '<a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+&func=select&id=[^\n\r\t ]+?)"> %s</a>' #href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=select&id=1171"> Stagione 1</a> self.season_pattern = '<a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+?&func=select&id=[^\n\r\t ]+?)"> Stagione %s</a>' #<img src='http://www.italiansubs.net/components/com_remository/images/folder_icons/category.gif' width=20 height=20><a name="1172"><a href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=select&id=1172"> 720p</a> self.category_pattern = '<img src=\'http://www\.italiansubs\.net/components/com_remository/images/folder_icons/category\.gif\' width=20 height=20><a name="[^\n\r\t ]+?"><a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+?&func=select&id=[^\n\r\t ]+?)"> ([^\n\r\t]+?)</a>' #<a href="http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=fileinfo&id=7348">Dexter 3x02</a> self.subtitle_pattern = '<a href="http://www\.italiansubs\.net/(index.php\?option=com_remository&Itemid=\d+?&func=fileinfo&id=([^\n\r\t ]+?))">(%s %sx%02d.*?)</a>' #<a href='http://www.italiansubs.net/index.php?option=com_remository&Itemid=6&func=download&id=7228&chk=5635630f675375afbdd6eec317d8d688&no_html=1'> self.subtitle_download_pattern = '<a href=\'http://www\.italiansubs\.net/(index\.php\?option=com_remository&Itemid=\d+?&func=download&id=%s&chk=[^\n\r\t ]+?&no_html=1\')>' self.verbose = verbose if not self.username or not self.password: self.error( 'No username or password found in settings, please check them')
def torrents(): session.forget(response) settings_ = w2p_tvseries_settings() gsettings = settings_.global_settings() if gsettings.tclient == 'None' or not gsettings.tclient: session.flash = 'no client configured' redirect(URL('default', 'client_settings')) return dict()
def torrents(): session.forget(response) settings_ = w2p_tvseries_settings() gsettings = settings_.global_settings() if gsettings.tclient == "None" or not gsettings.tclient: session.flash = "no client configured" redirect(URL("default", "client_settings")) return dict()
def get_missing(self, seriesid, seasonnumber): db = current.w2p_tvseries.database fname = 'get_missing' ss_tb = db.seasons_settings se_tb = db.series gs = w2p_tvseries_settings().global_settings() path_format = gs.path_format or '%(seasonnumber).2d' season = db( (ss_tb.series_id == seriesid) & (ss_tb.seasonnumber == seasonnumber) & (se_tb.id == ss_tb.series_id) ).select().first() bpath = season and season.series.basepath or '' if bpath == '': return dict(err='No basepath found') path = os.path.join(bpath, path_format % dict(seasonnumber = season.seasons_settings.seasonnumber)) tracking = season and season.seasons_settings.subtitle_tracking or None sub_settings = season and season.seasons_settings.subtitle_settings or None quality = simplejson.loads(sub_settings).get('quality', 'Normal') language = simplejson.loads(sub_settings).get('language', 'eng') name = season and season.series.name or None id = season and season.seasons_settings.id or None if tracking and name and id: data = simplejson.loads(season.seasons_settings.season_status) missingsubs = data.get('missingsubs', []) if len(missingsubs) == 0: message="No missing subs for %s, season %s, type %s, in path %s" % (name, seasonnumber, quality, path) self.log(fname, message) return dict(message=message) errs = '' subtitles_list, errs = self.search_subtitles(id, name, seasonnumber, missingsubs, quality, language) if errs <> '': return dict(err=errs) else: res = self.download_subtitles(subtitles_list, path) found = [a['number'] for a in subtitles_list] not_found = [] for a in missingsubs: if a not in found: not_found.append(a) data['missingsubs'] = not_found data = simplejson.dumps(data) db(ss_tb.id == season.seasons_settings.id).update(season_status=data) db.commit() message="Searching subs for %s, season %s, type %s, in path %s, were %s, are %s" % (name, seasonnumber, quality, path, missingsubs, not_found) self.log(fname, message) return dict(message=message) else: err = 'settings deny to download subtitles' self.error('fetch_subtitles', err) return dict(err=err)
def torrents_status(): session.forget(response) settings_ = w2p_tvseries_settings() gsettings = settings_.global_settings() tclient = w2p_tvseries_torrent_client_loader(gsettings.tclient) res = tclient.get_status() if res is None: response.flash = 'Unable to connect' res = [] #res = [] return dict(res=res)
def torrents_status(): session.forget(response) settings_ = w2p_tvseries_settings() gsettings = settings_.global_settings() tclient = w2p_tvseries_torrent_client_loader(gsettings.tclient) res = tclient.get_status() if res is None: response.flash = "Unable to connect" res = [] # res = [] return dict(res=res)
def add(): gs = w2p_tvseries_settings().global_settings() language = gs.language or 'en' error = None res = [] form = SQLFORM.factory(Field("series_name", requires=IS_NOT_EMPTY()), showid=False) if form.process(hideerror=True).accepted: try: tvdb = w2p_tvseries_tvdb_loader() res = tvdb.search_series(form.vars.series_name, language) except: res = [] error = 'Sorry, timeout on thetvdb.com, try again later' response.flash = '' return dict(res=res, form=form, error=error)
def check_path(self, seriesid, seasonnumber, create=False): db = current.w2p_tvseries.database se_tb = db.series ss_tb = db.seasons_settings gs = w2p_tvseries_settings().global_settings() path_format = gs.path_format or '%(seasonnumber).2d' #check path existance and writability season = db((se_tb.id == seriesid) & (ss_tb.series_id == se_tb.id) & (ss_tb.seasonnumber == seasonnumber)).select().first() name = season and season.series.name or '' series_basepath = season and season.series.basepath or '' if series_basepath == '': self.error( 'check_path', "No basepath found for %s season %s" % (name, seasonnumber)) return dict(err='no basepath', series=season.series.name, seasonnumber=seasonnumber) season_path = os.path.join( series_basepath, path_format % dict(seasonnumber=int(seasonnumber))) if os.path.exists(season_path) and os.access(season_path, os.W_OK): return dict(ok='1') else: if create: try: os.makedirs(season_path) self.log('check_path', 'Created folder %s' % (season_path)) return dict(ok='1') except OSError, e: self.error( 'check_path', 'error creating folder %s (%s)' % (season_path, e)) return dict(err='error creating folder %s (%s)' % (season_path, e), series=season.series.name, seasonnumber=seasonnumber) return dict(dir=season_path, message="dir %s doesn't exist, can I create it?" % season_path, series=season.series.name, seasonnumber=seasonnumber, seriesid=seriesid)
def get_season_path(series_id, seasonnumber): gs = w2p_tvseries_settings().global_settings() path_format = gs.season_path or '%(seasonnumber).2d' #season_setting rec = db((db.series.id == db.seasons_settings.series_id) & (db.seasons_settings.seasonnumber == seasonnumber) & (db.series.id == series_id) & (db.seasons_settings.tracking == True)).select().first() if not rec: return None path = os.path.join(rec.series.basepath, path_format % dict(seasonnumber=seasonnumber)) if os.path.exists(path): return path else: return None
def get_season_path(series_id, seasonnumber): gs = w2p_tvseries_settings().global_settings() path_format = gs.season_path or '%(seasonnumber).2d' #season_setting rec = db( (db.series.id == db.seasons_settings.series_id) & (db.seasons_settings.seasonnumber == seasonnumber) & (db.series.id == series_id) & (db.seasons_settings.tracking == True) ).select().first() if not rec: return None path = os.path.join(rec.series.basepath, path_format % dict(seasonnumber=seasonnumber)) if os.path.exists(path): return path else: return None
def client_settings(): settings_ = w2p_tvseries_settings() settings = settings_.torrent_client_settings() gsettings = settings_.global_settings() for k,v in gsettings.iteritems(): settings.defaults[k] = v fi = [ Field(k, settings.types.get(k, 'string'), comment=settings.comments[k], default=settings.defaults[k], label=settings.labels.get(k, k), widget=settings.widgets[k], requires=settings.requires[k] ) for k in settings.fields ] form = SQLFORM.factory( *fi, buttons=[ BUTTON("Save Changes", _class="btn btn-primary"), BUTTON("Try Connection", _class="btn btn-info tclient_validate", _href=URL('default', 'client_settings_validate.load') ) ] ) if form.process(hideerror=True).accepted: for a in form.vars: db.global_settings.update_or_insert( db.global_settings.kkey == a, value = form.vars[a], kkey=a ) settings_.global_settings(refresh=True) session.flash = 'settings updated correctly' redirect(URL(r=request, args=request.args)) elif form.errors: response.flash = 'errors in form, please check' return dict(form=form)
def client_settings(): settings_ = w2p_tvseries_settings() settings = settings_.torrent_client_settings() gsettings = settings_.global_settings() for k, v in gsettings.iteritems(): settings.defaults[k] = v fi = [ Field(k, settings.types.get(k, 'string'), comment=settings.comments[k], default=settings.defaults[k], label=settings.labels.get(k, k), widget=settings.widgets[k], requires=settings.requires[k]) for k in settings.fields ] form = SQLFORM.factory( *fi, buttons=[ BUTTON("Save Changes", _class="btn btn-primary"), BUTTON("Try Connection", _class="btn btn-info tclient_validate", _href=URL('default', 'client_settings_validate.load')) ]) if form.process(hideerror=True).accepted: for a in form.vars: db.global_settings.update_or_insert(db.global_settings.kkey == a, value=form.vars[a], kkey=a) settings_.global_settings(refresh=True) session.flash = 'settings updated correctly' redirect(URL(r=request, args=request.args)) elif form.errors: response.flash = 'errors in form, please check' return dict(form=form)
def check(self, seriesid, seasonnumber, mode='video'): db = current.w2p_tvseries.database se_tb = db.series ep_tb = db.episodes ss_tb = db.seasons_settings gs = w2p_tvseries_settings().global_settings() if mode == 'video': check_exts = self.video_ext elif mode == 'subs': check_exts = self.subs_ext path_format = gs.path_format or '%(seasonnumber).2d' rec = db((se_tb.id == seriesid) & (ss_tb.tracking == True) & (ss_tb.series_id == se_tb.id) & (ss_tb.seasonnumber == seasonnumber)).select().first() bpath = rec and rec.series.basepath or '' name = rec and rec.series.name or '' if bpath == '': self.error( 'check', "basepath not found (%s season %s)" % (name, seasonnumber)) return dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=[], missing=[], errors='basepath not found') path = os.path.join( bpath, path_format % dict(seasonnumber=rec.seasons_settings.seasonnumber)) if not os.path.exists(path): self.error( 'check', "%s path not found (%s season %s)" % (path, name, seasonnumber)) return dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=[], missing=[], errors='path not found') lista = [] for a in os.listdir(path): file = os.path.join(path, a) if os.path.isfile(file): if os.path.splitext(file)[1] in check_exts: lista.append(file) ep_tb = db.episodes se_tb = db.series eplist = db((se_tb.id == seriesid) & (ep_tb.seriesid == se_tb.seriesid) & (ep_tb.seasonnumber == seasonnumber) & (ep_tb.firstaired < datetime.datetime.utcnow()) & (ep_tb.tracking == True)).select(ep_tb.seasonnumber, ep_tb.epnumber, ep_tb.name) eplist_dict = {} for row in eplist: eplist_dict[row.epnumber] = row.name self.default_format = "%(seriesname)s - S%(seasonnumber).2d%(number)s - %(name)s%(ext)s" to_rename = [] episodes_matching = [] matching = [] for file_ in lista: file = os.path.split(file_)[1] match = self.meddler.analyze(file) if match.reason: continue matching.append((file_, match)) if len(match.episodes) > 0: for ep in match.episodes: episodes_matching.append(("%.2d" % ep)) missing = [] errors = [] for a in eplist_dict: if "%.2d" % (int(a)) not in episodes_matching: missing.append(a) if len(lista) == 0: rtn = dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=[], missing=missing, errors=errors) return rtn for a in matching: file, match = a origext = os.path.splitext(file)[1] origpath, origfile = os.path.split(file) name = [] number = [] if match.reason: errors.append(file) continue if len(match.episodes) > 1: for ep in match.episodes: #(we have a episode, we don't have a record for it) name_ = eplist_dict.get(int(ep), 'WEDONTHAVEARECORDFORTHIS') if name == 'WEDONTHAVEARECORDFORTHIS' and file not in errors: errors.append(file) continue name.append(name_) number.append(ep) name = '-'.join(name) number = ''.join(["E%.2d" % i for i in number]) else: #find name, if not, continue (we have a episode, we don't have a record for it) name = eplist_dict.get(int(match.episodes[0]), 'WEDONTHAVEARECORDFORTHIS') if name == 'WEDONTHAVEARECORDFORTHIS': errors.append(file) continue number = "E%.2d" % int(match.episodes[0]) newname = self.default_format % dict( seriesname=self.slugify(rec.series.name), seasonnumber=int(match.seasonnumber), number=number, name=self.slugify(name), ext=origext) if mode == 'video': db((ep_tb.epnumber.belongs(match.episodes)) & (ep_tb.seasonnumber == seasonnumber) & (ep_tb.seriesid == rec.series.seriesid)).update( filename=newname) if newname != origfile: to_rename.append((file, os.path.join(origpath, newname))) self.log( 'check', "Completed check for %s season %s" % (rec.series.name, seasonnumber)) rtn = dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=to_rename, missing=missing, errors=errors) return rtn
def get_series_path(series_id): gs = w2p_tvseries_settings().global_settings() basefolder = gs.series_basefolder series = db.series(series_id) last = filenamelify(series.name) return os.path.join(basefolder, last, '').strip()
def series_settings(): series_id = request.args(0) if not series_id: return '' validate_seasons(series_id) settings = w2p_tvseries_settings() seasons_settings = db(db.seasons_settings.series_id == series_id).select() series = db.series(series_id) series_name = series.name forms = [] active_tab = 0 i = 0 global_settings = db(db.global_settings.id>0).select() starts = 'torrent_default_' tor_global_settings = dict([(row.kkey.replace(starts,''), row.value) for row in global_settings if row.kkey.startswith(starts)]) starts = 'subtitles_default_' sub_global_settings = dict([(row.kkey.replace(starts,''), row.value) for row in global_settings if row.kkey.startswith(starts)]) season_number = {} for row in seasons_settings: key = "season_%s" % row.id season_number[i] = row.seasonnumber torrent_settings = settings.torrent_settings() #update defaults with globals torrent_settings.defaults.update(tor_global_settings) #update defaults with season settings season_settings = sj.loads(row.torrent_settings) torrent_settings.defaults.update(season_settings) if not torrent_settings.defaults.show_name: torrent_settings.defaults.show_name = series_name if not torrent_settings.defaults.season: torrent_settings.defaults.season = row.seasonnumber torrent_fi = [ Field("tor_%s" % k, torrent_settings.types.get(k, 'string'), comment=torrent_settings.comments[k] , default=torrent_settings.defaults[k], widget=torrent_settings.widgets[k] , requires=torrent_settings.requires[k] , label = torrent_settings.labels.get(k, k.replace('_', ' ').title()) ) for k in torrent_settings.fields ] subtitles_settings = settings.subtitle_settings() #update defaults with globals subtitles_settings.defaults.update(sub_global_settings) #update defaults with season settings season_settings = sj.loads(row.subtitle_settings) subtitles_settings.defaults.update(season_settings) subtitle_fi = [ Field("sub_%s" % k, subtitles_settings.types.get(k, 'string'), comment=subtitles_settings.comments[k] , default=subtitles_settings.defaults[k], widget=subtitles_settings.widgets[k] , requires=subtitles_settings.requires[k] ) for k in subtitles_settings.fields ] tracking_fi = [ Field('tracking', 'boolean', default=row.tracking ,label="Season tracking" ), Field('torrent_tracking', 'boolean', default=row.torrent_tracking ), Field('subtitle_tracking', 'boolean', default=row.subtitle_tracking ) ] if row.scooper_strings is None: row.scooper_strings = [] common_formats = ["%s.S%.2dE", "%s S%.2dE", "%s.%sx", "%s %sx"] for a in common_formats: row.scooper_strings.append(a % (series.name, row.seasonnumber)) others_fi = [ Field("ref_urls", 'list:string', default=row.ref_urls, label="Reference urls" ), Field("scooper_strings", 'list:string', default=row.scooper_strings, label="Scooper masks" ) ] all_fields = torrent_fi + subtitle_fi + tracking_fi + others_fi form = SQLFORM.factory(*all_fields, table_name=key, hidden=dict(ss_id=row.id), buttons=[ BUTTON("Save Changes", _class="btn btn-primary"), BUTTON("Preview torrents", _class="btn btn-info pre_torrents", _href=URL('manage', 'preview_torrents.load')), BUTTON("Preview scooper", _class="btn btn-info pre_scooper", _href=URL('manage', 'preview_scooper.load')) ] ) form.wells = [ dict( title="General Settings", fields=['tracking', 'torrent_tracking', 'subtitle_tracking', 'ref_urls'] ), dict( title="Subtitles", fields=["sub_%s" % a for a in subtitles_settings.fields] ), dict( title="Torrents", fields=["tor_%s" % a for a in torrent_settings.fields] ), dict( title="Scooper Settings", fields=['scooper_strings'] ) ] if form.process(formname=key, hideerror=True, onvalidation=series_settings_validate).accepted: tor_fields = ["tor_%s" % a for a in torrent_settings.fields] tor_vars = Storage([(a.replace('tor_','',1), form.vars[a]) for a in tor_fields]) if tor_vars.regex == '': tor_vars.regex = None sub_fields = ["sub_%s" % a for a in subtitles_settings.fields] sub_vars = Storage([(a.replace('sub_','',1), form.vars[a]) for a in sub_fields]) season_fields = ['tracking', 'torrent_tracking', 'subtitle_tracking', 'ref_urls', 'scooper_strings'] season_vars = Storage([(a, form.vars[a]) for a in season_fields]) for k,v in season_vars.iteritems(): if k in ['ref_urls', 'scooper_strings']: if not isinstance(v, list): season_vars[k] = [v] sub_fields = sj.dumps(sub_vars) tor_fields = sj.dumps(tor_vars) row.update_record(**season_vars) if row.torrent_tracking: row.update_record(torrent_settings=tor_fields) if row.subtitle_tracking: row.update_record(subtitle_settings=sub_fields) session.flash = 'Settings for season %s accepted' % (row.seasonnumber) redirect(URL(r=request, args=request.args, vars=dict(active_tab=i))) elif form.errors: response.flash = 'errors in form, please check' i += 1 forms.append( form ) suggested = None if series.basepath == '' or series.basepath == None: suggested = "w2p_tvseries guessed this path. Please press on save if you're okay with that" db.series.basepath.widget = myfolderwidget form_series = SQLFORM(db.series, series, fields=['basepath'], showid=False, submit_button = 'Save folder') if suggested: form_series.vars.basepath = get_series_path(series.id) if form_series.process(formname='series', hideerror=True, onvalidation=series_basefolder_validate).accepted: session.flash = 'settings saved' redirect(URL(r=request, args=request.args, vars=dict(active_tab=request.vars.active_tab or active_tab))) elif form_series.errors: response.flash = 'errors in form, please check' return dict(form_series=form_series, forms=forms, suggested=suggested, series=series, season_number=season_number)
def settings(): settings_ = w2p_tvseries_settings() settings = settings_.general_settings() gsettings = settings_.global_settings() for k, v in gsettings.iteritems(): settings.defaults[k] = v fi = [ Field(k, settings.types.get(k, 'string'), comment=settings.comments[k], default=settings.defaults[k], widget=settings.widgets[k], requires=settings.requires[k]) for k in settings.fields ] form = SQLFORM.factory(*fi, submit_button="Save Settings") form.wells = [ dict(title="General Settings", fields=[ 'series_language', 'season_path', 'series_basefolder', 'series_metadata', 'hash_gen' ]), dict(title="Scooper Settings", fields=['scooper_path']), dict(title="Torrent Defaults", fields=[ 'torrent_path', 'torrent_magnet', 'torrent_default_feed', 'torrent_default_quality', 'torrent_default_minsize', 'torrent_default_maxsize' ]), dict(title="Subtitles Settings", fields=[ 'itasa_username', 'itasa_password', 'subtitles_default_method', 'subtitles_default_quality', 'subtitles_default_language' ]) ] if form.process(hideerror=True).accepted: for a in form.vars: if a == 'itasa_password': if form.vars[a] <> 8 * ('*'): db.global_settings.update_or_insert( db.global_settings.kkey == a, value=form.vars[a], kkey=a) elif a == 'series_basefolder': db.global_settings.update_or_insert( db.global_settings.kkey == a, value=form.vars[a].strip(), kkey=a) ##FIXME elif a == 'scooper_path': values = form.vars[a] if not isinstance(values, (tuple, list)): values = [values] values = [a.strip() for a in values if a.strip() != ''] #FIXME values = set(values) db(db.global_settings.kkey == 'scooper_path').delete() for b in values: db.global_settings.insert(kkey='scooper_path', value=b) else: db.global_settings.update_or_insert( db.global_settings.kkey == a, value=form.vars[a], kkey=a) db.commit() settings_.global_settings(refresh=True) if form.vars.torrent_magnet == 'ST': if gsettings.tclient == 'None': session.flash = 'You need to configure your torrent client' redirect(URL('default', 'client_settings')) session.flash = 'settings updated correctly' redirect(URL(r=request, args=request.args)) elif form.errors: response.flash = 'errors in form, please check' return dict(form=form)
def settings(): settings_ = w2p_tvseries_settings() settings = settings_.general_settings() gsettings = settings_.global_settings() for k,v in gsettings.iteritems(): settings.defaults[k] = v fi = [ Field(k, settings.types.get(k, 'string'), comment=settings.comments[k], default=settings.defaults[k], widget=settings.widgets[k], requires=settings.requires[k]) for k in settings.fields ] form = SQLFORM.factory( *fi, submit_button="Save Settings" ) form.wells = [ dict( title="General Settings", fields=['series_language', 'season_path', 'series_basefolder', 'series_metadata', 'hash_gen'] ), dict( title="Scooper Settings", fields=['scooper_path'] ), dict( title="Torrent Defaults", fields=['torrent_path', 'torrent_magnet', 'torrent_default_feed', 'torrent_default_quality','torrent_default_minsize', 'torrent_default_maxsize'] ), dict( title="Subtitles Settings", fields=['itasa_username','itasa_password','subtitles_default_method', 'subtitles_default_quality', 'subtitles_default_language'] ) ] if form.process(hideerror=True).accepted: for a in form.vars: if a == 'itasa_password': if form.vars[a] <> 8*('*'): db.global_settings.update_or_insert( db.global_settings.kkey == a, value = form.vars[a], kkey=a ) elif a == 'series_basefolder': db.global_settings.update_or_insert( db.global_settings.kkey == a, value = form.vars[a].strip(), kkey=a ) ##FIXME elif a == 'scooper_path': values = form.vars[a] if not isinstance(values, (tuple,list)): values = [values] values = [a.strip() for a in values if a.strip() != ''] #FIXME values = set(values) db(db.global_settings.kkey=='scooper_path').delete() for b in values: db.global_settings.insert(kkey='scooper_path', value=b) else: db.global_settings.update_or_insert( db.global_settings.kkey == a, value = form.vars[a], kkey=a ) db.commit() settings_.global_settings(refresh=True) if form.vars.torrent_magnet == 'ST': if gsettings.tclient == 'None': session.flash = 'You need to configure your torrent client' redirect(URL('default', 'client_settings')) session.flash = 'settings updated correctly' redirect(URL(r=request, args=request.args)) elif form.errors: response.flash = 'errors in form, please check' return dict(form=form)
def check(self, seriesid, seasonnumber, mode='video'): db = current.w2p_tvseries.database se_tb = db.series ep_tb = db.episodes ss_tb = db.seasons_settings gs = w2p_tvseries_settings().global_settings() if mode == 'video': check_exts = self.video_ext elif mode == 'subs': check_exts = self.subs_ext path_format = gs.path_format or '%(seasonnumber).2d' rec = db((se_tb.id == seriesid) & (ss_tb.tracking == True) & (ss_tb.series_id == se_tb.id) & (ss_tb.seasonnumber == seasonnumber) ).select().first() bpath = rec and rec.series.basepath or '' name = rec and rec.series.name or '' if bpath == '': self.error('check', "basepath not found (%s season %s)" % (name, seasonnumber)) return dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=[], missing=[], errors='basepath not found') path = os.path.join(bpath, path_format % dict(seasonnumber = rec.seasons_settings.seasonnumber)) if not os.path.exists(path): self.error('check', "%s path not found (%s season %s)" % (path, name, seasonnumber)) return dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=[], missing=[], errors='path not found') lista = [] for a in os.listdir(path): file = os.path.join(path, a) if os.path.isfile(file): if os.path.splitext(file)[1] in check_exts: lista.append(file) ep_tb = db.episodes se_tb = db.series eplist = db( (se_tb.id == seriesid) & (ep_tb.seriesid == se_tb.seriesid) & (ep_tb.seasonnumber == seasonnumber) & (ep_tb.firstaired < datetime.datetime.utcnow()) & (ep_tb.tracking == True) ).select(ep_tb.seasonnumber, ep_tb.epnumber, ep_tb.name) eplist_dict = {} for row in eplist: eplist_dict[row.epnumber] = row.name self.default_format = "%(seriesname)s - S%(seasonnumber).2d%(number)s - %(name)s%(ext)s" to_rename = [] episodes_matching = [] matching = [] for file_ in lista: file = os.path.split(file_)[1] match = self.meddler.analyze(file) if match.reason: continue matching.append((file_, match)) if len(match.episodes)>0: for ep in match.episodes: episodes_matching.append(("%.2d" % ep)) missing = [] errors = [] for a in eplist_dict: if "%.2d" % (int(a)) not in episodes_matching: missing.append(a) if len(lista) == 0: rtn = dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=[], missing=missing, errors=errors) return rtn for a in matching: file, match = a origext = os.path.splitext(file)[1] origpath, origfile = os.path.split(file) name = [] number = [] if match.reason: errors.append(file) continue if len(match.episodes)>1: for ep in match.episodes: #(we have a episode, we don't have a record for it) name_ = eplist_dict.get(int(ep), 'WEDONTHAVEARECORDFORTHIS') if name == 'WEDONTHAVEARECORDFORTHIS' and file not in errors: errors.append(file) continue name.append(name_) number.append(ep) name = '-'.join(name) number = ''.join(["E%.2d" % i for i in number]) else: #find name, if not, continue (we have a episode, we don't have a record for it) name = eplist_dict.get(int(match.episodes[0]), 'WEDONTHAVEARECORDFORTHIS') if name == 'WEDONTHAVEARECORDFORTHIS': errors.append(file) continue number = "E%.2d" % int(match.episodes[0]) newname = self.default_format % dict(seriesname = self.slugify(rec.series.name), seasonnumber = int(match.seasonnumber), number = number, name = self.slugify(name), ext = origext ) if mode == 'video': db( (ep_tb.epnumber.belongs(match.episodes)) & (ep_tb.seasonnumber == seasonnumber) & (ep_tb.seriesid == rec.series.seriesid) ).update(filename=newname) if newname != origfile: to_rename.append((file, os.path.join(origpath, newname))) self.log('check', "Completed check for %s season %s" % (rec.series.name, seasonnumber)) rtn = dict(seriesid=seriesid, seasonnumber=seasonnumber, rename=to_rename, missing=missing, errors=errors) return rtn
def get_missing(self, seriesid, seasonnumber): db = current.w2p_tvseries.database fname = 'get_missing' ss_tb = db.seasons_settings se_tb = db.series gs = w2p_tvseries_settings().global_settings() path_format = gs.path_format or '%(seasonnumber).2d' season = db((ss_tb.series_id == seriesid) & (ss_tb.seasonnumber == seasonnumber) & (se_tb.id == ss_tb.series_id)).select().first() bpath = season and season.series.basepath or '' if bpath == '': return dict(err='No basepath found') path = os.path.join( bpath, path_format % dict(seasonnumber=season.seasons_settings.seasonnumber)) tracking = season and season.seasons_settings.subtitle_tracking or None sub_settings = season and season.seasons_settings.subtitle_settings or None quality = simplejson.loads(sub_settings).get('quality', 'Normal') language = simplejson.loads(sub_settings).get('language', 'eng') name = season and season.series.name or None id = season and season.seasons_settings.id or None if tracking and name and id: data = simplejson.loads(season.seasons_settings.season_status) missingsubs = data.get('missingsubs', []) if len(missingsubs) == 0: message = "No missing subs for %s, season %s, type %s, in path %s" % ( name, seasonnumber, quality, path) self.log(fname, message) return dict(message=message) errs = '' subtitles_list, errs = self.search_subtitles( id, name, seasonnumber, missingsubs, quality, language) if errs <> '': return dict(err=errs) else: res = self.download_subtitles(subtitles_list, path) found = [a['number'] for a in subtitles_list] not_found = [] for a in missingsubs: if a not in found: not_found.append(a) data['missingsubs'] = not_found data = simplejson.dumps(data) db(ss_tb.id == season.seasons_settings.id).update( season_status=data) db.commit() message = "Searching subs for %s, season %s, type %s, in path %s, were %s, are %s" % ( name, seasonnumber, quality, path, missingsubs, not_found) self.log(fname, message) return dict(message=message) else: err = 'settings deny to download subtitles' self.error('fetch_subtitles', err) return dict(err=err)
def download_torrents(self, seriesid, seasonnumber): fname = "down_torrents" db = current.w2p_tvseries.database dw = db.downloads ep = db.episodes gs = w2p_tvseries_settings().global_settings() torrent_path = gs.torrent_path torrent_magnet = gs.torrent_magnet or 'N' if not torrent_path: self.error(fname, "torrent_path not set") return if not os.path.exists(torrent_path): self.error(fname, "torrent_path %s not found" % (torrent_path)) return if torrent_magnet == 'ST': #retrieve current torrent client configured tclient = gs.tclient from w2p_tvseries_clients import w2p_tvseries_torrent_client_loader tc = w2p_tvseries_torrent_client_loader(tclient, gsettings=gs) if torrent_magnet <> 'N': #find magnets to serialize res = db( (dw.queued == False) & (dw.magnet != None) & (dw.magnet != '') & (dw.series_id == seriesid) & (dw.seasonnumber == seasonnumber) ).select() for row in res: if not self.magnetdnr.search(row.magnet): ep_name = db(ep.id == row.episode_id).select(ep.name).first() ep_name = ep_name and ep_name.name or row.episode_id ep_name = urllib.urlencode({'dn' : ep_name}) row.magnet = "%s&%s" % (row.magnet, ep_name) if torrent_magnet == 'ST': if tc.add_magnet(row.magnet): row.update_record(queued=True, queued_at=datetime.datetime.utcnow()) db.commit() time.sleep(1) #avoid DDoS to the client else: db.rollback() else: filename = os.path.join(torrent_path, "catalog.magnet") if torrent_magnet == 'MF': filename = os.path.join(torrent_path, "%s.magnet" % (row.id)) try: with open(filename, 'a') as g: g.write(row.magnet + '\n') row.update_record(queued=True, queued_at=datetime.datetime.utcnow()) db.commit() except: self.error(fname, "Cannot write to %s" % (filename)) db.rollback() if torrent_magnet in ('N', 'ST'): #find torrents to download (also for adding to client if no magnet link is there) res = db( (dw.queued == False) & (dw.series_id == seriesid) & (dw.seasonnumber == seasonnumber) ).select() for row in res: if not row.link: row.link = self.get_torrent_from_magnet(row.magnet) row.update_record(link=row.link) if not row.down_file: content = self.downloader(row.link) if content == None and row.magnet: newurl = self.get_torrent_from_magnet(row.magnet) if newurl: content = self.downloader(newurl) if content == None: self.error(fname, "Can't download %s " % row.link) continue else: row.update_record(down_file=content) else: content = row.down_file filename = row.link.split('/')[-1] filename = os.path.join(torrent_path, filename) try: with open(filename, 'wb') as g: g.write(content) except: self.error(fname, "Cannot write to %s" % (filename)) db.rollback() continue if torrent_magnet == 'ST': if tc.add_torrent(filename): row.update_record(queued=True, queued_at=datetime.datetime.utcnow()) self.log(fname, "added to client %s" % (row.link)) db.commit() time.sleep(1) #avoid DDoS to the client else: row.update_record(queued=True, queued_at=datetime.datetime.utcnow()) self.log(fname, "added to client %s" % (row.link)) db.commit()
def access_settings(self): if not self.gsettings: self.gsettings = w2p_tvseries_settings().global_settings() self.url = self.gsettings.turl self.username = self.gsettings.tusername self.password = self.gsettings.tpassword