def save(self, **data): ''' Save all config settings ''' config = cherrypy.config.get('config') # catch checkboxes for bool in ['Renamer.enabled', 'Renamer.trailerQuality', 'Renamer.cleanup', 'global.launchbrowser', 'Torrents.enabled', 'NZB.enabled', 'NZBMatrix.enabled', 'NZBsorg.enabled', 'newznab.enabled']: if not data.get(bool): data[bool] = False # Do quality order order = data.get('Quality.order').split(',') for id in order: qo = Db.query(QualityTemplate).filter_by(id = int(id)).one() qo.order = order.index(id) Db.flush() del data['Quality.order'] # Save templates if data.get('Quality.templates'): templates = json.loads(data.get('Quality.templates')) Qualities().saveTemplates(templates) del data['Quality.templates'] # Save post data for name in data: section = name.split('.')[0] var = name.split('.')[1] config.set(section, var, data[name]) # Change cron interval self.cron.get('yarr').setInterval(config.get('Intervals', 'search')) config.save()
def save(self, **data): ''' Save all config settings ''' config = cherrypy.config.get('config') # catch checkboxes bools = filter(lambda s: not data.get(s), [ 'global.launchbrowser', 'global.updater', 'XBMC.enabled', 'XBMC.onSnatch', 'NMJ.enabled', 'PLEX.enabled', 'PROWL.enabled', 'PROWL.onSnatch', 'GROWL.enabled', 'GROWL.onSnatch', 'Notifo.enabled', 'Notifo.onSnatch', 'NMA.enable', 'NMA.onSnatch', 'Meta.enabled', 'MovieETA.enabled', 'Renamer.enabled', 'Renamer.trailerQuality', 'Renamer.cleanup', 'Torrents.enabled', 'NZB.enabled', 'NZBMatrix.enabled', 'NZBMatrix.english', 'NZBMatrix.ssl', 'NZBsRUS.enabled', 'newzbin.enabled', 'NZBsorg.enabled', 'newznab.enabled', 'Subtitles.enabled', 'Subtitles.addLanguage', 'MovieRSS.enabled', ] ) data.update(data.fromkeys(bools, False)) # Do quality order order = data.get('Quality.order').split(',') for id in order: qo = Db.query(QualityTemplate).filter_by(id = int(id)).one() qo.order = order.index(id) Db.flush() del data['Quality.order'] # Save templates if data.get('Quality.templates'): templates = json.loads(data.get('Quality.templates')) Qualities().saveTemplates(templates) del data['Quality.templates'] # Save post data for name in data: section = name.split('.')[0] var = name.split('.')[1] config.set(section, var, data[name]) # Change cron interval self.cron.get('yarr').setInterval(config.get('Intervals', 'search')) config.save() self.flash.add('config', 'Settings successfully saved.') return redirect(cherrypy.request.headers.get('referer'))
def clear_downloaded(self): """Clear downloaded movies.""" qMovie = Db.query(Movie) downloaded = qMovie.filter_by(status=u"downloaded").all() for movie in downloaded: movie.status = u"deleted" Db.flush() return redirect(url(controller="movie", action="index"))
def clear_downloaded(self): """Clear downloaded movies.""" qMovie = Db.query(Movie) downloaded = qMovie.filter_by(status=u'downloaded').all() for movie in downloaded: movie.status = u'deleted' Db.flush() return redirect(url(controller='movie', action='index'))
def clear_downloaded(self): """Clear downloaded movies.""" qMovie = Db.query(Movie) downloaded = qMovie.filter_by(status = u'downloaded').all() for movie in downloaded: movie.status = u'deleted' Db.flush() return redirect(url(controller = 'movie', action = 'index'))
def alreadyDownloaded(self, movie, file, key): key = self.getKey(key) movieId = 0 if not movie else movie.id results = Db.query(SubtitleHistory).filter(and_(SubtitleHistory.subtitle == key, SubtitleHistory.movie == movieId, SubtitleHistory.file == file)).all() for h in results: h.status = u'ignored' Db.flush() return len(results) > 0
def saveExtra(self, id, name, value): exists = Db.query(MovieExtra).filter(and_(MovieExtra.movieId == id, MovieExtra.name == name)).first() if not exists: exists = MovieExtra() Db.add(exists) exists.movieId = id exists.name = name exists.value = value Db.flush()
def save(self, **data): """ Save all config settings """ config = cherrypy.config.get("config") # catch checkboxes for bool in [ "XBMC.enabled", "Meta.enabled", "Renamer.enabled", "Renamer.trailerQuality", "Renamer.cleanup", "global.launchbrowser", "global.updater", "Torrents.enabled", "NZB.enabled", "NZBMatrix.enabled", "NZBsorg.enabled", "newznab.enabled", "Newzbin.enabled" "Subtitles.enabled", "Subtitles.addLanguage", ]: if not data.get(bool): data[bool] = False # Do quality order order = data.get("Quality.order").split(",") for id in order: qo = Db.query(QualityTemplate).filter_by(id=int(id)).one() qo.order = order.index(id) Db.flush() del data["Quality.order"] # Save templates if data.get("Quality.templates"): templates = json.loads(data.get("Quality.templates")) Qualities().saveTemplates(templates) del data["Quality.templates"] # Save post data for name in data: section = name.split(".")[0] var = name.split(".")[1] config.set(section, var, data[name]) # Change cron interval self.cron.get("yarr").setInterval(config.get("Intervals", "search")) config.save() self.flash.add("config", "Settings successfully saved.") return redirect(cherrypy.request.headers.get("referer"))
def downloaded(self, id): """ Mark movie as downloaded """ movie = Db.query(Movie).filter_by(id=id).one() # set status movie.status = u"downloaded" Db.flush() self.flash.add("movie-" + str(movie.id), '"%s" marked as downloaded.' % (movie.name)) return redirect(url(controller="movie", action="index"))
def save(self, movie, result): row = Db.query(MovieETA).filter_by(movieId=movie.id).first() if not row: row = MovieETA() Db.add(row) row.movieId = movie.id row.theater = result.get('theater') row.dvd = result.get('dvd') row.bluray = result.get('bluray') row.lastCheck = result.get('expires') Db.flush()
def downloaded(self, id): ''' Mark movie as downloaded ''' movie = Db.query(Movie).filter_by(id = id).one() #set status movie.status = u'downloaded' Db.flush() self.flash.add('movie-' + str(movie.id), '"%s" marked as downloaded.' % (movie.name)) return redirect(url(controller = 'movie', action = 'index'))
def addToHistory(self, movie, file, key, data): key = self.getKey(key) movieId = 0 if not movie else movie.id new = SubtitleHistory() new.movie = movieId new.file = latinToAscii(file) new.subtitle = key new.status = u'downloaded' new.data = str(data) Db.add(new) Db.flush()
def save(self, movie, result): row = Db.query(MovieETA).filter_by(movieId = movie.id).first() if not row: row = MovieETA() Db.add(row) row.movieId = movie.id row.theater = result.get('theater') row.dvd = result.get('dvd') row.bluray = result.get('bluray') row.lastCheck = result.get('expires') Db.flush()
def save(self, movie, result): row = Db.query(MovieETA).filter_by(movieId = movie.id).first() if not row: row = MovieETA() Db.add(row) row.movieId = movie.id row.videoEtaId = result.get('id', 0) row.theater = result.get('theater', 0) row.dvd = result.get('dvd', 0) row.bluray = result.get('bluray', 0) row.lastCheck = int(time.time()) Db.flush()
def downloaded(self, id): ''' Mark movie as downloaded ''' movie = Db.query(Movie).filter_by(id=id).one() #set status movie.status = u'downloaded' Db.flush() self.flash.add('movie-' + str(movie.id), '"%s" marked as downloaded.' % (movie.name)) return redirect(url(controller='movie', action='index'))
def delete(self, id): """ Mark movie as deleted """ movie = Db.query(Movie).filter_by(id=id).one() previousStatus = movie.status # set status movie.status = u"deleted" Db.flush() if previousStatus == "downloaded": self.flash.add("movie-" + str(movie.id), '"%s" deleted.' % (movie.name)) return redirect(url(controller="movie", action="index"))
def delete(self, id): ''' Mark movie as deleted ''' movie = Db.query(Movie).filter_by(id = id).one() previousStatus = movie.status #set status movie.status = u'deleted' Db.flush() if previousStatus == 'downloaded': self.flash.add('movie-' + str(movie.id), '"%s" deleted.' % (movie.name)) return redirect(url(controller = 'movie', action = 'index'))
def alreadyDownloaded(self, movie, file, key): key = self.getKey(key) movieId = 0 if not movie else movie.id file = latinToAscii(file) results = Db.query(SubtitleHistory).filter(and_(SubtitleHistory.subtitle == key, SubtitleHistory.movie == movieId, SubtitleHistory.file == file)).all() if cherrypy.config.get('debug'): log.debug('%s already downloaded.' % results) return False else: for h in results: h.status = u'ignored' Db.flush() return len(results) > 0
def delete(self, id): ''' Mark movie as deleted ''' movie = Db.query(Movie).filter_by(id=id).one() previousStatus = movie.status #set status movie.status = u'deleted' Db.flush() if previousStatus == 'downloaded': self.flash.add('movie-' + str(movie.id), '"%s" deleted.' % (movie.name)) return redirect(url(controller='movie', action='index'))
def saveTemplates(self, templates): log.debug('Saving Templates %s' % templates) # get all items delete = {'templates': [], 'types': []} for item in self.all(custom=True): delete['templates'].append(item.id) for type in item.types: delete['types'].append(type.id) for template in templates: # Don't delete try: delete['templates'].remove(int(template['id'])) except (ValueError, TypeError): pass if int(template['id']) == 0: template['id'] = template['name'] for type in template['types']: # Don't delete try: delete['types'].remove(int(type['id'])) except (ValueError, TypeError): pass self.create(template['id'], template['name'], template['types'], waitFor=template['waitFor']) # remove all non used custom if delete['templates']: [ Db.delete(x) for x in Db.query(QualityTemplate).filter( QualityTemplate.id.in_(delete['templates'])).all() ] Db.flush() if delete['types']: [ Db.delete(x) for x in Db.query(QualityTemplateType).filter( QualityTemplateType.id.in_(delete['types'])).all() ] Db.flush()
def reAdd(self, id): ''' Re-add movie and force search ''' movie = Db.query(Movie).filter_by(id = id).one() for x in movie.queue: x.completed = False Db.flush() #set status movie.status = u'want' Db.flush() #gogo find nzb for added movie via Cron self.cron.get('yarr').forceCheck(id) self.searchers.get('etaQueue').put({'id':id}) self.flash.add('movie-' + str(movie.id), '"%s" re-added.' % (movie.name)) return redirect(url(controller = 'movie', action = 'index'))
def reAdd(self, id, **data): ''' Re-add movie and force search ''' movie = Db.query(Movie).filter_by(id = id).one() if data.get('failed'): for history in movie.history: if history.status == u'snatched': history.status = u'ignore' Db.flush() for x in movie.queue: if x.completed == True: x.completed = False Db.flush() break #set status movie.status = u'want' Db.flush() #gogo find nzb for added movie via Cron self.cron.get('yarr').forceCheck(id) self.searchers.get('etaQueue').put({'id':id}) self.flash.add('movie-' + str(movie.id), '"%s" re-added.' % (movie.name)) return redirect(url(controller = 'movie', action = 'index'))
def saveTemplates(self, templates): log.debug("Saving Templates %s" % templates) # get all items delete = {"templates": [], "types": []} for item in self.all(custom=True): delete["templates"].append(item.id) for type in item.types: delete["types"].append(type.id) for template in templates: # Don't delete try: delete["templates"].remove(int(template["id"])) except (ValueError, TypeError): pass if int(template["id"]) == 0: template["id"] = template["name"] for type in template["types"]: # Don't delete try: delete["types"].remove(int(type["id"])) except (ValueError, TypeError): pass self.create(template["id"], template["name"], template["types"], waitFor=template["waitFor"]) # remove all non used custom if delete["templates"]: [Db.delete(x) for x in Db.query(QualityTemplate).filter(QualityTemplate.id.in_(delete["templates"])).all()] Db.flush() if delete["types"]: [ Db.delete(x) for x in Db.query(QualityTemplateType).filter(QualityTemplateType.id.in_(delete["types"])).all() ] Db.flush()
def reAdd(self, id, **data): ''' Re-add movie and force search ''' movie = Db.query(Movie).filter_by(id=id).one() if data.get('failed'): for history in movie.history: if history.status == u'snatched': history.status = u'ignore' Db.flush() for x in movie.queue: if x.completed == True: x.completed = False Db.flush() break #set status movie.status = u'want' Db.flush() #gogo find nzb for added movie via Cron self.cron.get('yarr').forceCheck(id) self.searchers.get('etaQueue').put({'id': id}) self.flash.add('movie-' + str(movie.id), '"%s" re-added.' % (movie.name)) return redirect(url(controller='movie', action='index'))
def reAdd(self, id, **data): """ Re-add movie and force search """ movie = Db.query(Movie).filter_by(id=id).one() if data.get("failed"): for history in movie.history: if history.status == u"snatched": history.status = u"ignore" Db.flush() for x in movie.queue: if x.completed == True: x.completed = False Db.flush() break # set status movie.status = u"want" Db.flush() # gogo find nzb for added movie via Cron self.cron.get("yarr").forceCheck(id) self.searchers.get("etaQueue").put({"id": id}) self.flash.add("movie-" + str(movie.id), '"%s" re-added.' % (movie.name)) return redirect(url(controller="movie", action="index"))
def _addMovie(self, movie, quality, year=None): if self._checkMovieExists(movie=movie, qualityId=quality): return log.info('Adding movie to database: %s' % movie.name) if movie.id: exists = Db.query(Movie).filter_by(movieDb=movie.id).first() else: exists = Db.query(Movie).filter_by(imdb=movie.imdb).first() if exists: log.info('Movie already exists, do update.') # Delete old qualities for x in exists.queue: x.active = False Db.flush() new = exists else: new = Movie() Db.add(new) # Update the stuff new.status = u'want' new.name = movie.name new.imdb = movie.imdb new.movieDb = movie.id new.quality = quality new.year = year if year and movie.year == 'None' else movie.year Db.flush() # Add qualities to the queue quality = Db.query(QualityTemplate).filter_by(id=quality).one() for type in quality.types: queue = MovieQueue() queue.qualityType = type.type queue.movieId = new.id queue.order = type.order queue.active = True queue.completed = False queue.waitFor = 0 if type.markComplete else quality.waitFor queue.markComplete = type.markComplete Db.add(queue) Db.flush() #Get xml from themoviedb and save to cache self.searchers.get('movie').getExtraInfo(new.id, overwrite=True) #gogo find nzb for added movie via Cron self.cron.get('yarr').forceCheck(new.id) self.flash.add('movie-' + str(new.id), '"%s" (%s) added.' % (new.name, new.year))
def _addMovie(self, movie, quality, year = None): if self._checkMovieExists(movie=movie): return log.info('Adding movie to database: %s' % movie.name) if movie.id: exists = Db.query(Movie).filter_by(movieDb = movie.id).first() else: exists = Db.query(Movie).filter_by(imdb = movie.imdb).first() if exists: log.info('Movie already exists, do update.') # Delete old qualities for x in exists.queue: x.active = False Db.flush() new = exists else: new = Movie() Db.add(new) # Update the stuff new.status = u'want' new.name = movie.name new.imdb = movie.imdb new.movieDb = movie.id new.quality = quality new.year = year if year and movie.year == 'None' else movie.year Db.flush() # Add qualities to the queue quality = Db.query(QualityTemplate).filter_by(id = quality).one() for type in quality.types: queue = MovieQueue() queue.qualityType = type.type queue.movieId = new.id queue.order = type.order queue.active = True queue.completed = False queue.waitFor = 0 if type.markComplete else quality.waitFor queue.markComplete = type.markComplete Db.add(queue) Db.flush() #Get xml from themoviedb and save to cache self.searchers.get('movie').getExtraInfo(new.id, overwrite = True) #gogo find nzb for added movie via Cron self.cron.get('yarr').forceCheck(new.id) self.flash.add('movie-' + str(new.id), '"%s" (%s) added.' % (new.name, new.year))
def __init__(self, config): self.config = config # Config TheMovieDB self.theMovieDb = theMovieDb(self.config) self.sources.append(self.theMovieDb) # Config imdbWrapper self.imdb = imdbWrapper(self.config) self.sources.append(self.imdb) # Update the cache movies = Db.query(Movie).order_by(Movie.name).filter(or_(Movie.status == u'want', Movie.status == u'waiting')).all() for movie in movies: if not movie.extra: self.getExtraInfo(movie) # Fix db errors try: # Clear wrong value imdb_is_int = False try: imdb_is_int = float(movie.imdb) except ValueError: pass if not imdb_is_int and movie.imdb[:2] != 'tt': movie.imdb = None Db.flush() if movie.imdb and movie.imdb[:2] != 'tt': movie.imdb = 'tt%s' % movie.imdb Db.flush() elif not movie.imdb and movie.movieDb: results = self.findById(movie.movieDb) if results.get('imdb'): movie.imdb = results.get('imdb') Db.flush() if not movie.imdb: log.error('Errors in your database, try and remove & re-add: %s' % movie.name) except: pass
def create(self, name, label, types, waitFor=0, custom=True, order=0): newQ = QualityTemplate() exists = Db.query(QualityTemplate).filter( or_(QualityTemplate.name == name, QualityTemplate.id == name)).first() if not exists: log.info('Creating custom=%s quality: %s' % (custom, name)) newQ.name = name newQ.label = label newQ.custom = custom newQ.waitFor = waitFor newQ.order = order Db.add(newQ) Db.flush() exists = Db.query(QualityTemplate).filter_by(name=name).first() else: exists.label = label exists.waitFor = waitFor Db.flush() nr = 1 for type in types: # Update if needed newT = Db.query(QualityTemplateType).filter_by( quality=exists.id, type=type['type']).first() if not newT: newT = QualityTemplateType() newT.quality = exists.id newT.order = nr newT.type = type['type'] newT.markComplete = type['markComplete'] nr += 1 Db.add(newT) Db.flush() return True
def create(self, name, label, types, waitFor = 0, custom = True, order = 0): newQ = QualityTemplate() exists = Db.query(QualityTemplate).filter(or_(QualityTemplate.name == name, QualityTemplate.id == name)).first() if not exists: log.info('Creating custom=%s quality: %s' % (custom, name)) newQ.name = name newQ.label = label newQ.custom = custom newQ.waitFor = waitFor newQ.order = order Db.add(newQ) Db.flush() exists = Db.query(QualityTemplate).filter_by(name = name).first() else: exists.label = label exists.waitFor = waitFor Db.flush() nr = 1 for type in types: # Update if needed newT = Db.query(QualityTemplateType).filter_by(quality = exists.id, type = type['type']).first() if not newT: newT = QualityTemplateType() newT.quality = exists.id newT.order = nr newT.type = type['type'] newT.markComplete = type['markComplete'] nr += 1 Db.add(newT) Db.flush() return True
def _search(self, movie, force = False): # Stop caching ffs! Db.expire_all() # Check release date and search for appropriate qualities preReleaseSearch = False dvdReleaseSearch = False now = int(time.time()) # Search all if ETA is unknow, but try update ETA for next time. log.debug('Calculate ETA') checkETA = False if not movie.eta: checkETA = True preReleaseSearch = True dvdReleaseSearch = True else: # Prerelease 1 week before theaters if movie.eta.theater <= now + 604800: preReleaseSearch = True # dvdRelease 6 weeks before dvd release if movie.eta.dvd <= now + 3628800: preReleaseSearch = True dvdReleaseSearch = True # Dvd date is unknown but movie is in theater already if movie.eta.dvd == 0 and movie.eta.theater > now: dvdReleaseSearch = False # Force ETA check if movie.eta.lastCheck < now: checkETA = True # Minimal week interval for ETA check if checkETA and self.config.get('MovieETA', 'enabled'): cherrypy.config.get('searchers').get('etaQueue').put({'id':movie.id}) for queue in movie.queue: # Movie already found, don't search further if queue.completed: log.debug('%s already completed for "%s". Not searching for any qualities below.' % (queue.qualityType, movie.name)) return True # only search for active and not completed, minimal 1 min since last search if queue.active and not queue.completed and not self.abort and not self.stop: #skip if no search is set log.debug('Needs a search?') if (not ((preReleaseSearch and queue.qualityType in Qualities.preReleases) or (dvdReleaseSearch and not queue.qualityType in Qualities.preReleases))) and not queue.lastCheck < (now - int(self.config.get('Intervals', 'search')) * 7200): continue log.debug('Start searching for movie: %s' % movie.name) highest = self.provider.find(movie, queue) log.debug('End searching for movie: %s' % movie.name) #send highest to SABnzbd & mark as snatched if highest: log.debug('Found highest') #update what I found queue.name = latinToAscii(highest.name) queue.link = highest.detailUrl Db.flush() waitFor = queue.waitFor * (60 * 60 * 24) if queue.markComplete or (not queue.markComplete and highest.date + waitFor < time.time()): time.sleep(10) # Give these APIs air! if self.config.get('NZB', 'sendTo') == 'Sabnzbd' and highest.type == 'nzb': success = self.sabNzbd.send(highest, movie.imdb) elif self.config.get('NZB', 'sendTo') == 'Nzbget' and highest.type == 'nzb': success = self.nzbGet.send(highest) elif self.config.get('Torrents', 'sendTo') == 'Transmission' and highest.type == 'torrent': success = self.transmission.send(highest, movie.imdb) else: success = self.blackHole(highest) else: success = False log.info('Found %s but waiting for %d hours.' % (highest.name, ((highest.date + waitFor) - time.time()) / (60 * 60))) # Set status if success: log.debug('Success') movie.status = u'snatched' if queue.markComplete else u'waiting' movie.dateChanged = datetime.datetime.now() queue.lastCheck = now queue.completed = True Db.flush() # Add to history h = History() h.movie = movie.id h.value = str(highest.id) + '-' + str(highest.size) h.status = u'snatched' Db.add(h) Db.flush() # Notify PROWL if self.config.get('PROWL', 'onSnatch'): log.debug('PROWL') prowl = PROWL() prowl.notify(highest.name, 'Download Started') # Notify XBMC if self.config.get('XBMC', 'onSnatch'): log.debug('XBMC') xbmc = XBMC() xbmc.notify('Snatched %s' % highest.name) # Notify GROWL if self.config.get('GROWL', 'onSnatch'): log.debug('GROWL') growl = GROWL() growl.notify('Snatched %s' % highest.name, 'Download Started') # Notify Notifo if self.config.get('Notifo', 'onSnatch'): log.debug('Notifo') notifo = Notifo() notifo.notify('%s' % highest.name, "Snatched:") # Notify NotifyMyAndroid if self.config.get('NMA', 'onSnatch'): log.debug('NotifyMyAndroid') nma = NMA() nma.notify('Download Started', 'Snatched %s' % highest.name) # Notify Twitter if self.config.get('Twitter', 'onSnatch'): log.debug('Twitter') twitter = Twitter() twitter.notify('Download Started', 'Snatched %s' % highest.name) return True queue.lastCheck = now Db.flush() return False
def _search(self, movie, force=False): # Stop caching ffs! Db.expire_all() # Check release date and search for appropriate qualities preReleaseSearch = False dvdReleaseSearch = False now = int(time.time()) # Search all if ETA is unknow, but try update ETA for next time. log.debug('Calculate ETA') checkETA = False if not movie.eta: checkETA = True preReleaseSearch = True dvdReleaseSearch = True else: # Prerelease 1 week before theaters if movie.eta.theater <= now + 604800: preReleaseSearch = True # dvdRelease 6 weeks before dvd release if movie.eta.dvd <= now + 3628800: preReleaseSearch = True dvdReleaseSearch = True # Dvd date is unknown but movie is in theater already if movie.eta.dvd == 0 and movie.eta.theater > now: dvdReleaseSearch = False # Force ETA check if movie.eta.lastCheck < now: checkETA = True # Minimal week interval for ETA check if checkETA and self.config.get('MovieETA', 'enabled'): cherrypy.config.get('searchers').get('etaQueue').put( {'id': movie.id}) for queue in movie.queue: # Movie already found, don't search further if queue.completed: log.debug( '%s already completed for "%s". Not searching for any qualities below.' % (queue.qualityType, movie.name)) return True # only search for active and not completed, minimal 1 min since last search if queue.active and not queue.completed and not self.abort and not self.stop: #skip if no search is set log.debug('Needs a search?') if (not ((preReleaseSearch and queue.qualityType in Qualities.preReleases) or (dvdReleaseSearch and not queue.qualityType in Qualities.preReleases)) ) and not queue.lastCheck < (now - int( self.config.get('Intervals', 'search')) * 7200): continue log.debug('Start searching for movie: %s' % movie.name) highest = self.provider.find(movie, queue) log.debug('End searching for movie: %s' % movie.name) #send highest to SABnzbd & mark as snatched if highest: log.debug('Found highest') #update what I found queue.name = latinToAscii(highest.name) queue.link = highest.detailUrl Db.flush() waitFor = queue.waitFor * (60 * 60 * 24) if queue.markComplete or ( not queue.markComplete and highest.date + waitFor < time.time()): time.sleep(10) # Give these APIs air! if self.config.get( 'NZB', 'sendTo' ) == 'Sabnzbd' and highest.type == 'nzb': success = self.sabNzbd.send(highest, movie.imdb) elif self.config.get( 'NZB', 'sendTo' ) == 'Nzbget' and highest.type == 'nzb': success = self.nzbGet.send(highest) elif self.config.get( 'Torrents', 'sendTo' ) == 'Transmission' and highest.type == 'torrent': success = self.transmission.send( highest, movie.imdb) else: success = self.blackHole(highest) else: success = False log.info('Found %s but waiting for %d hours.' % (highest.name, ((highest.date + waitFor) - time.time()) / (60 * 60))) # Set status if success: log.debug('Success') movie.status = u'snatched' if queue.markComplete else u'waiting' movie.dateChanged = datetime.datetime.now() queue.lastCheck = now queue.completed = True Db.flush() # Add to history h = History() h.movie = movie.id h.value = str(highest.id) + '-' + str(highest.size) h.status = u'snatched' Db.add(h) Db.flush() # Notify PROWL if self.config.get('PROWL', 'onSnatch'): log.debug('PROWL') prowl = PROWL() prowl.notify(highest.name, 'Download Started') # Notify XBMC if self.config.get('XBMC', 'onSnatch'): log.debug('XBMC') xbmc = XBMC() xbmc.notify('Snatched %s' % highest.name) # Notify GROWL if self.config.get('GROWL', 'onSnatch'): log.debug('GROWL') growl = GROWL() growl.notify('Snatched %s' % highest.name, 'Download Started') # Notify Notifo if self.config.get('Notifo', 'onSnatch'): log.debug('Notifo') notifo = Notifo() notifo.notify('%s' % highest.name, "Snatched:") # Notify SNS if self.config.get('SNS', 'onSnatch'): log.debug('SNS') sns = SNS() sns.notify('%s' % highest.name, "Snatched:") # Notify Boxcar if self.config.get('Boxcar', 'onSnatch'): log.debug('Boxcar') boxcar = Boxcar() boxcar.notify('%s' % highest.name, "Snatched:") # Notify NotifyMyAndroid if self.config.get('NMA', 'onSnatch'): log.debug('NotifyMyAndroid') nma = NMA() nma.notify('Download Started', 'Snatched %s' % highest.name) # Notify NotifyMyWindowsPhone if self.config.get('NMWP', 'onSnatch'): log.debug('NotifyMyWindowsPhone') nmwp = NMWP() nmwp.notify('Download Started', 'Snatched %s' % highest.name) # Notify Twitter if self.config.get('Twitter', 'onSnatch'): log.debug('Twitter') twitter = Twitter() twitter.notify('Download Started', 'Snatched %s' % highest.name) return True queue.lastCheck = now Db.flush() return False
def renameFiles(self, files, movie, queue = None): ''' rename files based on movie data & conf ''' multiple = False if len(files['files']) > 1: multiple = True destination = self.conf('destination') folderNaming = self.conf('foldernaming') fileNaming = self.conf('filenaming') # Remove weird chars from moviename moviename = re.sub(r"[\x00\/\\:\*\?\"<>\|]", '', movie.name) # Put 'The' at the end namethe = moviename if moviename[:3].lower() == 'the': namethe = moviename[3:] + ', The' #quality if not queue: queue = self.getQueue(movie) if not queue: quality = Qualities().guess(files['files']) queueId = 0 else: quality = Qualities.types[queue.qualityType]['label'] queueId = queue.id replacements = { 'cd': '', 'cdNr': '', 'ext': '.mkv', 'namethe': namethe.strip(), 'thename': moviename.strip(), 'year': movie.year, 'first': namethe[0].upper(), 'quality': quality, } if multiple: cd = 1 justAdded = [] totalSize = 0 for file in files['files']: fullPath = os.path.join(file['path'], file['filename']) totalSize += os.path.getsize(fullPath) # Do something with ISO, as they should be between DVDRip and BRRIP ext = os.path.splitext(file['filename'])[1].lower()[1:] if ext == 'iso': totalSize -= (os.path.getsize(fullPath) / 1.6) log.info('Total size of new files is %s.' % int(totalSize / 1024 / 1024)) finalDestination = None finalFilename = self.doReplace(fileNaming, replacements) for file in sorted(files['files']): log.info('Trying to find a home for: %s' % latinToAscii(file['filename'])) replacements['ext'] = file['ext'] if multiple: replacements['cd'] = ' cd' + str(cd) replacements['cdNr'] = ' ' + str(cd) replacements['original'] = file['root'] replacements['video'] = self.getCodec(file['filename'], RenamerCron.videoCodecs) replacements['audio'] = self.getCodec(file['filename'], RenamerCron.audioCodecs) replacements['group'] = self.getGroup(file['root']) folder = self.doReplace(folderNaming, replacements) filename = self.doReplace(fileNaming, replacements) old = os.path.join(file['path'], file['filename']) dest = os.path.join(destination, folder, filename) finalDestination = os.path.dirname(dest) if not os.path.isdir(finalDestination): # Use same permissions as conf('destination') folder try: #mode = os.stat(destination) #chmod = mode[ST_MODE] & 07777 log.info('Creating directory %s' % finalDestination) os.makedirs(finalDestination) shutil.copymode(destination, finalDestination) #os.chmod(finalDestination, chmod) except OSError: log.error('Failed setting permissions for %s' % finalDestination) os.makedirs(finalDestination) # Remove old if better quality removed = self.removeOld(os.path.join(destination, folder), justAdded, totalSize) if not os.path.isfile(dest) and removed: log.info('Moving file "%s" to %s.' % (latinToAscii(old), dest)) shutil.move(old, dest) justAdded.append(dest) else: try: path = file['path'].split(os.sep) path.extend(['_EXISTS_' + path.pop()]) shutil.move(file['path'], os.sep.join(path)) except IOError: pass log.error('File %s already exists or not better.' % latinToAscii(filename)) break #get subtitle if any & move if len(files['subtitles']) > 0: log.info('Moving matching subtitle.') subtitle = files['subtitles'].pop(0) replacements['ext'] = subtitle['ext'] subFilename = self.doReplace(fileNaming, replacements) shutil.move(os.path.join(subtitle['path'], subtitle['filename']), os.path.join(destination, folder, subFilename)) # Add to renaming history h = RenameHistory() h.movieId = movie.id h.movieQueue = queueId h.old = unicode(old.decode('utf-8')) h.new = unicode(dest.decode('utf-8')) Db.add(h) Db.flush() if multiple: cd += 1 # Mark movie downloaded if queueId > 0: if queue.markComplete: movie.status = u'downloaded' queue.completed = True Db.flush() return { 'directory': finalDestination, 'filename': finalFilename }
def getExtraInfo(self, movie, overwrite = False): if(type(movie) in [int, str, unicode]): movie = Db.query(Movie).filter_by(id = movie).one() # Try and update if no tmdbId if not movie.movieDb: result = self.theMovieDb.findByImdbId(movie.imdb) if result: movie.movieDb = result.id Db.flush() if not movie.movieDb: log.error('Search failed for "%s", no TheMovieDB id.' % movie.name) return movieId = movie.id theMovieDbId = movie.movieDb self.cacheExtra(theMovieDbId, overwrite) xmlFile = os.path.join(cherrypy.config.get('cachePath'), 'xml', str(theMovieDbId) + '.xml') if os.path.isfile(xmlFile): if overwrite: log.info('Getting extra movie info for %s.' % movie.name) handle = open(xmlFile, 'r') movieInfo = self.theMovieDb.getItems(handle, 'movies/movie') if not movieInfo: return movieInfo = movieInfo[0] # rating rating = self.theMovieDb.gettextelement(movieInfo, 'rating') self.saveExtra(movieId, 'rating', rating) overview = self.theMovieDb.gettextelement(movieInfo, 'overview') if overview: overview = self.theMovieDb.toSaveString(overview) self.saveExtra(movieId, 'overview', overview) hasPosterThumb = False images = movieInfo.findall('images/image') hasPosterCover = False hasPosterMid = False hasPosterThumb = False for image in images: imageFile = str(theMovieDbId) + '-' + image.get('type') + '-' + image.get('size') + '.jpg' if image.get('type') == 'poster' and image.get('size') == 'cover' and not hasPosterCover: poster = self.theMovieDb.saveImage(image.get('url'), imageFile) if poster: self.saveExtra(movieId, 'poster_cover', poster) hasPosterCover = True if image.get('type') == 'poster' and image.get('size') == 'mid' and not hasPosterMid: poster = self.theMovieDb.saveImage(image.get('url'), imageFile) if poster: self.saveExtra(movieId, 'poster_mid', poster) hasPosterMid = True if image.get('type') == 'poster' and image.get('size') == 'thumb' and not hasPosterThumb: poster = self.theMovieDb.saveImage(image.get('url'), imageFile) if poster: self.saveExtra(movieId, 'poster_thumb', poster) hasPosterThumb = True handle.close()
def determineMovie(self, movie): result = False movieName = self.cleanName(movie["folder"]) movieYear = self.findYear(movie["folder"]) # check to see if the downloaded movie nfo file agrees with what we thought we were downloading if movie["info"]["cpnfoImdb"] and movie["info"]["imdb"]: cpnfoimdb = movie["info"]["cpnfoImdb"].replace("tt", "") nfoimdb = movie["info"]["imdb"].replace("tt", "") if cpnfoimdb != nfoimdb: log.info("Downloaded movie's nfo has imdb id that doesn't match what we though we downloaded") # Would be nice to develop some sort of 'holding area' for "iffy" movies like this # For now, assume the movie's nfo is wrong... movie["info"]["imdb"] = cpnfoimdb else: movie["info"]["imdb"] = cpnfoimdb if movie["info"]["imdb"]: byImdb = self.getMovieByIMDB(movie["info"]["imdb"]) if byImdb: return byImdb else: result = cherrypy.config["searchers"]["movie"].findByImdbId(movie["info"]["imdb"]) if not result: # Check and see if name is in queue try: queue = Db.query(MovieQueue).filter_by(name=movie["folder"]).first() if queue: log.info("Found movie via MovieQueue.") return queue.Movie except: pass # Find movie via movie name try: m = Db.query(Movie).filter_by(name=movieName).first() if m: log.info("Found movie via moviename.") return m except: pass # Try and match the movies via filenaming for file in movie["files"]: dirnames = movie["path"].replace(unicode(self.config.get("Renamer", "download")), "").split(os.path.sep) dirnames.append(file["filename"]) dirnames.reverse() for dir in dirnames: dir = self.cleanName(dir) # last resort, match every word in path to db lastResort = {} dirSplit = re.split("\W+", dir.lower()) for s in dirSplit: if s: results = ( Db.query(Movie).filter(Movie.name.like("%" + s + "%")).filter_by(year=movieYear).all() ) for r in results: lastResort[r.id] = r for l in lastResort.itervalues(): wordCount = 0 for word in dirSplit: if word in l.name.lower(): wordCount += 1 if wordCount == len(dirSplit) and len(dirSplit) > 0: return l # Search tMDB if movieName and not movieName in ["movie"]: log.info('Searching for "%s".' % movie["folder"]) result = cherrypy.config["searchers"]["movie"].find(movieName + " " + movieYear, limit=1) if result: movie = self.getMovieByIMDB(result.imdb) if not movie: new = Movie() Db.add(new) try: # Add found movie as downloaded new.status = u"downloaded" new.name = result.name new.imdb = result.imdb new.movieDb = result.id new.year = result.year Db.flush() return new except Exception, e: log.error("Movie could not be added to database %s. %s" % (result, e)) else: return movie
def _addMovie(self, movie, quality, year=None): if cherrypy.config.get('config').get('XBMC', 'dbpath'): for root, dirs, files in os.walk( cherrypy.config.get('config').get('XBMC', 'dbpath')): for file in files: if file.startswith('MyVideos'): dbfile = os.path.join(root, file) if dbfile: #------Opening connection to XBMC DB------ connXbmc = MySqlite.connect(dbfile) if connXbmc: log.debug('Checking if movie exists in XBMC by IMDB id:' + movie.imdb) connXbmc.row_factory = MySqlite.Row cXbmc = connXbmc.cursor() cXbmc.execute('select c09 from movie where c09="' + movie.imdb + '"') #------End of Opening connection to XBMC DB------ inXBMC = False for rowXbmc in cXbmc: # do a final check just to be sure log.debug('Found in XBMC:' + rowXbmc["c09"]) if movie.imdb == rowXbmc["c09"]: inXBMC = True else: inXBMC = False cXbmc.close() if inXBMC: log.info('Movie already exists in XBMC, skipping.') return else: log.info( 'Could not connect to the XBMC database at ' + cherrypy.config.get('config').get('XBMC', 'dbpath')) else: log.info('Could not find the XBMC MyVideos db at ' + cherrypy.config.get('config').get('XBMC', 'dbpath')) log.info('Adding movie to database: %s' % movie.name) if movie.id: exists = Db.query(Movie).filter_by(movieDb=movie.id).first() else: exists = Db.query(Movie).filter_by(imdb=movie.imdb).first() if exists: log.info('Movie already exists, do update.') # Delete old qualities for x in exists.queue: x.active = False Db.flush() new = exists else: new = Movie() Db.add(new) # Update the stuff new.status = u'want' new.name = movie.name new.imdb = movie.imdb new.movieDb = movie.id new.quality = quality new.year = year if year and movie.year == 'None' else movie.year Db.flush() # Add qualities to the queue quality = Db.query(QualityTemplate).filter_by(id=quality).one() for type in quality.types: queue = MovieQueue() queue.qualityType = type.type queue.movieId = new.id queue.order = type.order queue.active = True queue.completed = False queue.waitFor = 0 if type.markComplete else quality.waitFor queue.markComplete = type.markComplete Db.add(queue) Db.flush() #Get xml from themoviedb and save to cache self.searchers.get('movie').getExtraInfo(new.id, overwrite=True) #gogo find nzb for added movie via Cron self.cron.get('yarr').forceCheck(new.id) self.flash.add('movie-' + str(new.id), '"%s" (%s) added.' % (new.name, new.year))
def determineMovie(self, movie): movieName = self.cleanName(movie['folder']) movieYear = self.findYear(movie['folder']) if movie['nfo']: for nfo in movie['nfo']: nfoFile = open(os.path.join(movie['path'], nfo), 'r').read() imdbId = self.getImdb(nfoFile) if imdbId: m = cherrypy.config['searchers']['movie'].findByImdbId(imdbId) if m: return m # check and see if name is in queue queue = Db.query(MovieQueue).filter_by(name = movieName).first() if queue: log.info('Found movie via MovieQueue.') return queue.Movie for file in movie['files']: dirnames = movie['path'].split(os.path.sep) dirnames.append(file['filename']) dirnames.reverse() for dir in dirnames: dir = self.cleanName(dir) # last resort, match every word in path to db lastResort = {} dirSplit = re.split('\W+', dir.lower()) for s in dirSplit: if s: results = Db.query(Movie).filter(Movie.name.like('%' + s + '%')).filter_by(year = movieYear).all() for r in results: lastResort[r.id] = r for l in lastResort.itervalues(): wordCount = 0 for word in dirSplit: if word in l.name.lower(): wordCount += 1 if wordCount == len(dirSplit) and len(dirSplit) > 0: return l # Search tMDB if movieName: log.info('Searching for "%s".' % movie['folder']) result = cherrypy.config['searchers']['movie'].find(movieName + ' ' + movieYear, limit = 1) if result: movie = self.getMovieByIMDB(result.imdb) if not movie: new = Movie() Db.add(new) try: # Add found movie as downloaded new.status = u'downloaded' new.name = result.name new.imdb = result.imdb new.movieDb = result.id new.year = result.year Db.flush() return new except Exception, e: log.error('Movie could not be added to database %s. %s' % (result, e)) else: return movie
def getExtraInfo(self, movie, overwrite=False): if type(movie) in [int, str, unicode]: movie = Db.query(Movie).filter_by(id=movie).one() # Try and update if no tmdbId if not movie.movieDb: result = self.theMovieDb.findByImdbId(movie.imdb) if result: movie.movieDb = result.id Db.flush() if not movie.movieDb: log.error('Search failed for "%s", no TheMovieDB id.' % movie.name) return movieId = movie.id theMovieDbId = movie.movieDb self.cacheExtra(theMovieDbId, overwrite) xmlFile = os.path.join(cherrypy.config.get("cachePath"), "xml", str(theMovieDbId) + ".xml") if os.path.isfile(xmlFile): if overwrite: log.info("Getting extra movie info for %s." % movie.name) handle = open(xmlFile, "r") movieInfo = self.theMovieDb.getItems(handle, "movies/movie") if not movieInfo: return movieInfo = movieInfo[0] # rating rating = self.theMovieDb.gettextelement(movieInfo, "rating") self.saveExtra(movieId, "rating", rating) overview = self.theMovieDb.gettextelement(movieInfo, "overview") if overview: overview = self.theMovieDb.toSaveString(overview) self.saveExtra(movieId, "overview", overview) hasPosterThumb = False images = movieInfo.findall("images/image") hasPosterCover = False hasPosterMid = False hasPosterThumb = False for image in images: imageFile = str(theMovieDbId) + "-" + image.get("type") + "-" + image.get("size") + ".jpg" if image.get("type") == "poster" and image.get("size") == "cover" and not hasPosterCover: poster = self.theMovieDb.saveImage(image.get("url"), imageFile) if poster: self.saveExtra(movieId, "poster_cover", poster) hasPosterCover = True if image.get("type") == "poster" and image.get("size") == "mid" and not hasPosterMid: poster = self.theMovieDb.saveImage(image.get("url"), imageFile) if poster: self.saveExtra(movieId, "poster_mid", poster) hasPosterMid = True if image.get("type") == "poster" and image.get("size") == "thumb" and not hasPosterThumb: poster = self.theMovieDb.saveImage(image.get("url"), imageFile) if poster: self.saveExtra(movieId, "poster_thumb", poster) hasPosterThumb = True handle.close()
def determineMovie(self, movie): result = False movieName = self.cleanName(movie['folder']) movieYear = self.findYear(movie['folder']) #check to see if the downloaded movie nfo file agrees with what we thought we were downloading if movie['info']['cpnfoImdb'] and movie['info']['imdb']: cpnfoimdb = 'tt' + movie['info']['cpnfoImdb'].replace("tt", '') nfoimdb = 'tt' + movie['info']['imdb'].replace("tt", '') if cpnfoimdb != nfoimdb: log.info( "Downloaded movie's nfo has imdb id that doesn't match what we though we downloaded" ) movie['info']['imdb'] = cpnfoimdb if movie['info']['imdb']: byImdb = self.getMovieByIMDB(movie['info']['imdb']) if byImdb: return byImdb else: result = cherrypy.config['searchers']['movie'].findByImdbId( movie['info']['imdb']) if not result: # Check and see if name is in queue try: queue = Db.query(MovieQueue).filter_by( name=movie['folder']).first() if queue: log.info('Found movie via MovieQueue.') return queue.Movie except: pass # Find movie via movie name try: m = Db.query(Movie).filter_by(name=movieName).first() if m: log.info('Found movie via moviename.') return m except: pass # Try and match the movies via filenaming for file in movie['files']: dirnames = movie['path'].lower().replace( unicode(self.config.get('Renamer', 'download')).lower(), '').split(os.path.sep) dirnames.append(file['filename']) dirnames.reverse() for dir in dirnames: dir = self.cleanName(dir) # last resort, match every word in path to db lastResort = {} dirSplit = re.split('\W+', dir.lower()) for s in dirSplit: if s: results = Db.query(Movie).filter( Movie.name.like('%' + s + '%')).filter_by( year=movieYear).all() for r in results: lastResort[r.id] = r for l in lastResort.itervalues(): wordCount = 0 for word in dirSplit: if word in l.name.lower(): wordCount += 1 if wordCount == len(dirSplit) and len(dirSplit) > 0: return l # Search tMDB if movieName and not movieName in ['movie']: log.info('Searching for "%s".' % movie['folder']) result = cherrypy.config['searchers']['movie'].find( movieName + ' ' + movieYear, limit=1) if result: movie = self.getMovieByIMDB(result.imdb) if not movie: new = Movie() Db.add(new) try: # Add found movie as downloaded new.status = u'downloaded' new.name = result.name new.imdb = result.imdb new.movieDb = result.id new.year = result.year Db.flush() return new except Exception, e: log.error('Movie could not be added to database %s. %s' % (result, e)) else: return movie
def save(self, **data): ''' Save all config settings ''' config = cherrypy.config.get('config') # catch checkboxes bools = filter(lambda s: not data.get(s), [ 'global.launchbrowser', 'global.updater', 'XBMC.enabled', 'XBMC.onSnatch', 'NMJ.enabled', 'PLEX.enabled', 'PROWL.enabled', 'PROWL.onSnatch', 'GROWL.enabled', 'GROWL.onSnatch', 'Notifo.enabled', 'Notifo.onSnatch', 'Boxcar.enabled', 'Boxcar.onSnatch', 'NMA.enable', 'NMA.onSnatch', 'Twitter.enabled', 'Twitter.onSnatch', 'Trakt.notification_enabled', 'Trakt.watchlist_remove', 'Trakt.watchlist_enabled', 'Trakt.dontaddcollection', 'Meta.enabled', 'MovieETA.enabled', 'Renamer.enabled', 'Renamer.trailerQuality', 'Renamer.cleanup', 'Torrents.enabled', 'NZB.enabled', 'NZBMatrix.enabled', 'NZBMatrix.english', 'NZBMatrix.ssl', 'NZBsRUS.enabled', 'newzbin.enabled', 'NZBsorg.enabled', 'newznab.enabled', 'x264.enabled', 'Subtitles.enabled', 'Subtitles.addLanguage', 'MovieRSS.enabled', 'KinepolisRSS.enabled', ]) data.update(data.fromkeys(bools, False)) # Do quality order order = data.get('Quality.order').split(',') for id in order: qo = Db.query(QualityTemplate).filter_by(id=int(id)).one() qo.order = order.index(id) Db.flush() del data['Quality.order'] # Save templates if data.get('Quality.templates'): templates = json.loads(data.get('Quality.templates')) Qualities().saveTemplates(templates) del data['Quality.templates'] # Save post data for name in data: section = name.split('.')[0] var = name.split('.')[1] config.set(section, var, data[name]) # Change cron interval self.cron.get('yarr').setInterval(config.get('Intervals', 'search')) config.save() self.flash.add('config', 'Settings successfully saved.') return redirect(cherrypy.request.headers.get('referer'))
def renameFiles(self, movie): """ rename files based on movie data & conf """ multiple = False if len(movie["files"]) > 1: multiple = True destination = self.conf("destination") folderNaming = self.conf("foldernaming") fileNaming = self.conf("filenaming") # Remove weird chars from moviename moviename = re.sub(r"[\x00\/\\:\*\?\"<>\|]", "", movie["info"].get("name")) # Put 'The' at the end namethe = moviename if moviename[:4].lower() == "the ": namethe = moviename[4:] + ", The" replacements = { "cd": "", "cdNr": "", "ext": ".mkv", "namethe": namethe.strip(), "thename": moviename.strip(), "year": movie["info"]["year"], "first": namethe[0].upper(), "quality": movie["info"]["quality"], "video": movie["info"]["codec"]["video"], "audio": movie["info"]["codec"]["audio"], "group": movie["info"]["group"], "resolution": movie["info"]["resolution"], "sourcemedia": movie["info"]["sourcemedia"], } if multiple: cd = 1 justAdded = [] finalDestination = None finalFilename = self.doReplace(fileNaming, replacements) for file in movie["files"]: log.info("Trying to find a home for: %s" % latinToAscii(file["filename"])) replacements["ext"] = file["ext"] if multiple: replacements["cd"] = " cd" + str(cd) replacements["cdNr"] = " " + str(cd) replacements["original"] = file["filename"] folder = self.doReplace(folderNaming, replacements) filename = self.doReplace(fileNaming, replacements) old = os.path.join(movie["path"], file["filename"]) dest = os.path.join(destination, folder, filename) finalDestination = os.path.dirname(dest) if not os.path.isdir(finalDestination): try: log.info("Creating directory %s" % finalDestination) os.makedirs(finalDestination) shutil.copymode(destination, finalDestination) except OSError: log.error("Failed changing permissions %s" % finalDestination) # Remove old if better quality removed = self.removeOld(os.path.join(destination, folder), justAdded, movie["info"]["size"]) if not os.path.isfile(dest) and removed: log.info('Moving file "%s" to %s.' % (latinToAscii(old), dest)) shutil.move(old, dest) justAdded.append(dest) else: try: path = file["path"].split(os.sep) path.extend(["_EXISTS_" + path.pop()]) shutil.move(file["path"], os.sep.join(path)) except IOError: pass log.error("File %s already exists or not better." % latinToAscii(filename)) break # get subtitle if any & move for type in movie["subtitles"]: if len(movie["subtitles"][type]) > 0: log.info("Moving matching subtitle.") subtitle = movie["subtitles"][type].pop(0) replacements["ext"] = subtitle["ext"] subDest = os.path.join(destination, folder, self.doReplace(fileNaming, replacements)) shutil.move(os.path.join(movie["path"], subtitle["filename"]), subDest) justAdded.append(subDest) # Add to ignore list when removing stuff. # Add to renaming history h = RenameHistory() Db.add(h) h.movieQueue = movie["queue"].id if movie["queue"] else 0 h.old = unicode(old.decode("utf-8")) h.new = unicode(dest.decode("utf-8")) Db.flush() if multiple: cd += 1 # Mark movie downloaded if movie["queue"] and movie["queue"].id > 0: if movie["queue"].markComplete: movie["movie"].status = u"downloaded" movie["queue"].completed = True Db.flush() return {"directory": finalDestination, "filename": finalFilename}
def renameFiles(self, movie): ''' rename files based on movie data & conf ''' multiple = False if len(movie['files']) > 1: multiple = True destination = self.conf('destination') folderNaming = self.conf('foldernaming') fileNaming = self.conf('filenaming') # Remove weird chars from moviename moviename = re.sub(r"[\x00\/\\:\*\?\"<>\|]", '', movie['info'].get('name')) # Put 'The' at the end namethe = moviename if moviename[:4].lower() == 'the ': namethe = moviename[4:] + ', The' replacements = { 'cd': '', 'cdNr': '', 'ext': 'mkv', 'namethe': namethe.strip(), 'thename': moviename.strip(), 'year': movie['info']['year'], 'first': namethe[0].upper(), 'quality': movie['info']['quality'], 'video': movie['info']['codec']['video'], 'audio': movie['info']['codec']['audio'], 'group': movie['info']['group'], 'resolution': movie['info']['resolution'], 'sourcemedia': movie['info']['sourcemedia'] } if multiple: cd = 1 justAdded = [] finalDestination = None #clean up post-processing script ppScriptName = movie['info'].get('ppScriptName') ppDirName = self.config.get('Sabnzbd', 'ppDir') if ppScriptName: if ppDirName: ppPath = os.path.join(ppDirName, ppScriptName) try: os.remove(ppPath) log.info("Removed post-processing script: %s" % ppPath) except: log.info("Couldn't remove post-processing script: %s" % ppPath) else: log.info("Don't know where the post processing script is located, not removing %s" % ppScriptName) filenames = [] for file in movie['files']: log.info('Trying to find a home for: %s' % latinToAscii(file['filename'])) replacements['ext'] = file['ext'] if multiple: replacements['cd'] = ' cd' + str(cd) replacements['cdNr'] = ' ' + str(cd) replacements['original'] = file['filename'] folder = self.doReplace(folderNaming, replacements) filename = self.doReplace(fileNaming, replacements) filenames.append(filename) old = os.path.join(movie['path'], file['filename']) dest = os.path.join(destination, folder, filename) finalDestination = os.path.dirname(dest) if not os.path.isdir(finalDestination): try: log.info('Creating directory %s' % finalDestination) os.makedirs(finalDestination) shutil.copymode(destination, finalDestination) except OSError: log.error('Failed changing permissions %s' % finalDestination) # Remove old if better quality removed = self.removeOld(os.path.join(destination, folder), justAdded, movie['info']['size']) if not os.path.isfile(dest) and removed: log.info('Moving file "%s" to %s.' % (latinToAscii(old), dest)) if not _move(old, dest): break justAdded.append(dest) else: try: log.error('File %s already exists or not better.' % latinToAscii(filename)) path = file['path'].split(os.sep) path.extend(['_EXISTS_' + path.pop()]) old = file['path'] dest = os.sep.join(path) _move(old, dest) except: log.error('Could not extend path name.') break #get subtitle if any & move for type in movie['subtitles']: if len(movie['subtitles'][type]) > 0: log.info('Moving matching subtitle.') subtitle = movie['subtitles'][type].pop(0) replacements['original'] = subtitle['filename'] replacements['ext'] = subtitle['ext'] subDest = os.path.join(destination, folder, self.doReplace(fileNaming, replacements)) old = os.path.join(movie['path'], subtitle['filename']) if not _move(old, subDest): break justAdded.append(subDest) # Add to ignore list when removing stuff. # Add to renaming history log.debug('renamehistory start') h = RenameHistory() Db.add(h) try: h.movieQueue = movie['queue'].id except: h.movieQueue = 0 h.old = unicode(old.decode('utf-8')) h.new = unicode(dest.decode('utf-8')) Db.flush() log.debug('renamehistory end') if multiple: cd += 1 # Mark movie downloaded log.debug('queue downloaded start') if movie['queue'] and movie['queue'].id > 0: if movie['queue'].markComplete: movie['movie'].status = u'downloaded' movie['queue'].completed = True Db.flush() log.debug('queue downloaded end') return { 'directory': finalDestination, 'filenames': filenames }
def renameFiles(self, movie): ''' rename files based on movie data & conf ''' multiple = False if len(movie['files']) > 1: multiple = True destination = self.conf('destination') folderNaming = self.conf('foldernaming') fileNaming = self.conf('filenaming') # Remove weird chars from moviename moviename = re.sub(r"[\x00\/\\:\*\?\"<>\|]", '', movie['info'].get('name')) # Put 'The' at the end namethe = moviename if moviename[:4].lower() == 'the ': namethe = moviename[4:] + ', The' replacements = { 'cd': '', 'cdNr': '', 'ext': 'mkv', 'namethe': namethe.strip(), 'thename': moviename.strip(), 'year': movie['info']['year'], 'first': namethe[0].upper(), 'quality': movie['info']['quality'], 'video': movie['info']['codec']['video'], 'audio': movie['info']['codec']['audio'], 'group': movie['info']['group'], 'resolution': movie['info']['resolution'], 'sourcemedia': movie['info']['sourcemedia'] } if multiple: cd = 1 justAdded = [] finalDestination = None #clean up post-processing script ppScriptName = movie['info'].get('ppScriptName') ppDirName = self.config.get('Sabnzbd', 'ppDir') if ppScriptName: if ppDirName: ppPath = os.path.join(ppDirName, ppScriptName) try: os.remove(ppPath) log.info("Removed post-processing script: %s" % ppPath) except: log.info("Couldn't remove post-processing script: %s" % ppPath) else: log.info("Don't know where the post processing script is located, not removing %s" % ppScriptName) filenames = [] for file in movie['files']: log.info('Trying to find a home for: %s' % latinToAscii(file['filename'])) replacements['ext'] = file['ext'] if multiple: replacements['cd'] = ' cd' + str(cd) replacements['cdNr'] = ' ' + str(cd) replacements['original'] = file['filename'] folder = self.doReplace(folderNaming, replacements) filename = self.doReplace(fileNaming, replacements) filenames.append(filename) old = os.path.join(movie['path'], file['filename']) dest = os.path.join(destination, folder, filename) finalDestination = os.path.dirname(dest) if not os.path.isdir(finalDestination): try: log.info('Creating directory %s' % finalDestination) os.makedirs(finalDestination) shutil.copymode(destination, finalDestination) except OSError: log.error('Failed changing permissions %s' % finalDestination) # Remove old if better quality removed = self.removeOld(os.path.join(destination, folder), justAdded, movie['info']['size']) if not os.path.isfile(dest) and removed: log.info('Moving file "%s" to %s.' % (latinToAscii(old), dest)) if not _move(old, dest): break justAdded.append(dest) else: try: log.error('File %s already exists or not better.' % latinToAscii(filename)) path = movie['path'].split(os.sep) path.extend(['_EXISTS_' + path.pop()]) old = movie['path'] dest = os.sep.join(path) _move(old, dest) except: log.error('Could not extend path name.') break #get subtitle if any & move for type in movie['subtitles']: if len(movie['subtitles'][type]) > 0: log.info('Moving matching subtitle.') subtitle = movie['subtitles'][type].pop(0) replacements['original'] = subtitle['filename'] replacements['ext'] = subtitle['ext'] subDest = os.path.join(destination, folder, self.doReplace(fileNaming, replacements)) old = os.path.join(movie['path'], subtitle['filename']) if not _move(old, subDest): break justAdded.append(subDest) # Add to ignore list when removing stuff. # Add to renaming history log.debug('renamehistory start') h = RenameHistory() Db.add(h) try: h.movieQueue = movie['queue'].id except: h.movieQueue = 0 h.old = unicode(old.decode('utf-8')) h.new = unicode(dest.decode('utf-8')) Db.flush() log.debug('renamehistory end') if multiple: cd += 1 # Mark movie downloaded log.debug('queue downloaded start') if movie['queue'] and movie['queue'].id > 0: if movie['queue'].markComplete: movie['movie'].status = u'downloaded' movie['queue'].completed = True Db.flush() log.debug('queue downloaded end') return { 'directory': finalDestination, 'filenames': filenames }
def _search(self, movie, force = False): # Stop caching ffs! Db.expire_all() # Check release date and search for appropriate qualities preReleaseSearch = False dvdReleaseSearch = False now = int(time.time()) # Search all if ETA is unknow, but try update ETA for next time. checkETA = False if not movie.eta or force: checkETA = True preReleaseSearch = True dvdReleaseSearch = True else: # Prerelease 1 week before theaters if movie.eta.theater <= now + 604800: preReleaseSearch = True # dvdRelease 6 weeks before dvd release if movie.eta.dvd <= now + 3628800: preReleaseSearch = True dvdReleaseSearch = True # Dvd date is unknown but movie is in theater already if movie.eta.dvd == 0 and movie.eta.theater > now: checkETA = True dvdReleaseSearch = False # Force ETA check once a week or 3 weeks if ((movie.eta.dvd == 0 or movie.eta.theater == 0) and movie.eta.lastCheck < now - 604800) or (movie.eta.lastCheck < now - 1814400): checkETA = True # Minimal week interval for ETA check if checkETA: cherrypy.config.get('searchers').get('etaQueue').put({'id':movie.id}) for queue in movie.queue: # Movie already found, don't search further if queue.completed: log.debug('%s already completed for "%s". Not searching for any qualities below.' % (queue.qualityType, movie.name)) return True # only search for active and not completed, minimal 1 min since last search if queue.active and not queue.completed and not self.abort and not self.stop: #skip if no search is set if (not ((preReleaseSearch and queue.qualityType in Qualities.preReleases) or (dvdReleaseSearch and not queue.qualityType in Qualities.preReleases))) and not queue.lastCheck < (now - int(self.config.get('Intervals', 'search')) * 7200): continue highest = self.provider.find(movie, queue) #send highest to SABnzbd & mark as snatched if highest: #update what I found queue.name = latinToAscii(highest.name) queue.link = highest.detailUrl Db.flush() waitFor = queue.waitFor * (60 * 60 * 24) if queue.markComplete or (not queue.markComplete and highest.date + waitFor < time.time()): time.sleep(10) # Give these APIs air! if self.config.get('NZB', 'sendTo') == 'Sabnzbd' and highest.type == 'nzb': success = self.sabNzbd.send(highest, movie.imdb) else: success = self.blackHole(highest) else: success = False log.info('Found %s but waiting for %d hours.' % (highest.name, ((highest.date + waitFor) - time.time()) / (60 * 60))) # Set status if success: movie.status = u'snatched' if queue.markComplete else u'waiting' movie.dateChanged = datetime.datetime.now() queue.lastCheck = now queue.completed = True Db.flush() # Add to history h = History() h.movie = movie.id h.value = str(highest.id) + '-' + str(highest.size) h.status = u'snatched' Db.add(h) Db.flush() return True queue.lastCheck = now Db.flush() return False