1import sys
2from argparse import ArgumentParser, ArgumentTypeError
3
4from sqlalchemy.orm.exc import NoResultFound
5
6from flexget import options
7from flexget.event import event
8from flexget.manager import Session
9from flexget.terminal import TerminalTable, colorize, console, disable_colors, table_parser
10
11from . import db
12
13
14def valid_entry(value):
15    try:
16        int(value)
17    except ValueError:
18        if value != 'all':
19            raise ArgumentTypeError('Must select \'all\' or valid entry ID')
20    return value
21
22
23def do_cli(manager, options):
24    if hasattr(options, 'table_type') and options.table_type == 'porcelain':
25        disable_all_colors()
26
27    if options.action == 'list':
28        list_entries(options)
29    elif options.action == 'approve':
30        manage_entries(options, options.selection, True)
31    elif options.action == 'reject':
32        manage_entries(options, options.selection, False)
33    elif options.action == 'clear':
34        clear_entries(options)
35
36
37def list_entries(options):
38    """List pending entries"""
39    approved = options.approved
40    task_name = options.task_name
41
42    with Session() as session:
43        entries = db.list_pending_entries(session=session, task_name=task_name, approved=approved)
44        header = ['#', 'Task Name', 'Title', 'URL', 'Approved', 'Added']
45        table = TerminalTable(*header, table_type=options.table_type)
46        for entry in entries:
47            table.add_row(
48                str(entry.id),
49                entry.task_name,
50                entry.title,
51                entry.url,
52                colorize('green', 'Yes') if entry.approved else 'No',
53                entry.added.strftime("%c"),
54            )
55    console(table)
56
57
58def manage_entries(options, selection, approved):
59    """Manage pending entries"""
60    approved_text = 'approved' if approved else 'pending'
61    with Session() as session:
62        if selection == 'all':
63            entries = db.list_pending_entries(session=session, approved=not approved)
64        else:
65            try:
66                entry = db.get_entry_by_id(session, selection)
67                if entry.approved is approved:
68                    console(
69                        colorize('red', 'ERROR: ')
70                        + 'Entry with ID %s is already %s' % (entry.id, approved_text)
71                    )
72                    sys.exit(1)
73            except NoResultFound:
74                console('Pending entry with ID %s does not exist' % selection)
75                sys.exit(1)
76            else:
77                entries = [entry]
78        if not entries:
79            console('All entries are already %s' % approved_text)
80            return
81        for entry in entries:
82            if entry.approved is not approved:
83                console(
84                    'Setting pending entry with ID %s status to %s' % (entry.id, approved_text)
85                )
86                entry.approved = approved
87
88
89def clear_entries(options):
90    """Clear pending entries"""
91    with Session() as session:
92        query = session.query(db.PendingEntry).filter(db.PendingEntry.approved == False)
93        if options.task_name:
94            query = query.filter(db.PendingEntry.task_name == options.task_name)
95        deleted = query.delete()
96        console('Successfully deleted %i pending entries' % deleted)
97
98
99@event('options.register')
100def register_parser_arguments():
101    selection_parser = ArgumentParser(add_help=False)
102    selection_parser.add_argument(
103        'selection', type=valid_entry, help='Entity ID or \'all\' to approve all pending entries'
104    )
105
106    filter_parser = ArgumentParser(add_help=False)
107    filter_parser.add_argument('--task-name', help='Filter by task name')
108
109    parser = options.register_command('pending', do_cli, help='View and manage pending entries')
110    subparsers = parser.add_subparsers(title='actions', metavar='<action>', dest='action')
111
112    list_parser = subparsers.add_parser(
113        'list', help='Shows all existing pending entries', parents=[table_parser, filter_parser]
114    )
115
116    list_group = list_parser.add_mutually_exclusive_group()
117    list_group.add_argument(
118        '--pending',
119        action='store_false',
120        help='Show only pending entries',
121        dest='approved',
122        default=None,
123    )
124    list_group.add_argument(
125        '--approved',
126        action='store_true',
127        help='Show only approved entries',
128        dest='approved',
129        default=None,
130    )
131
132    subparsers.add_parser('approve', help='Approve pending entries', parents=[selection_parser])
133    subparsers.add_parser('reject', help='Reject pending entries', parents=[selection_parser])
134    subparsers.add_parser('clear', help='Clear all pending entries', parents=[filter_parser])
135