3 """Serve a JSON API for getting/setting notmuch tags with nmbug commits."""
17 app = flask.Flask(__name__)
18 app.config['CORS_HEADERS'] = 'Content-Type'
21 TAG_PREFIX = os.getenv('NMBPREFIX', 'notmuch::')
25 @app.route('/tags', methods=['GET'])
28 database = notmuch.Database(path=NOTMUCH_PATH)
30 for t in database.get_all_tags():
31 if t.startswith(TAG_PREFIX):
32 tags.add(t[len(TAG_PREFIX):])
35 return flask.Response(
36 response=json.dumps(sorted(tags)),
37 mimetype='application/json')
40 def _message_tags(message):
42 tag[len(TAG_PREFIX):] for tag in message.get_tags()
43 if tag.startswith(TAG_PREFIX))
46 @app.route('/mid/<message_id>', methods=['GET', 'POST'])
47 def message_id_tags(message_id):
48 if flask.request.method == 'POST':
49 changes = flask.request.get_json()
51 return flask.Response(status=400)
52 database = notmuch.Database(
54 mode=notmuch.Database.MODE.READ_WRITE)
56 message = database.find_message(message_id)
58 return flask.Response(status=404)
59 database.begin_atomic()
61 for change in changes:
62 if change.startswith('+'):
63 message.add_tag(TAG_PREFIX + change[1:])
64 elif change.startswith('-'):
65 message.remove_tag(TAG_PREFIX + change[1:])
67 return flask.Response(status=400)
70 tags = _message_tags(message=message)
73 nmbug.commit(message='nmhive: {} {}'.format(
74 message_id, ' '.join(changes)))
75 elif flask.request.method == 'GET':
76 database = notmuch.Database(path=NOTMUCH_PATH)
78 message = database.find_message(message_id)
80 return flask.Response(status=404)
81 tags = _message_tags(message=message)
84 return flask.Response(
85 response=json.dumps(tags),
86 mimetype='application/json')
89 @app.route('/gmane/<group>/<int:article>', methods=['GET'])
90 def gmane_message_id(group, article):
91 url = 'http://download.gmane.org/{}/{}/{}'.format(
92 group, article, article + 1)
93 response = urllib.request.urlopen(url=url, timeout=3)
94 mbox_bytes = response.read()
95 with tempfile.NamedTemporaryFile(prefix='nmbug-', suffix='.mbox') as f:
97 mbox = mailbox.mbox(path=f.name)
98 _, message = mbox.popitem()
99 message_id = message['message-id']
100 return flask.Response(
101 response=message_id.lstrip('<').rstrip('>'),
102 mimetype='text/plain')
105 if __name__ == '__main__':
108 parser = argparse.ArgumentParser(description=__doc__)
110 '-H', '--host', default='127.0.0.1',
111 help='The hostname to listen on.')
113 '-p', '--port', type=int, default=5000,
114 help='The port to listen on.')
116 '-d', '--debug', type=bool, default=False,
117 help='Run Flask in debug mode (e.g. show errors).')
119 args = parser.parse_args()
121 app.debug = args.debug
122 app.run(host=args.host, port=args.port)