def forget(manager, options): name = options.series_name if options.episode_id: # remove by id identifier = options.episode_id try: forget_series_episode(name, identifier) console('Removed episode `%s` from series `%s`.' % (identifier, name.capitalize())) except ValueError: # Try upper casing identifier if we fail at first try: forget_series_episode(name, identifier.upper()) console('Removed episode `%s` from series `%s`.' % (identifier, name.capitalize())) except ValueError as e: console(e.message) else: # remove whole series try: forget_series(name) console('Removed series `%s` from database.' % name.capitalize()) except ValueError as e: console(e.message) manager.config_changed()
def bootstrap(self, session, config): """bootstrap the plugin configuration and update db with cached chat_ids""" console('{0} - bootstrapping...'.format(_PLUGIN_NAME)) chat_ids = self._real_init(session, config) found_usernames = [x.username for x in chat_ids if x.username] found_fullnames = [(x.firstname, x.surname) for x in chat_ids if x.firstname] found_grps = [x.group for x in chat_ids if x.group] missing_usernames = [x for x in self._usernames if x not in found_usernames] missing_fullnames = [x for x in self._fullnames if x not in found_fullnames] missing_grps = [x for x in self._groups if x not in found_grps] if missing_usernames or missing_fullnames or missing_grps: for i in missing_usernames: console('ERR: could not find chat_id for username: {0}'.format(i)) for i in missing_fullnames: console('ERR: could not find chat_id for fullname: {0} {1}'.format(*i)) for i in missing_grps: console('ERR: could not find chat_id for group: {0}'.format(i)) res = False else: console('{0} - bootstrap was successful'.format(_PLUGIN_NAME)) res = True return res
def on_process_start(self, task): if task.manager.options.series_forget: task.manager.disable_tasks() name = unicode(task.manager.options.series_forget[0]) if len(task.manager.options.series_forget) > 1: # remove by id identifier = task.manager.options.series_forget[1] if identifier and name: try: forget_series_episode(name, identifier) console('Removed episode `%s` from series `%s`.' % (identifier, name.capitalize())) except ValueError: # Try upper casing identifier if we fail at first try: forget_series_episode(name, identifier.upper()) console('Removed episode `%s` from series `%s`.' % (identifier, name.capitalize())) except ValueError as e: console(e.message) else: # remove whole series try: forget_series(name) console('Removed series `%s` from database.' % name.capitalize()) except ValueError as e: console(e.message) task.manager.config_changed()
def reset_plugin(manager): if not manager.options.reset_plugin: return manager.disable_tasks() plugin = manager.options.reset_plugin if plugin == '__list__': console('%-20s Ver Tables' % 'Name') console('-' * 79) for k, v in sorted(plugin_schemas.iteritems()): tables = '' line_len = 0 for name in v['tables']: if line_len + len(name) + 2 >= 53: tables += '\n' tables += ' ' * 25 line_len = len(name) + 2 else: line_len += len(name) + 2 tables += name + ', ' tables = tables.rstrip(', ') console('%-20s %s %s' % (k, v['version'], tables)) else: try: reset_schema(plugin) console('The database for `%s` has been reset.' % plugin) except ValueError as e: console('Unable to reset %s: %s' % (plugin, e.message))
def on_process_start(self, task): """Handle --movie-queue management""" if not getattr(task.manager.options, 'movie_queue', False): return task.manager.disable_tasks() options = task.manager.options.movie_queue if options['action'] == 'list': self.queue_list(task.session) return # If the action was to do more than just list the series, make sure all entries are processed again next run. task.manager.config_changed() if options['action'] == 'downloaded': self.queue_list(task.session, downloaded=True) return if options['action'] == 'clear': self.clear(task.session) return if options['action'] == 'del': try: title = queue_del(options['what']) except QueueError, e: console(e.message) else: console('Removed %s from queue' % title) return
def on_process_start(self, feed): """Handle --movie-queue management""" if not getattr(feed.manager.options, 'movie_queue', False): return feed.manager.disable_feeds() options = feed.manager.options.movie_queue if options['action'] == 'list': self.queue_list(feed.session) return if options['action'] == 'downloaded': self.queue_list(feed.session, downloaded=True) return if options['action'] == 'clear': self.clear(feed.session) return if options['action'] == 'del': try: title = queue_del(options['what']) except QueueError, e: console(e.message) else: console('Removed %s from queue' % title) return
def bootstrap(self, session, config): """bootstrap the plugin configuration and update db with cached chat_ids""" console('{0} - bootstrapping...'.format(_PLUGIN_NAME)) chat_ids = self._real_init(session, config) found_usernames = [x.username for x in chat_ids if x.username] found_fullnames = [(x.firstname, x.surname) for x in chat_ids if x.firstname] found_grps = [x.group for x in chat_ids if x.group] missing_usernames = [ x for x in self._usernames if x not in found_usernames ] missing_fullnames = [ x for x in self._fullnames if x not in found_fullnames ] missing_grps = [x for x in self._groups if x not in found_grps] if missing_usernames or missing_fullnames or missing_grps: for i in missing_usernames: console( 'ERR: could not find chat_id for username: {0}'.format(i)) for i in missing_fullnames: console( 'ERR: could not find chat_id for fullname: {0} {1}'.format( *i)) for i in missing_grps: console('ERR: could not find chat_id for group: {0}'.format(i)) res = False else: console('{0} - bootstrap was successful'.format(_PLUGIN_NAME)) res = True return res
def parse_what(self, what): """Given an imdb id or movie title, looks up from imdb and returns a dict with imdb_id and title keys""" imdb_id = extract_id(what) title = what if imdb_id: # Given an imdb id, find title parser = ImdbParser() try: parser.parse('http://www.imdb.com/title/%s' % imdb_id) except Exception: raise QueueError('Error parsing info from imdb for %s' % imdb_id) if parser.name: title = parser.name else: # Given a title, try to do imdb search for id console('Searching imdb for %s' % what) search = ImdbSearch() result = search.smart_match(what) if not result: raise QueueError( 'ERROR: Unable to find any such movie from imdb, use imdb url instead.' ) imdb_id = extract_id(result['url']) title = result['name'] self.options['imdb_id'] = imdb_id self.options['title'] = title return {'title': title, 'imdb_id': imdb_id}
def vacuum(): console("Running VACUUM on sqlite database, this could take a while.") session = Session() session.execute("VACUUM") session.commit() session.close() console("VACUUM complete.")
def on_process_start(self, feed): """Handle --movie-queue management""" if not getattr(feed.manager.options, "movie_queue", False): return feed.manager.disable_feeds() options = feed.manager.options.movie_queue if options["action"] == "list": self.queue_list(feed.session) return if options["action"] == "downloaded": self.queue_list(feed.session, downloaded=True) return if options["action"] == "clear": self.clear(feed.session) return if options["action"] == "del": try: title = queue_del(options["what"]) except QueueError, e: console(e.message) else: console("Removed %s from queue" % title) return
def clear_backlog(manager): if not manager.options.clear_backlog: return manager.disable_tasks() session = Session() num = session.query(BacklogEntry).delete() session.close() console('%s entries cleared from backlog.' % num)
def vacuum(): console('Running VACUUM on sqlite database, this could take a while.') session = Session() try: session.execute('VACUUM') session.commit() finally: session.close() console('VACUUM complete.')
def cli_perf_test(manager, options): if options.test_name not in TESTS: console('Unknown performance test %s' % options.test_name) return session = Session() try: if options.test_name == 'imdb_query': imdb_query(session) finally: session.close()
def seen_forget(manager, options): forget_name = options.forget_value if is_imdb_url(forget_name): imdb_id = extract_id(forget_name) if imdb_id: forget_name = imdb_id count, fcount = forget(forget_name) console('Removed %s titles (%s fields)' % (count, fcount)) manager.config_changed()
def clear_failed(manager): session = Session() try: results = session.query(FailedEntry).delete() console('Cleared %i items.' % results) session.commit() if results: manager.config_changed() finally: session.close()
def reset_plugin(manager): if not manager.options.reset_plugin: return manager.disable_tasks() plugin = manager.options.reset_plugin try: reset_schema(plugin) console('The database for `%s` has been reset.' % plugin) except ValueError as e: console('Unable to reset %s: %s' % (plugin, e.message))
def test_msg(self, session, config): """send test message to configured recipients""" console('{0} loading chat_ids...'.format(_PLUGIN_NAME)) chat_ids = self._real_init(session, config) console('{0} sending test message(s)...'.format(_PLUGIN_NAME)) for chat_id in (x.id for x in chat_ids): self._bot.sendMessage(chat_id=chat_id, text='test message from flexget') return True
def clear_rejected(manager): session = Session() try: results = session.query(RememberEntry).delete() console("Cleared %i items." % results) session.commit() if results: manager.config_changed() finally: session.close()
def clear_rejected(manager): session = Session() try: results = session.query(RememberEntry).delete() console('Cleared %i items.' % results) session.commit() if results: manager.config_changed() finally: session.close()
def reset_plugin(manager): if not manager.options.reset_plugin: return manager.disable_tasks() plugin = manager.options.reset_plugin try: reset_schema(plugin) console('The database for `%s` has been reset.' % plugin) except ValueError, e: console('Unable to reset %s: %s' % (plugin, e.message))
def clear(): """Deletes waiting movies from queue""" items = queue_get(downloaded=False) console('Removing the following movies from movie queue:') console('-' * 79) for item in items: console(item.title) queue_del(title=item.title) if not items: console('No results') console('-' * 79)
def clear_failed(self): """Clears list of failed entries""" session = Session() try: results = session.query(FailedEntry).all() for row in results: session.delete(row) console('Cleared %i items.' % len(results)) session.commit() finally: session.close()
def list_failed(): session = Session() try: results = session.query(FailedEntry).all() if not results: console('No failed entries recorded') for entry in results: console('%16s - %s - %s times - %s' % (entry.tof.strftime('%Y-%m-%d %H:%M'), entry.title, entry.count, entry.reason)) finally: session.close()
def print_failed(self): """Parameter --failed""" failed = Session() try: results = failed.query(FailedEntry).all() if not results: console('No failed entries recorded') for entry in results: console('%16s - %s - %s times' % (entry.tof.strftime('%Y-%m-%d %H:%M'), entry.title, entry.count)) finally: failed.close()
def seen_add(options): seen_name = options.add_value if is_imdb_url(seen_name): imdb_id = extract_id(seen_name) if imdb_id: seen_name = imdb_id with Session() as session: se = SeenEntry(seen_name, 'cli_seen') sf = SeenField('cli_seen', seen_name) se.fields.append(sf) session.add(se) console('Added %s as seen. This will affect all tasks.' % seen_name)
def archive_inject(option, opt, value, parser): """Option parser function""" if not parser.rargs: console('Usage: --archive-inject ID [IMMORTAL]') import sys sys.exit(1) parser.values.archive_inject_id = parser.rargs[0] if len(parser.rargs) >= 2: from flexget.utils.tools import str_to_boolean parser.values.archive_inject_immortal = str_to_boolean(parser.rargs[1])
def print_failed(self): """Parameter --failed""" failed = Session() try: results = failed.query(FailedEntry).all() if not results: console('No failed entries recorded') for entry in results: console('%16s - %s - %s times - %s' % (entry.tof.strftime('%Y-%m-%d %H:%M'), entry.title, entry.count, entry.reason)) finally: failed.close()
def clear_failed(self): """ Clears list of failed entries :return: The number of entries cleared. """ session = Session() try: results = session.query(FailedEntry).delete() console('Cleared %i items.' % results) session.commit() return results finally: session.close()
def __call__(self, parser, namespace, values, option_string=None): if self.version == '{git}': # Attempt to get version from git version = '' try: p = subprocess.Popen('git describe', stdout=subprocess.PIPE) version = p.stdout.read() except Exception: pass if version.startswith('1.0'): self.version += version else: console('Unable to get current version from git.') super(VersionAction, self).__call__(parser, namespace, values, option_string)
def search(self, search_term, tags=None): def print_ae(ae): diff = datetime.now() - ae.added console('ID: %-6s | Title: %s\nAdded: %s (%d days ago)\nURL: %s' % (ae.id, ae.title, ae.added, diff.days, ae.url)) source_names = ', '.join([s.name for s in ae.sources]) tag_names = ', '.join([t.name for t in ae.tags]) console('Source(s): %s | Tag(s): %s' % (source_names or 'N/A', tag_names or 'N/A')) if ae.description: console('Description: %s' % strip_html(ae.description)) console('---') session = Session() try: console('Searching: %s' % search_term) if tags: console('Tags: %s' % ', '.join(tags)) console('Please wait ...') console('') for ae in search(session, search_term, tags): print_ae(ae) finally: session.close()
def on_exec_stopped(manager): if not manager.options.execute.mem_usage: return console('Calculating memory usage:') console(heapy.heap()) console('-' * 79) console(heapy.heap().get_rp(40))
def clear(self, session): """Delete movie queue""" items = queue_get(session=session, downloaded=False) console('Removing the following movies from movie queue:') console('-' * 79) for item in items: console(item.title) queue_del(item.imdb_id) if not items: console('No results') console('-' * 79)
def do_cli(manager, options): if options.action == 'clear': num = clear_entries(options.task) console('%s entries cleared from backlog.' % num) else: cols = '{:<65.64}{:<15.15}' console(cols.format('Title', 'Task')) console('-' * 80) with Session() as session: entries = get_entries(options.task, session=session) for entry in entries: console(cols.format(entry.title, entry.task)) if not entries: console('No items')
def on_process_start(self, task): if task.manager.options.series_forget: task.manager.disable_tasks() name = unicode(task.manager.options.series_forget[0]) if len(task.manager.options.series_forget) > 1: # remove by id identifier = task.manager.options.series_forget[1].upper() if identifier and name: try: forget_series_episode(name, identifier) console('Removed episode `%s` from series `%s`.' % (identifier, name.capitalize())) except ValueError as e: console(e.message) else: # remove whole series try: forget_series(name) console('Removed series `%s` from database.' % name.capitalize()) except ValueError as e: console(e.message) task.manager.config_changed()
def clear(self, session): """Delete movie queue""" items = queue_get(session=session, downloaded=False) console("Removing the following movies from movie queue:") console("-" * 79) for item in items: console(item.title) queue_del(item.imdb_id) if not items: console("No results") console("-" * 79)
def start(self): """ Starting point when executing from commandline, dispatch execution to correct destination. If there is a FlexGet process with an ipc server already running, the command will be sent there for execution and results will be streamed back. If not, this will attempt to obtain a lock, initialize the manager, and run the command here. """ # When we are in test mode, we use a different lock file and db if self.options.test: self.lockfile = os.path.join(self.config_base, '.test-%s-lock' % self.config_name) # If another process is started, send the execution to the running process ipc_info = self.check_ipc_info() if ipc_info: console( 'There is a FlexGet process already running for this config, sending execution there.' ) log.debug('Sending command to running FlexGet process: %s' % self.args) try: client = IPCClient(ipc_info['port'], ipc_info['password']) except ValueError as e: log.error(e) else: try: client.handle_cli(self.args) except KeyboardInterrupt: log.error( 'Disconnecting from daemon due to ctrl-c. Executions will still continue in the ' 'background.') except EOFError: log.error('Connection from daemon was severed.') return if self.options.test: log.info('Test mode, creating a copy from database ...') db_test_filename = os.path.join( self.config_base, 'test-%s.sqlite' % self.config_name) if os.path.exists(self.db_filename): shutil.copy(self.db_filename, db_test_filename) log.info('Test database created') self.db_filename = db_test_filename # No running process, we start our own to handle command with self.acquire_lock(): self.initialize() self.handle_cli() self._shutdown()
def do_cli(manager, options): import win32file import win32serviceutil if hasattr(sys, 'real_prefix'): # We are in a virtualenv, there is some special setup if not os.path.exists(os.path.join(sys.prefix, 'python.exe')): console('Creating a hard link to virtualenv python.exe in root of virtualenv') win32file.CreateHardLink(os.path.join(sys.prefix, 'python.exe'), os.path.join(sys.prefix, 'Scripts', 'python.exe')) argv = options.args if options.help: argv = [] # Hack sys.argv a bit so that we get a better usage message sys.argv[0] = 'flexget service' win32serviceutil.HandleCommandLine(AppServerSvc, argv=['flexget service'] + argv)
def print_ae(ae): diff = datetime.now() - ae.added console('ID: %-6s | Title: %s\nAdded: %s (%d days ago)\nURL: %s' %\ (ae.id, ae.title, ae.added, diff.days, ae.url)) source_names = ', '.join([s.name for s in ae.sources]) tag_names = ', '.join([t.name for t in ae.tags]) console('Source(s): %s | Tag(s): %s' % (source_names or 'N/A', tag_names or 'N/A')) if ae.description: console('Description: %s' % strip_html(ae.description)) console('---')
def print_ae(ae): diff = datetime.now() - ae.added console('ID: %-6s | Title: %s\nAdded: %s (%d days ago)\nURL: %s' % (ae.id, ae.title, ae.added, diff.days, ae.url)) source_names = ', '.join([s.name for s in ae.sources]) tag_names = ', '.join([t.name for t in ae.tags]) console('Source(s): %s | Tag(s): %s' % (source_names or 'N/A', tag_names or 'N/A')) if ae.description: console('Description: %s' % strip_html(ae.description)) console('---')
def do_cli(manager, options): import win32file import win32serviceutil if hasattr(sys, "real_prefix"): # We are in a virtualenv, there is some special setup if not os.path.exists(os.path.join(sys.prefix, "python.exe")): console("Creating a hard link to virtualenv python.exe in root of virtualenv") win32file.CreateHardLink( os.path.join(sys.prefix, "python.exe"), os.path.join(sys.prefix, "Scripts", "python.exe") ) argv = options.args if options.help: argv = [] # Hack sys.argv a bit so that we get a better usage message sys.argv[0] = "flexget service" win32serviceutil.HandleCommandLine(AppServerSvc, argv=["flexget service"] + argv)
def on_process_start(self, feed): """ Handle IMDb queue management """ if not getattr(feed.manager.options, 'movie_queue', False): return feed.manager.disable_feeds() options = feed.manager.options.movie_queue if options['action'] == 'list': self.queue_list() return # all actions except list require imdb_url to work # Generate imdb_id and movie title from movie name, or imdb_url try: what = self.parse_what(options['what']) except QueueError, e: console(e.message)
def __call__(self, parser, namespace, values, option_string=None): # Print the version number console('%s' % self.version) # Check for latest version from server try: page = requests.get('http://download.flexget.com/latestversion') except requests.RequestException: console( 'Error getting latest version number from download.flexget.com' ) else: ver = page.text.strip() if self.version == ver: console('You are on the latest release.') else: console('Latest release: %s' % ver) parser.exit()
def seen_search(options): session = Session() try: search_term = '%' + options.search_term + '%' seen_entries = (session.query(SeenEntry).join(SeenField).filter( SeenField.value.like(search_term)).order_by(SeenField.added).all()) for se in seen_entries: console('ID: %s Name: %s Task: %s Added: %s' % (se.id, se.title, se.task, se.added.strftime('%c'))) for sf in se.fields: console(' %s: %s' % (sf.field, sf.value)) console('') if not seen_entries: console('No results') finally: session.close()
def list_rejected(): session = Session() try: results = session.query(RememberEntry).all() if not results: console('No rejected entries recorded by remember_rejected') else: console('Rejections remembered by remember_rejected:') for entry in results: console('%s from %s by %s because %s' % (entry.title, entry.task.name, entry.rejected_by, entry.reason)) finally: session.close()
def on_task_output(self, task, config): if not config and not task.options.dump_entries: return eval_lazy = task.options.dump_entries == 'eval' trace = task.options.dump_entries == 'trace' undecided = [entry for entry in task.all_entries if entry.undecided] if undecided: console('-- Undecided: --------------------------') dump(undecided, task.options.debug, eval_lazy, trace) if task.accepted: console('-- Accepted: ---------------------------') dump(task.accepted, task.options.debug, eval_lazy, trace) if task.rejected: console('-- Rejected: ---------------------------') dump(task.rejected, task.options.debug, eval_lazy, trace)