__main__.py 6.83 KB
Newer Older
Martin Matějek's avatar
Martin Matějek committed
1
import argparse
2
import json
3
import logging
4
import os
5
import sys
Martin Matějek's avatar
Martin Matějek committed
6

7 8
from .api import Api
from .exceptions import (
9
    MediaTypeNotAvailableException,
10
    NoSuchActionException,
11
    NoSuchNotificationException,
12
    NoSuchNotificationSkeletonException,
13
    NotificationNotDismissibleException,
14
    NotificationStorageException,
15
)
16
from .sorting import Sorting
Martin Matějek's avatar
Martin Matějek committed
17

18 19 20 21 22 23 24 25 26 27 28 29 30
SEVERITIES = {
    'info': 'I',
    'warning': 'W',
    'error': 'E',
}

COLORS = {
    'info': '\033[34m',
    'warning': '\033[93m',
    'error': '\033[91m',
    'default': '\033[39m',
}

31
LOGLEVEL = 'INFO'
32

33
logger = logging.getLogger('cliapp')
34

Martin Matějek's avatar
Martin Matějek committed
35 36 37 38 39

def create_argparser():
    """Create new argument parser"""
    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--config", help="Specify config file")
40
    parser.add_argument("--debug", help="More verbose output", action="store_true")
Martin Matějek's avatar
Martin Matějek committed
41 42

    subparsers = parser.add_subparsers(help="sub-command help", dest='command')
43
    subparsers.required = True
Martin Matějek's avatar
Martin Matějek committed
44 45

    parser_action = subparsers.add_parser("add", help="Add new notification")
46
    parser_action.add_argument("--template", help="Notification type / template", default='simple')
47
    parser_action.add_argument("--persistent", help="Persistent notification", action="store_true")
Martin Matějek's avatar
Martin Matějek committed
48
    parser_action.add_argument("--timeout", help="Timeout in minutes after which message disappear", type=int)
49
    parser_action.add_argument("--severity", help="Severity of message")
50
    parser_action.add_argument("--nodismiss", help="Disable explicit dismiss of message", action="store_false")
51
    parser_action.add_argument("--default-action", help="Set action which will be used as 'default'")
Martin Matějek's avatar
Martin Matějek committed
52

53
    group_add = parser_action.add_mutually_exclusive_group(required=True)
54 55 56
    group_add.add_argument('--from-json', metavar='JSON', help='Json string with template variables')
    group_add.add_argument('--from-env', metavar='ENV_VAR', help='ENV variable which will template variables be read from')

57
    parser_list = subparsers.add_parser("list", help="List various things")
58
    parser_list.add_argument("target", help="List stored messages or available templates", choices=["messages", "templates"], nargs="?", default="messages")
59
    parser_list.add_argument("--sort", help="Sort notifications by criterion", nargs="?")
60 61 62

    parser_get = subparsers.add_parser("get", help="Get specific message")
    parser_get.add_argument("msgid", help="ID of notification message")
63
    parser_get.add_argument("media_type", help="Media type of notification message", nargs="?", default="simple")
64
    parser_get.add_argument("lang", help="Language of notification message", nargs="?", default="en")
65
    parser_get.add_argument("--force-media-type", dest="force_media_type", help="Request media type and don't return default media type in case requested one is not available", action="store_true")
Martin Matějek's avatar
Martin Matějek committed
66

67 68 69
    parser_call = subparsers.add_parser("call", help="Call actions on messages")
    parser_call.add_argument("msgid", help="ID of notification message")
    parser_call.add_argument("action", help="Name of action")
70
    parser_call.add_argument("--cmd-args", help="Arguments for command as single string")
71

Martin Matějek's avatar
Martin Matějek committed
72 73 74
    return parser


75 76 77 78
def print_severity(severity):
    return "{}[{}]{}".format(COLORS[severity], SEVERITIES[severity], COLORS['default'])


79 80 81
def print_templates(templates):
    """Pretty print templates list"""
    print("Available templates:")
82 83
    for t in templates:
        print(t)
84 85


86
def list_notifications(notifications):
87
    """Pretty print stored notifications"""
88
    print("Stored notifications:")
89
    for k, v in notifications.items():
90
        trimmed = ' '.join(v['message'][:80].split())
91 92
        severity = v['metadata']['severity']

93
        print("{} {}\t{}".format(print_severity(severity), k[:8], trimmed))
94 95


96 97
def print_notification(notification):
    """Print single rendered notification"""
98 99 100
    print("Message: {}".format(notification['message']))
    print("Actions: {}".format(notification['actions']))
    print("Metadata: {}".format(notification['metadata']))
101 102


103
def setup_logging(loglevel=logging.INFO):
104 105
    logging_format = "%(levelname)s: %(message)s"
    logging.basicConfig(level=loglevel, format=logging_format)
106
    logger.setLevel(loglevel)
107 108


109
def process_args(parser, args):
Martin Matějek's avatar
Martin Matějek committed
110
    """Call module interface based on args"""
111 112 113 114
    if args.debug:
        setup_logging(logging.DEBUG)
    else:
        setup_logging()
115

116 117
    logger.debug("Argparser arguments: %s", args)

118 119 120 121 122
    if args.config:
        api = Api(os.path.abspath(args.config))
    else:
        api = Api()

Martin Matějek's avatar
Martin Matějek committed
123
    if args.command == 'add':
Martin Matějek's avatar
Martin Matějek committed
124 125
        opts = {
            'skel_id': args.template,
126
            'data': json.loads(args.from_json),
Martin Matějek's avatar
Martin Matějek committed
127
        }
Martin Matějek's avatar
Martin Matějek committed
128

129 130 131 132
        if args.persistent:
            opts['persistent'] = args.persistent
        if args.severity:
            opts['severity'] = args.severity
Martin Matějek's avatar
Martin Matějek committed
133 134
        if args.timeout:
            opts['timeout'] = args.timeout * 60
135 136
        if not args.nodismiss:
            opts['explicit_dismiss'] = args.nodismiss
137 138
        if args.default_action:
            opts['default_action'] = args.default_action
139

140 141
        try:
            ret = api.create(**opts)
142
            print("Succesfully created notification '{}'".format(ret))
143
        except NoSuchNotificationSkeletonException:
144
            print("'{}' is not valid notification template".format(args.template))
145 146
            sys.exit(1)
        except NotificationStorageException as e:
147
            print("Failed to create notification. Reason: {}".format(e))
148
            sys.exit(1)
Martin Matějek's avatar
Martin Matějek committed
149

150
    elif args.command == 'list':
151
        if args.target == 'messages':
152
            ret = api.get_notifications()
153 154 155

            if args.sort:
                ret = Sorting.sort_by(ret, args.sort)
156 157 158
            else:
                # Sorting by timestamp is default sort order
                ret = Sorting.sort_by(ret, 'timestamp')
159

160
            list_notifications(ret)
Martin Matějek's avatar
Martin Matějek committed
161

162 163 164
        elif args.target == 'templates':
            ret = api.get_templates()
            print_templates(ret)
165 166 167 168 169 170

    elif args.command == 'get':
        msgid = args.msgid
        media_type = args.media_type
        lang = args.lang

171 172 173 174 175
        try:
            ret = api.get_rendered_notification(msgid, media_type, lang, args.force_media_type)

            print_notification(ret)
        except NoSuchNotificationException as e:
176
            print(e)
177
        except MediaTypeNotAvailableException as e:
178
            print(e)
179

180
    elif args.command == 'call':
181 182
        try:
            api.call_action(args.msgid, args.action, args.cmd_args)
183
        except NoSuchNotificationException as e:
184
            print(e)
185
        except NoSuchActionException as e:
186 187 188
            print("Failed to call action on notification: {}".format(e))
        except NotificationNotDismissibleException:
            print("This notification cannot be dismissed via dismiss action. Use another action instead.")
Martin Matějek's avatar
Martin Matějek committed
189 190 191 192 193 194


def main():
    parser = create_argparser()
    args = parser.parse_args()

195
    process_args(parser, args)
Martin Matějek's avatar
Martin Matějek committed
196 197 198 199


if __name__ == '__main__':
    main()