Passed
Push — master ( dd0bda...e4c11f )
by Alexander
02:47 queued 01:21
created

things3.things3_api.Things3API.api_toggle()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
4
"""Simple read-only Things 3 Web Serivce."""
5
6
from __future__ import print_function
7
8
__author__ = "Alexander Willner"
9
__copyright__ = "Copyright 2020 Alexander Willner"
10
__credits__ = ["Alexander Willner"]
11
__license__ = "Apache License 2.0"
12
__version__ = "2.5.0.dev0"
13
__maintainer__ = "Alexander Willner"
14
__email__ = "[email protected]"
15
__status__ = "Development"
16
17
import sys
18
from os import getcwd
19
import json
20
from flask import Flask
21
from flask import Response
22
from flask import request
23
from werkzeug.serving import make_server
24
from things3.things3 import Things3
25
26
27
class Things3API():
28
    """API Wrapper for the simple read-only API for Things 3."""
29
30
    HOST = 'localhost'
31
    PORT = 15000
32
    PATH = getcwd() + '/resources/'
33
    things3 = None
34
    harmonized = True
35
    test_mode = "task"
36
37
    def on_get(self, url):
38
        """Handles other GET requests"""
39
        filename = self.PATH + url
40
        content_type = 'application/json'
41
        if filename.endswith('css'):
42
            content_type = 'text/css'
43
        if filename.endswith('html'):
44
            content_type = 'text/html'
45
        if filename.endswith('js'):
46
            content_type = 'text/javascript'
47
        if filename.endswith('png'):
48
            content_type = 'image/png'
49
        if filename.endswith('jpg'):
50
            content_type = 'image/jpeg'
51
        if filename.endswith('ico'):
52
            content_type = 'image/x-ico'
53
        with open(filename, 'rb') as source:
54
            data = source.read()
55
        return Response(response=data, content_type=content_type)
56
57
    def mode_selector(self):
58
        """Switch between project and task mode"""
59
        try:
60
            mode = request.args.get('mode')
61
        except RuntimeError:
62
            mode = 'task'
63
        if mode == "project" or self.test_mode == "project":
64
            self.things3.mode_project()
65
66
    def api(self, command):
67
        """Return database as JSON strings."""
68
        if command in self.things3.functions:
69
            func = self.things3.functions[command]
70
            self.mode_selector()
71
            data = func(self.things3)
72
            self.things3.mode_task()
73
            data = json.dumps(data)
74
            return Response(response=data, content_type='application/json')
75
76
        data = json.dumps(self.things3.get_not_implemented())
77
        return Response(response=data, content_type='application/json',
78
                        status=404)
79
80
    def api_filter(self, mode, uuid):
81
        """Filter view by specific modifiers"""
82
        if mode == "area" and uuid != "":
83
            self.things3.filter = f"TASK.area = '{uuid}' AND"
84
        if mode == "project" and uuid != "":
85
            self.things3.filter = f"""
86
                (TASK.project = '{uuid}' OR HEADING.project = '{uuid}') AND
87
                """
88
        return Response(status=200)
89
90
    def api_filter_reset(self):
91
        """Reset filter modifiers"""
92
        self.things3.filter = ""
93
        return Response(status=200)
94
95
    def __init__(self, database=None):
96
        self.things3 = Things3(database=database)
97
        self.flask = Flask(__name__)
98
        self.flask.add_url_rule('/api/<command>', view_func=self.api)
99
        self.flask.add_url_rule(
100
            '/api/filter/<mode>/<uuid>', view_func=self.api_filter)
101
        self.flask.add_url_rule('/api/filter/reset',
102
                                view_func=self.api_filter_reset)
103
        self.flask.add_url_rule('/<url>', view_func=self.on_get)
104
        self.flask.app_context().push()
105
        self.flask_context = None
106
107
    def main(self):
108
        """"Main function."""
109
        print(f"Serving at http://{self.HOST}:{self.PORT} ...")
110
111
        try:
112
            self.flask_context = make_server(
113
                self.HOST, self.PORT, self.flask, True)
114
            self.flask_context.serve_forever()
115
        except KeyboardInterrupt:
116
            print("Shutting down...")
117
            sys.exit(0)
118
119
120
def main():
121
    """Main entry point for CLI installation"""
122
    Things3API().main()
123
124
125
if __name__ == "__main__":
126
    main()
127