forked from cmyr/anagramatron
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hit_server.py
183 lines (157 loc) · 5.49 KB
/
hit_server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
from __future__ import print_function
from bottle import (Bottle, run, request, server_names,
ServerAdapter, abort)
import time
import hitmanager
import anagramstats as stats
import daemon
# import os
# import sys
from hitmanager import (HIT_STATUS_REVIEW, HIT_STATUS_SEEN, HIT_STATUS_MISC,
HIT_STATUS_REJECTED, HIT_STATUS_POSTED, HIT_STATUS_APPROVED)
# SSL subclass of bottle cribbed from:
# http://dgtool.blogspot.com.au/2011/12/ssl-encryption-in-python-bottle.html
# Declaration of new class that inherits from ServerAdapter
# It's almost equal to the supported cherrypy class CherryPyServer
from serverauth import AUTH_TOKEN, TEST_PORT
class MySSLCherryPy(ServerAdapter):
def run(self, handler):
import cherrypy
from cherrypy import wsgiserver
server = cherrypy.wsgiserver.CherryPyWSGIServer(
(self.host, self.port),
handler,
numthreads=1,
max=1)
# If cert variable is has a valid path, SSL will be used
# You can set it to None to disable SSL
cert = 'data/server.pem' # certificate path
server.ssl_certificate = cert
server.ssl_private_key = cert
try:
server.start()
finally:
server.stop()
# Add our new MySSLCherryPy class to the supported servers
# under the key 'mysslcherrypy'
server_names['sslbottle'] = MySSLCherryPy
app = Bottle()
def authenticate(auth):
return True
if auth == AUTH_TOKEN:
return True
print('failed authentication')
abort(401, '-_-')
# actual bottle stuff
@app.route('/hits')
def get_hits():
print(request)
count = 50
auth = request.get_header('Authorization')
if not authenticate(auth):
return
# update data
try:
status = str(request.query.status)
except ValueError:
status = HIT_STATUS_REVIEW
try:
cutoff = int(request.query.cutoff)
except ValueError:
cutoff = 0
if (request.query.count):
count = int(request.query.count)
print('client requested %i hits with %s status, from %i' %
(count, status, cutoff))
hits = hitmanager.all_hits(status, cutoff)
total_hits = len(hits)
print('hitmanager returned %i hits' % total_hits)
hits = sorted(hits, key=lambda k: k['id'], reverse=True)
hits = hits[:count]
print("returned %i hits" % len(hits))
return {'hits': hits, 'total_count': total_hits}
@app.route('/mod')
def modify_hit():
print(request)
auth = request.get_header('Authorization')
if not authenticate(auth):
return
hit_id = int(request.query.id)
action = str(request.query.status)
print(hit_id, action)
if not hit_id or not action:
abort(400, 'v0_0v')
success_flag = hitmanager.set_hit_status(hit_id, action)
success_string = 'succeeded' if success_flag else 'FAILED'
print('modification of hit %i to status %s %s'
% (hit_id, action, success_string))
return {'action': action, 'hit': hit_id, 'success': success_flag}
@app.route('/seen')
def mark_seen():
auth = request.get_header('Authorization')
if not authenticate(auth):
return
hit_ids = request.query.hits
hit_ids = hit_ids.split(',')
print(hit_ids)
if not len(hit_ids):
print('no ids -_-')
if len(hit_ids) == 1:
itwerked = hitmanager.set_hit_status(hit_ids[0], HIT_STATUS_SEEN)
print('status changed? %s' % str(itwerked))
for i in hit_ids:
hitmanager.set_hit_status(i, HIT_STATUS_SEEN)
return {'action': HIT_STATUS_SEEN, 'count': len(hit_ids)}
@app.route('/approve')
def approve_hit():
auth = request.get_header('Authorization')
if not authenticate(auth):
return
print("/approve endpoint received request:", request.json, request.params)
hit_id = int(request.query.id)
post_now = int(request.query.post_now)
print(hit_id, post_now)
flag = None
if (post_now):
flag = hitmanager.post_hit(hit_id)
if flag:
print('posting hit: %i' % hit_id)
else:
flag = hitmanager.approve_hit(hit_id)
if flag:
print('approved hit: %i' % hit_id)
action = HIT_STATUS_POSTED if post_now else HIT_STATUS_APPROVED
return {
'action': action,
'hit': hit_id,
'success': flag}
@app.route('/info')
def info():
"""
returns some basic stats about what's happening on the server.
"""
auth = request.get_header('Authorization')
if not authenticate(auth):
return
stats_dict = stats.stats_dict()
new_hits = hitmanager.new_hits_count()
last_post = hitmanager.last_post_time()
return {'stats': stats_dict, 'new_hits': new_hits, 'last_post': last_post}
def start_hit_server(debug=False):
if debug:
run(app, host='127.0.0.1', port=TEST_PORT, debug=True)
else:
run(app, host='0.0.0.0', port=TEST_PORT, debug=True, server='sslbottle')
return True
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--daemonize',
help='run as daemon', action="store_true")
parser.add_argument('--debug',
help='run locally', action="store_true")
args = parser.parse_args()
if args.daemonize:
start_hit_daemon(args.debug)
else:
start_hit_server(args.debug)