This repository has been archived by the owner on Feb 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathanalytics_server.py
145 lines (119 loc) · 4.49 KB
/
analytics_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
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading
import urlparse
import json
from datetime import datetime, timedelta
import GeoIP
import os.path
FILE_MPVERSIONS = "data/mailpile.versions"
FILE_MPNEWS = "data/mailpile.news"
CHECKIN_CACHE_MAX = 500
MAX_NEWS_AGE = 300
MAX_CACHE_AGE = 30
versions = []
checkin_cache = []
news_lastchecked = datetime(1970, 1, 1, 0, 0, 1)
checkindb_lastwrite = datetime.now()
news_cache = ""
checkin_lock = threading.Lock()
news_lock = threading.Lock()
def load_versions(vfile):
global versions
with open(vfile) as f:
versions = [x.strip() for x in f.readlines()]
print "Loaded Mailpile versions"
class Handler(BaseHTTPRequestHandler):
def __init__(self, a, b, c):
self.dispatch = {
"/": self._index,
"/checkin/": self._checkin,
}
BaseHTTPRequestHandler.__init__(self, a, b, c)
def _get_next_checkin_time(self):
str(datetime.now() + timedelta(seconds=604800))
def _get_newest_version(self):
return versions[-1]
def _register_checkin(self, uptime, country, version):
global checkindb_lastwrite
global checkin_cache
with checkin_lock:
checkin_cache.append((uptime, country, version))
if (len(checkin_cache) >= CHECKIN_CACHE_MAX or
(datetime.now() - checkindb_lastwrite).seconds
> MAX_CACHE_AGE):
with open("checkindb.txt", "a") as fh:
for l in checkin_cache:
fh.write("%s,%s,%s\n" % l)
checkin_cache = []
checkindb_lastwrite = datetime.now()
print "Wrote out to checkindb"
def _get_news(self):
global news_cache
global news_lastchecked
if (datetime.now() - news_lastchecked).seconds > MAX_NEWS_AGE:
if datetime.utcfromtimestamp(os.path.getmtime(FILE_MPNEWS)) > news_lastchecked:
with news_lock:
news_cache = open(FILE_MPNEWS).read()
news_lastchecked = datetime.now()
print "Reloaded news"
load_versions(FILE_MPVERSIONS)
return news_cache
def _index(self, qd):
self._response(200, "Hello!")
def _checkin(self, qd):
response = {}
query = urlparse.parse_qs(qd.query, False, True)
try:
assert("ts" in query and len(query["ts"]))
assert("cc" in query and len(query["cc"]))
assert("vn" in query and len(query["vn"]))
except AssertionError, e:
return self._response(400, "Missing parameters")
try:
uptime = int(query["ts"][0])
except ValueError, e:
return self._response(400, "ts must be an integer")
try:
country = query["cc"][0]
assert(country in GeoIP.country_codes)
except AssertionError, e:
return self._response(400, "cc must be a valid country code")
try:
version = query["vn"][0]
assert(version in versions)
except AssertionError:
return self._response(400, "vn must be a valid version number")
# print uptime, country, version
self._register_checkin(uptime, country, version)
response["newest_version"] = self._get_newest_version()
response["news"] = self._get_news()
response["reportback_next"] = self._get_next_checkin_time()
response["reportback_server"] = "checkin.mailpile.is"
self._response(200, json.dumps(response))
def _response(self, response_code, message):
self.send_response(response_code)
self.end_headers()
self.wfile.write(message)
def _404(self, qd):
self._response(404, "Nothing found")
def _500(self, qd):
self._response(500, "Error")
def do_GET(self):
parsed_path = urlparse.urlparse(self.path)
print "Dispatching '%s'" % (str(parsed_path),)
cb = self.dispatch.get(parsed_path.path, self._404)
cb(parsed_path)
try:
pass
except Exception, e:
print e
print "Something bad happened!"
self._500(parsed_path)
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass
if __name__ == '__main__':
load_versions(FILE_MPVERSIONS)
server = ThreadedHTTPServer(('localhost', 8080), Handler)
print 'Starting server, use <Ctrl-C> to stop'
server.serve_forever()