6f9f346777dad836c0c878793fce49f3b53d449f
[nmhive.git] / nmhive.py
1 #!/usr/bin/env python
2
3 import json
4 import mailbox
5 import os
6 import tempfile
7 import urllib.request
8
9 import flask
10 import flask_cors
11 import notmuch
12
13
14 app = flask.Flask(__name__)
15 app.config['CORS_HEADERS'] = 'Content-Type'
16 flask_cors.CORS(app)
17
18 TAG_PREFIX = os.getenv('NMBPREFIX', 'notmuch::')
19 NOTMUCH_PATH = None
20
21
22 @app.route('/tags', methods=['GET'])
23 def tags():
24     tags = set()
25     database = notmuch.Database(path=NOTMUCH_PATH)
26     try:
27         for t in database.get_all_tags():
28             if t.startswith(TAG_PREFIX):
29                 tags.add(t[len(TAG_PREFIX):])
30     finally:
31         database.close()
32     return flask.Response(
33         response=json.dumps(sorted(tags)),
34         mimetype='application/json')
35
36
37 def _message_tags(message):
38     return sorted(
39         tag[len(TAG_PREFIX):] for tag in message.get_tags()
40         if tag.startswith(TAG_PREFIX))
41
42
43 @app.route('/mid/<message_id>', methods=['GET', 'POST'])
44 def message_id_tags(message_id):
45     if flask.request.method == 'POST':
46         database = notmuch.Database(
47             path=NOTMUCH_PATH,
48             mode=notmuch.Database.MODE.READ_WRITE)
49         try:
50             message = database.find_message(message_id)
51             if not(message):
52                 return flask.Response(status=404)
53             database.begin_atomic()
54             message.freeze()
55             for change in flask.request.get_json():
56                 if change.startswith('+'):
57                     message.add_tag(TAG_PREFIX + change[1:])
58                 elif change.startswith('-'):
59                     message.remove_tag(TAG_PREFIX + change[1:])
60                 else:
61                     return flask.Response(status=400)
62             message.thaw()
63             database.end_atomic()
64             tags = _message_tags(message=message)
65         finally:
66             database.close()
67     elif flask.request.method == 'GET':
68         database = notmuch.Database(path=NOTMUCH_PATH)
69         try:
70             message = database.find_message(message_id)
71             if not(message):
72                 return flask.Response(status=404)
73             tags = _message_tags(message=message)
74         finally:
75             database.close()
76     return flask.Response(
77         response=json.dumps(tags),
78         mimetype='application/json')
79
80
81 @app.route('/gmane/<group>/<int:article>', methods=['GET'])
82 def gmane_message_id(group, article):
83     url = 'http://download.gmane.org/{}/{}/{}'.format(
84         group, article, article + 1)
85     response = urllib.request.urlopen(url=url, timeout=3)
86     mbox_bytes = response.read()
87     with tempfile.NamedTemporaryFile(prefix='nmbug-', suffix='.mbox') as f:
88         f.write(mbox_bytes)
89         mbox = mailbox.mbox(path=f.name)
90         _, message = mbox.popitem()
91         message_id = message['message-id']
92     return flask.Response(
93         response=message_id.lstrip('<').rstrip('>'),
94         mimetype='text/plain')
95
96
97 if __name__ == '__main__':
98     app.run(host='0.0.0.0')