def plugins_summary(manager, options): if options.table_type == 'porcelain': disable_all_colors() header = ['Keyword', 'Phases', 'Flags'] table_data = [header] for plugin in sorted(get_plugins(phase=options.phase, group=options.group)): if options.builtins and not plugin.builtin: continue flags = [] if plugin.instance.__doc__: flags.append('doc') if plugin.builtin: flags.append('builtin') if plugin.debug: if not options.debug: continue flags.append('developers') handlers = plugin.phase_handlers roles = [] for phase in handlers: priority = handlers[phase].priority roles.append('{0}({1})'.format(phase, priority)) name = colorize('green', plugin.name) if 'builtin' in flags else plugin.name table_data.append([name, ', '.join(roles), ', '.join(flags)]) try: table = TerminalTable(options.table_type, table_data, wrap_columns=[1, 2]) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return console(colorize('green', ' Built-in plugins'))
def action_status(options, irc_manager): connection = options.irc_connection try: status = irc_manager.status(connection) except ValueError as e: console('ERROR: %s' % e.args[0]) return header = ['Name', 'Alive', 'Channels', 'Server'] table_data = [header] for connection in status: for name, info in connection.items(): alive = colorize('green', 'Yes') if info['alive'] else colorize('red', 'No') channels = [] for channel in info['channels']: for channel_name, channel_status in channel.items(): channels.append(channel_name) if channel_status == IRCChannelStatus.CONNECTED: channels[-1] = colorize('green', '* ' + channels[-1]) table_data.append( [name, alive, ', '.join(channels), '%s:%s' % (info['server'], info['port'])] ) try: table = TerminalTable(options.table_type, table_data) console(table.output) console(colorize('green', ' * Connected channel')) except TerminalTableError as e: console('ERROR: %s' % e)
def plugins_summary(manager, options): if options.table_type == 'porcelain': disable_colors() header = ['Keyword', 'Interfaces', 'Phases', 'Flags'] table = TerminalTable(*header, table_type=options.table_type) for plugin in sorted( get_plugins(phase=options.phase, interface=options.interface)): if options.builtins and not plugin.builtin: continue flags = [] if plugin.instance.__doc__: flags.append('doc') if plugin.builtin: flags.append('builtin') if plugin.debug: if not options.debug: continue flags.append('developers') handlers = plugin.phase_handlers roles = [] for phase in handlers: priority = handlers[phase].priority roles.append('{0}({1})'.format(phase, priority)) name = colorize('green', plugin.name) if 'builtin' in flags else plugin.name table.add_row(name, ', '.join(plugin.interfaces), ', '.join(roles), ', '.join(flags)) table.caption = colorize('green', ' Built-in plugins') table.caption_justify = 'left' console(table)
def action_status(options, irc_manager): connection = options.irc_connection try: status = irc_manager.status(connection) except ValueError as e: console('ERROR: %s' % e.args[0]) return header = ['Name', 'Alive', 'Channels', 'Server'] table_data = [] for connection in status: for name, info in connection.items(): alive = colorize('green', 'Yes') if info['alive'] else colorize( 'red', 'No') channels = [] for channel in info['channels']: for channel_name, channel_status in channel.items(): channels.append(channel_name) if channel_status == IRCChannelStatus.CONNECTED: channels[-1] = colorize('green', '* ' + channels[-1]) table_data.append([ name, alive, ', '.join(channels), '%s:%s' % (info['server'], info['port']) ]) table = TerminalTable(*header, table_type=options.table_type) for row in table_data: table.add_row(*row) console(table) console(colorize('green', ' * Connected channel'))
def do_cli_summary(manager, options): header = [ 'Task', 'Last execution', 'Last success', 'Produced', 'Accepted', 'Rejected', 'Failed', 'Duration', ] table_data = [header] with Session() as session: for task in session.query(db.StatusTask).all(): ok = (session.query(db.TaskExecution).filter( db.TaskExecution.task_id == task.id).filter( db.TaskExecution.succeeded == True).filter( db.TaskExecution.produced > 0).order_by( db.TaskExecution.start.desc()).first()) if ok is None: duration = None last_success = '-' else: duration = ok.end - ok.start last_success = ok.start.strftime('%Y-%m-%d %H:%M') age = datetime.datetime.utcnow() - ok.start if age > timedelta(days=7): last_success = colorize('red', last_success) elif age < timedelta(minutes=10): last_success = colorize('green', last_success) # Fix weird issue that a task registers StatusTask but without an execution. GH #2022 last_exec = (task.last_execution_time.strftime('%Y-%m-%d %H:%M') if task.last_execution_time else '-') table_data.append([ task.name, last_exec, last_success, ok.produced if ok is not None else '-', ok.accepted if ok is not None else '-', ok.rejected if ok is not None else '-', ok.failed if ok is not None else '-', '%1.fs' % duration.total_seconds() if duration is not None else '-', ]) table = TerminalTable(options.table_type, table_data) try: console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def pending_list_list(options): """List pending list entries""" with Session() as session: try: pending_list = db.get_list_by_exact_name(options.list_name, session=session) except NoResultFound: console('Could not find pending list with name `{}`'.format( options.list_name)) return header = ['#', 'Title', '# of fields', 'Approved'] table_data = [header] for entry in db.get_entries_by_list_id(pending_list.id, order_by='added', descending=True, session=session): approved = colorize( 'green', entry.approved) if entry.approved else entry.approved table_data.append( [entry.id, entry.title, len(entry.entry), approved]) table = TerminalTable(options.table_type, table_data) try: console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def list_entries(options): """List pending entries""" approved = options.approved task_name = options.task_name with Session() as session: entries = db.list_pending_entries(session=session, task_name=task_name, approved=approved) header = ['#', 'Task Name', 'Title', 'URL', 'Approved', 'Added'] table_data = [header] for entry in entries: table_data.append([ entry.id, entry.task_name, entry.title, entry.url, colorize('green', 'Yes') if entry.approved else 'No', entry.added.strftime("%c"), ]) try: table = TerminalTable(options.table_type, table_data, wrap_columns=[1, 2, 3], drop_columns=[5, 1, 3]) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def manage_entries(options, selection, approved): """Manage pending entries""" approved_text = 'approved' if approved else 'pending' with Session() as session: if selection == 'all': entries = db.list_pending_entries(session=session, approved=not approved) else: try: entry = db.get_entry_by_id(session, selection) if entry.approved is approved: console( colorize('red', 'ERROR: ') + 'Entry with ID %s is already %s' % (entry.id, approved_text)) sys.exit(1) except NoResultFound: console('Pending entry with ID %s does not exist' % selection) sys.exit(1) else: entries = [entry] if not entries: console('All entries are already %s' % approved_text) return for entry in entries: if entry.approved is not approved: console('Setting pending entry with ID %s status to %s' % (entry.id, approved_text)) entry.approved = approved
def manage_entries(options, selection, approved): """Manage pending entries""" approved_text = 'approved' if approved else 'pending' with Session() as session: if selection == 'all': entries = db.list_pending_entries(session=session, approved=not approved) else: try: entry = db.get_entry_by_id(session, selection) if entry.approved is approved: console( colorize('red', 'ERROR: ') + 'Entry with ID %s is already %s' % (entry.id, approved_text) ) sys.exit(1) except NoResultFound: console('Pending entry with ID %s does not exist' % selection) sys.exit(1) else: entries = [entry] if not entries: console('All entries are already %s' % approved_text) return for entry in entries: if entry.approved is not approved: console( 'Setting pending entry with ID %s status to %s' % (entry.id, approved_text) ) entry.approved = approved
def list_entries(options): """List pending entries""" approved = options.approved task_name = options.task_name with Session() as session: entries = db.list_pending_entries(session=session, task_name=task_name, approved=approved) header = ['#', 'Task Name', 'Title', 'URL', 'Approved', 'Added'] table_data = [header] for entry in entries: table_data.append( [ entry.id, entry.task_name, entry.title, entry.url, colorize('green', 'Yes') if entry.approved else 'No', entry.added.strftime("%c"), ] ) try: table = TerminalTable( options.table_type, table_data, wrap_columns=[1, 2, 3], drop_columns=[5, 1, 3] ) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def do_cli_task(manager, options): header = [ 'Start', 'Duration', 'Produced', 'Accepted', 'Rejected', 'Failed', 'Abort Reason' ] table_data = [header] with Session() as session: try: task = session.query(db.StatusTask).filter( db.StatusTask.name == options.task).one() except NoResultFound: console( 'Task name `%s` does not exists or does not have any records' % options.task) return else: query = task.executions.order_by(desc( db.TaskExecution.start))[:options.limit] for ex in reversed(query): start = ex.start.strftime('%Y-%m-%d %H:%M') start = colorize('green', start) if ex.succeeded else colorize( 'red', start) if ex.end is not None and ex.start is not None: delta = ex.end - ex.start duration = '%1.fs' % delta.total_seconds() else: duration = '?' table_data.append([ start, duration, ex.produced, ex.accepted, ex.rejected, ex.failed, ex.abort_reason if ex.abort_reason is not None else '', ]) try: table = TerminalTable(options.table_type, table_data) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def do_cli_summary(manager, options): header = ['Task', 'Last execution', 'Last success', 'Produced', 'Accepted', 'Rejected', 'Failed', 'Duration'] table_data = [header] with Session() as session: for task in session.query(StatusTask).all(): ok = session.query(TaskExecution). \ filter(TaskExecution.task_id == task.id). \ filter(TaskExecution.succeeded == True). \ filter(TaskExecution.produced > 0). \ order_by(TaskExecution.start.desc()).first() if ok is None: duration = None last_success = '-' else: duration = ok.end - ok.start last_success = ok.start.strftime('%Y-%m-%d %H:%M') age = datetime.datetime.utcnow() - ok.start if age > timedelta(days=7): last_success = colorize('red', last_success) elif age < timedelta(minutes=10): last_success = colorize('green', last_success) table_data.append([ task.name, task.last_execution_time.strftime('%Y-%m-%d %H:%M'), last_success, ok.produced if ok is not None else '-', ok.accepted if ok is not None else '-', ok.rejected if ok is not None else '-', ok.failed if ok is not None else '-', '%1.fs' % duration.total_seconds() if duration is not None else '-', ] ) table = TerminalTable(options.table_type, table_data) try: console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def do_cli_task(manager, options): header = ['Start', 'Duration', 'Produced', 'Accepted', 'Rejected', 'Failed', 'Abort Reason'] table_data = [header] with Session() as session: try: task = session.query(StatusTask).filter(StatusTask.name == options.task).one() except NoResultFound: console('Task name `%s` does not exists or does not have any records' % options.task) return else: query = task.executions.order_by(desc(TaskExecution.start))[:options.limit] for ex in reversed(query): start = ex.start.strftime('%Y-%m-%d %H:%M') start = colorize('green', start) if ex.succeeded else colorize('red', start) if ex.end is not None and ex.start is not None: delta = ex.end - ex.start duration = '%1.fs' % delta.total_seconds() else: duration = '?' table_data.append( [ start, duration, ex.produced, ex.accepted, ex.rejected, ex.failed, ex.abort_reason if ex.abort_reason is not None else '' ] ) try: table = TerminalTable(options.table_type, table_data) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def pending_list_list(options): """List pending list entries""" with Session() as session: try: pending_list = get_list_by_exact_name(options.list_name, session=session) except NoResultFound: console('Could not find pending list with name `{}`'.format(options.list_name)) return header = ['#', 'Title', '# of fields', 'Approved'] table_data = [header] for entry in get_entries_by_list_id(pending_list.id, order_by='added', descending=True, session=session): approved = colorize('green', entry.approved) if entry.approved else entry.approved table_data.append([entry.id, entry.title, len(entry.entry), approved]) table = TerminalTable(options.table_type, table_data) try: console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e))
def list_entries(options): """List pending entries""" approved = options.approved task_name = options.task_name with Session() as session: entries = db.list_pending_entries(session=session, task_name=task_name, approved=approved) header = ['#', 'Task Name', 'Title', 'URL', 'Approved', 'Added'] table = TerminalTable(*header, table_type=options.table_type) for entry in entries: table.add_row( str(entry.id), entry.task_name, entry.title, entry.url, colorize('green', 'Yes') if entry.approved else 'No', entry.added.strftime("%c"), ) console(table)
def pending_list_list(options): """List pending list entries""" with Session() as session: try: pending_list = db.get_list_by_exact_name(options.list_name, session=session) except NoResultFound: console('Could not find pending list with name `{}`'.format( options.list_name)) return header = ['#', 'Title', '# of fields', 'Approved'] table = TerminalTable(*header, table_type=options.table_type) for entry in db.get_entries_by_list_id(pending_list.id, order_by='added', descending=True, session=session): approved = colorize( 'green', entry.approved) if entry.approved else entry.approved table.add_row(str(entry.id), entry.title, str(len(entry.entry)), approved) console(table)
def display_summary(options): """ Display series summary. :param options: argparse options from the CLI """ porcelain = options.table_type == 'porcelain' configured = options.configured or os.environ.get(ENV_LIST_CONFIGURED, 'configured') premieres = True if (os.environ.get(ENV_LIST_PREMIERES) == 'yes' or options.premieres) else False sort_by = options.sort_by or os.environ.get(ENV_LIST_SORTBY_FIELD, 'name') if options.order is not None: descending = True if options.order == 'desc' else False else: descending = True if os.environ.get(ENV_LIST_SORTBY_ORDER) == 'desc' else False with Session() as session: kwargs = {'configured': configured, 'premieres': premieres, 'session': session, 'sort_by': sort_by, 'descending': descending} if sort_by == 'name': kwargs['sort_by'] = 'show_name' else: kwargs['sort_by'] = 'last_download_date' query = get_series_summary(**kwargs) header = ['Name', 'Begin', 'Last Encountered', 'Age', 'Downloaded', 'Identified By'] for index, value in enumerate(header): if value.lower() == options.sort_by: header[index] = colorize(SORT_COLUMN_COLOR, value) table_data = [header] for series in query: name_column = series.name behind = (0,) begin = series.begin.identifier if series.begin else '-' latest_release = '-' age_col = '-' episode_id = '-' latest = get_latest_release(series) identifier_type = series.identified_by if identifier_type == 'auto': identifier_type = colorize('yellow', 'auto') if latest: behind = new_entities_after(latest) latest_release = get_latest_status(latest) # colorize age age_col = latest.age if latest.age_timedelta is not None: if latest.age_timedelta < timedelta(days=1): age_col = colorize(NEW_EP_COLOR, latest.age) elif latest.age_timedelta < timedelta(days=3): age_col = colorize(FRESH_EP_COLOR, latest.age) elif latest.age_timedelta > timedelta(days=400): age_col = colorize(OLD_EP_COLOR, latest.age) episode_id = latest.identifier if not porcelain: if behind[0] > 0: name_column += colorize(BEHIND_EP_COLOR, ' {} {} behind'.format(behind[0], behind[1])) table_data.append([name_column, begin, episode_id, age_col, latest_release, identifier_type]) try: table = TerminalTable(options.table_type, table_data, wrap_columns=[3], drop_columns=[4, 3, 2]) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return if not porcelain: if not query.count(): console('Use `flexget series list all` to view all known series.') else: console('Use `flexget series show NAME` to get detailed information.')
def display_details(options): """Display detailed series information, ie. series show NAME""" name = options.series_name sort_by = options.sort_by or os.environ.get(ENV_SHOW_SORTBY_FIELD, 'age') if options.order is not None: reverse = True if options.order == 'desc' else False else: reverse = True if os.environ.get(ENV_SHOW_SORTBY_ORDER) == 'desc' else False with Session() as session: name = normalize_series_name(name) # Sort by length of name, so that partial matches always show shortest matching title matches = shows_by_name(name, session=session) if not matches: console(colorize(ERROR_COLOR, 'ERROR: Unknown series `%s`' % name)) return # Pick the best matching series series = matches[0] table_title = colorize('white', series.name) if len(matches) > 1: warning = (colorize('red', ' WARNING: ') + 'Multiple series match to `{}`.\n ' 'Be more specific to see the results of other matches:\n\n' ' {}'.format(name, ', '.join(s.name for s in matches[1:]))) if not options.table_type == 'porcelain': console(warning) header = ['Identifier', 'Last seen', 'Release titles', 'Release Quality', 'Proper'] table_data = [header] entities = get_all_entities(series, session=session, sort_by=sort_by, reverse=reverse) for entity in entities: if not entity.releases: continue if entity.identifier is None: identifier = colorize(ERROR_COLOR, 'MISSING') age = '' else: identifier = entity.identifier age = entity.age entity_data = [identifier, age] release_titles = [] release_qualities = [] release_propers = [] for release in entity.releases: title = release.title quality = release.quality.name if not release.downloaded: title = colorize(UNDOWNLOADED_RELEASE_COLOR, title) quality = quality else: title += ' *' title = colorize(DOWNLOADED_RELEASE_COLOR, title) quality = quality release_titles.append(title) release_qualities.append(quality) release_propers.append('Yes' if release.proper_count > 0 else '') entity_data.append('\n'.join(release_titles)) entity_data.append('\n'.join(release_qualities)) entity_data.append('\n'.join(release_propers)) table_data.append(entity_data) footer = ' %s \n' % (colorize(DOWNLOADED_RELEASE_COLOR, '* Downloaded')) if not series.identified_by: footer += ('\n Series plugin is still learning which episode numbering mode is \n' ' correct for this series (identified_by: auto).\n' ' Few duplicate downloads can happen with different numbering schemes\n' ' during this time.') else: footer += '\n `%s` uses `%s` mode to identify episode numbering.' % (series.name, series.identified_by) begin_text = 'option' if series.begin: footer += ' \n Begin for `%s` is set to `%s`.' % (series.name, series.begin.identifier) begin_text = 'and `begin` options' footer += ' \n See `identified_by` %s for more information.' % begin_text try: table = TerminalTable(options.table_type, table_data, table_title, drop_columns=[4, 3, 1]) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return if not options.table_type == 'porcelain': console(footer)
def display_summary(options): """ Display series summary. :param options: argparse options from the CLI """ porcelain = options.table_type == 'porcelain' with Session() as session: kwargs = { 'configured': options.configured, 'premieres': options.premieres, 'session': session, 'sort_by': options.sort_by, 'descending': options.order } if options.new: kwargs['status'] = 'new' kwargs['days'] = options.new elif options.stale: kwargs['status'] = 'stale' kwargs['days'] = options.stale if options.sort_by == 'name': kwargs['sort_by'] = 'show_name' else: kwargs['sort_by'] = 'last_download_date' query = get_series_summary(**kwargs) header = ['Name', 'Latest', 'Age', 'Downloaded', 'Identified By'] for index, value in enumerate(header): if value.lower() == options.sort_by: header[index] = colorize(SORT_COLUMN_COLOR, value) table_data = [header] for series in query: name_column = series.name behind = (0, ) latest_release = '-' age_col = '-' episode_id = '-' latest = get_latest_release(series) identifier_type = series.identified_by if identifier_type == 'auto': identifier_type = colorize('yellow', 'auto') if latest: behind = new_entities_after(latest) latest_release = get_latest_status(latest) # colorize age age_col = latest.age if latest.age_timedelta is not None: if latest.age_timedelta < timedelta(days=1): age_col = colorize(NEW_EP_COLOR, latest.age) elif latest.age_timedelta < timedelta(days=3): age_col = colorize(FRESH_EP_COLOR, latest.age) elif latest.age_timedelta > timedelta(days=400): age_col = colorize(OLD_EP_COLOR, latest.age) episode_id = latest.identifier if not porcelain: if behind[0] > 0: name_column += colorize( BEHIND_EP_COLOR, ' {} {} behind'.format(behind[0], behind[1])) table_data.append([ name_column, episode_id, age_col, latest_release, identifier_type ]) try: table = TerminalTable(options.table_type, table_data, wrap_columns=[3], drop_columns=[4, 3, 2]) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return if not porcelain: if not query.count(): console('Use `flexget series list all` to view all known series.') else: console( 'Use `flexget series show NAME` to get detailed information.')
def display_details(options): """Display detailed series information, ie. series show NAME""" name = options.series_name with Session() as session: name = normalize_series_name(name) # Sort by length of name, so that partial matches always show shortest matching title matches = shows_by_name(name, session=session) if not matches: console(colorize(ERROR_COLOR, 'ERROR: Unknown series `%s`' % name)) return # Pick the best matching series series = matches[0] table_title = colorize('white', series.name) if len(matches) > 1: warning = ( colorize('red', ' WARNING: ') + 'Multiple series match to `{}`.\n ' 'Be more specific to see the results of other matches:\n\n' ' {}'.format(name, ', '.join(s.name for s in matches[1:]))) if not options.table_type == 'porcelain': console(warning) header = [ 'Entity ID', 'Latest age', 'Release titles', 'Release Quality', 'Proper' ] table_data = [header] entities = get_all_entities(series, session=session) for entity in entities: if entity.identifier is None: identifier = colorize(ERROR_COLOR, 'MISSING') age = '' else: identifier = entity.identifier age = entity.age entity_data = [identifier, age] release_titles = [] release_qualities = [] release_propers = [] for release in entity.releases: title = release.title quality = release.quality.name if not release.downloaded: title = colorize(UNDOWNLOADED_RELEASE_COLOR, title) quality = quality else: title += ' *' title = colorize(DOWNLOADED_RELEASE_COLOR, title) quality = quality release_titles.append(title) release_qualities.append(quality) release_propers.append( 'Yes' if release.proper_count > 0 else '') entity_data.append('\n'.join(release_titles)) entity_data.append('\n'.join(release_qualities)) entity_data.append('\n'.join(release_propers)) table_data.append(entity_data) footer = ' %s \n' % (colorize(DOWNLOADED_RELEASE_COLOR, '* Downloaded')) if not series.identified_by: footer += ( '\n Series plugin is still learning which episode numbering mode is \n' ' correct for this series (identified_by: auto).\n' ' Few duplicate downloads can happen with different numbering schemes\n' ' during this time.') else: footer += '\n Series uses `%s` mode to identify episode numbering (identified_by).' % series.identified_by footer += ' \n See option `identified_by` for more information.\n' if series.begin: footer += ' Begin episode for this series set to `%s`.' % series.begin.identifier try: table = TerminalTable(options.table_type, table_data, table_title, drop_columns=[4, 3, 1]) console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return if not options.table_type == 'porcelain': console(footer)
def display_summary(options): """ Display series summary. :param options: argparse options from the CLI """ porcelain = options.table_type == 'porcelain' with Session() as session: kwargs = {'configured': options.configured, 'premieres': options.premieres, 'session': session, 'sort_by': options.sort_by, 'descending': options.order} if options.new: kwargs['status'] = 'new' kwargs['days'] = options.new elif options.stale: kwargs['status'] = 'stale' kwargs['days'] = options.stale if options.sort_by == 'name': kwargs['sort_by'] = 'show_name' else: kwargs['sort_by'] = 'last_download_date' query = get_series_summary(**kwargs) header = ['Name', 'Latest', 'Age', 'Downloaded', 'Identified By'] for index, value in enumerate(header): if value.lower() == options.sort_by: header[index] = colorize(SORT_COLUMN_COLOR, value) footer = 'Use `flexget series show NAME` to get detailed information' table_data = [header] for series in query: name_column = series.name new_ep = False behind = 0 latest_release = '-' age_col = '-' episode_id = '-' latest = get_latest_release(series) identifier_type = series.identified_by if identifier_type == 'auto': identifier_type = colorize('yellow', 'auto') if latest: behind = new_eps_after(latest) latest_release = get_latest_status(latest) # colorize age age_col = latest.age if latest.age_timedelta is not None: if latest.age_timedelta < timedelta(days=1): age_col = colorize(NEW_EP_COLOR, latest.age) elif latest.age_timedelta < timedelta(days=3): age_col = colorize(FRESH_EP_COLOR, latest.age) elif latest.age_timedelta > timedelta(days=400): age_col = colorize(OLD_EP_COLOR, latest.age) episode_id = latest.identifier if not porcelain: if behind > 0: name_column += colorize(BEHIND_EP_COLOR, ' {} behind'.format(behind)) table_data.append([name_column, episode_id, age_col, latest_release, identifier_type]) table = TerminalTable(options.table_type, table_data, wrap_columns=[3], drop_columns=[4, 3, 2]) try: console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return if not porcelain: console(footer)
def display_details(options): """Display detailed series information, ie. series show NAME""" name = options.series_name with Session() as session: name = normalize_series_name(name) # Sort by length of name, so that partial matches always show shortest matching title matches = shows_by_name(name, session=session) if not matches: console(colorize(ERROR_COLOR, 'ERROR: Unknown series `%s`' % name)) return # Pick the best matching series series = matches[0] table_title = colorize('white', series.name) if len(matches) > 1: warning = (colorize('red', ' WARNING: ') + 'Multiple series match to `{}`.\n ' 'Be more specific to see the results of other matches:\n\n' ' {}'.format(name, ', '.join(s.name for s in matches[1:]))) if not options.table_type == 'porcelain': console(warning) header = ['Episode ID', 'Latest age', 'Release titles', 'Release Quality', 'Proper'] table_data = [header] episodes = show_episodes(series, session=session) for episode in episodes: if episode.identifier is None: identifier = colorize(ERROR_COLOR, 'MISSING') age = '' else: identifier = episode.identifier age = episode.age ep_data = [identifier, age] release_titles = [] release_qualities = [] release_propers = [] for release in episode.releases: title = release.title quality = release.quality.name if not release.downloaded: title = colorize(UNDOWNLOADED_RELEASE_COLOR, title) quality = quality else: title = colorize(DOWNLOADED_RELEASE_COLOR, title) quality = quality release_titles.append(title) release_qualities.append(quality) release_propers.append('Yes' if release.proper_count > 0 else '') ep_data.append('\n'.join(release_titles)) ep_data.append('\n'.join(release_qualities)) ep_data.append('\n'.join(release_propers)) table_data.append(ep_data) footer = (' %s %s\n' % (colorize(DOWNLOADED_RELEASE_COLOR, 'Downloaded'), colorize(UNDOWNLOADED_RELEASE_COLOR, 'Un-downloaded'))) if not series.identified_by: footer += ('\n' ' Series plugin is still learning which episode numbering mode is \n' ' correct for this series (identified_by: auto).\n' ' Few duplicate downloads can happen with different numbering schemes\n' ' during this time.') else: footer += ' \n Series uses `%s` mode to identify episode numbering (identified_by).' % series.identified_by footer += ' \n See option `identified_by` for more information.\n' if series.begin: footer += ' Begin episode for this series set to `%s`.' % series.begin.identifier table = TerminalTable(options.table_type, table_data, table_title, drop_columns=[4, 3, 1]) try: console(table.output) except TerminalTableError as e: console('ERROR: %s' % str(e)) return if not options.table_type == 'porcelain': console(footer)
def display_details(options): """Display detailed series information, ie. series show NAME""" name = options.series_name sort_by = options.sort_by or os.environ.get(ENV_SHOW_SORTBY_FIELD, 'age') if options.order is not None: reverse = True if options.order == 'desc' else False else: reverse = True if os.environ.get( ENV_SHOW_SORTBY_ORDER) == 'desc' else False with Session() as session: name = flexget.components.series.utils.normalize_series_name(name) # Sort by length of name, so that partial matches always show shortest matching title matches = db.shows_by_name(name, session=session) if not matches: console(colorize(ERROR_COLOR, 'ERROR: Unknown series `%s`' % name)) return # Pick the best matching series series = matches[0] table_title = series.name if len(matches) > 1: warning = ( colorize('red', ' WARNING: ') + 'Multiple series match to `{}`.\n ' 'Be more specific to see the results of other matches:\n\n' ' {}'.format(name, ', '.join(s.name for s in matches[1:]))) if not options.table_type == 'porcelain': console(warning) header = [ 'Identifier', 'Last seen', 'Release titles', 'Quality', 'Proper' ] table_data = [] entities = db.get_all_entities(series, session=session, sort_by=sort_by, reverse=reverse) for entity in entities: if not entity.releases: continue if entity.identifier is None: identifier = colorize(ERROR_COLOR, 'MISSING') age = '' else: identifier = entity.identifier age = entity.age entity_data = [identifier, age] release_titles = [] release_qualities = [] release_propers = [] for release in entity.releases: title = release.title quality = release.quality.name if not release.downloaded: title = colorize(UNDOWNLOADED_RELEASE_COLOR, title) quality = quality else: title += ' *' title = colorize(DOWNLOADED_RELEASE_COLOR, title) quality = quality release_titles.append(title) release_qualities.append(quality) release_propers.append( 'Yes' if release.proper_count > 0 else '') entity_data.append('\n'.join(release_titles)) entity_data.append('\n'.join(release_qualities)) entity_data.append('\n'.join(release_propers)) table_data.append(entity_data) footer = ' %s \n' % (colorize(DOWNLOADED_RELEASE_COLOR, '* Downloaded')) if not series.identified_by: footer += ( '\n Series plugin is still learning which episode numbering mode is \n' ' correct for this series (identified_by: auto).\n' ' Few duplicate downloads can happen with different numbering schemes\n' ' during this time.') else: footer += '\n `%s` uses `%s` mode to identify episode numbering.' % ( series.name, series.identified_by, ) begin_text = 'option' if series.begin: footer += ' \n Begin for `%s` is set to `%s`.' % ( series.name, series.begin.identifier) begin_text = 'and `begin` options' footer += ' \n See `identified_by` %s for more information.' % begin_text table = TerminalTable(*header, table_type=options.table_type, title=table_title) for row in table_data: table.add_row(*row) console(table) if not options.table_type == 'porcelain': console(footer)
def display_summary(options): """ Display series summary. :param options: argparse options from the CLI """ porcelain = options.table_type == 'porcelain' configured = options.configured or os.environ.get(ENV_LIST_CONFIGURED, 'configured') premieres = (True if (os.environ.get(ENV_LIST_PREMIERES) == 'yes' or options.premieres) else False) sort_by = options.sort_by or os.environ.get(ENV_LIST_SORTBY_FIELD, 'name') if options.order is not None: descending = True if options.order == 'desc' else False else: descending = True if os.environ.get( ENV_LIST_SORTBY_ORDER) == 'desc' else False with Session() as session: kwargs = { 'configured': configured, 'premieres': premieres, 'session': session, 'sort_by': sort_by, 'descending': descending, } if sort_by == 'name': kwargs['sort_by'] = 'show_name' else: kwargs['sort_by'] = 'last_download_date' query = db.get_series_summary(**kwargs) header = [ 'Name', 'Begin', 'Last Encountered', 'Age', 'Downloaded', 'Identified By' ] for index, value in enumerate(header): if value.lower() == options.sort_by: header[index] = colorize(SORT_COLUMN_COLOR, value) table = TerminalTable(*header, table_type=options.table_type) for series in query: name_column = series.name behind = (0, ) begin = series.begin.identifier if series.begin else '-' latest_release = '-' age_col = '-' episode_id = '-' latest = db.get_latest_release(series) identifier_type = series.identified_by if identifier_type == 'auto': identifier_type = colorize('yellow', 'auto') if latest: behind = db.new_entities_after(latest) latest_release = get_latest_status(latest) # colorize age age_col = latest.age if latest.age_timedelta is not None: if latest.age_timedelta < timedelta(days=1): age_col = colorize(NEW_EP_COLOR, latest.age) elif latest.age_timedelta < timedelta(days=3): age_col = colorize(FRESH_EP_COLOR, latest.age) elif latest.age_timedelta > timedelta(days=400): age_col = colorize(OLD_EP_COLOR, latest.age) episode_id = latest.identifier if not porcelain: if behind[0] > 0: name_column += colorize( BEHIND_EP_COLOR, ' {} {} behind'.format(behind[0], behind[1])) table.add_row(name_column, begin, episode_id, age_col, latest_release, identifier_type) console(table) if not porcelain: if not query.count(): console('Use `flexget series list all` to view all known series.') else: console( 'Use `flexget series show NAME` to get detailed information.')