socket.py (5534B) download
1from datetime import datetime
2import os
3import random
4import sys
5from typing import Dict
6from flask import request, jsonify
7from flask_login import current_user
8from flask_socketio import emit
9
10from .app import app, db, socket, domain
11from .models import Statistic, Trap, User
12
13current_user: User
14
15sockets: Dict[int, str] = {}
16
17accuracy_min = 80
18
19
20def make_token():
21 return ''.join(random.choice('0123456789abcdefghijklmnopqrstuvwxyz') for _ in range(16))
22
23
24@app.post("/api/hello")
25def register_trap():
26 req = request.get_json(True)
27 if not req:
28 return jsonify(dict(error='invalid-request'))
29
30 res = dict()
31 if 'token' not in req or not req['token'] or not Trap.query.filter_by(token=req['token']).first():
32 while True:
33 token = make_token()
34 if not Trap.query.filter_by(token=token).first():
35 break
36
37 trap = Trap(token=token, last_status=datetime.now())
38 db.session.add(trap)
39 db.session.commit()
40 res['token'] = token
41 else:
42 trap: Trap = Trap.query.filter_by(token=req['token']).first()
43
44 res['location_search'] = trap.location_search
45
46 if 'domain' not in req or req['domain'] != domain:
47 res['domain'] = domain
48
49 return jsonify(res)
50
51
52@app.post("/api/update")
53def update_status():
54 req = request.get_json(True)
55 if not req:
56 return jsonify(dict(error='invalid-request'))
57
58 trap: Trap = Trap.query.filter_by(token=req['token']).first()
59 if not trap:
60 return jsonify(dict(error='invalid-token'))
61
62 if not trap.caught and req['trap']:
63 if trap.owner:
64 stc = Statistic(user=trap.owner, trap=trap.id, date=datetime.now())
65 db.session.add(stc)
66 if os.environ.get('SEND_MAIL', '0') != '0':
67 os.system(
68 f"echo \"<p>Uw muizenval '{trap.name}' heeft iets gevangen!<br>Ga naar <a href='http://muizenval.tk/traps'>uw dashboard</a>.</p><p>Groetjes Team Benni!</p>\" | mailx -a 'Content-Type: text/html' -s 'Muizenval is geactiveerd' {trap.owner_class().email}") # type: ignore
69 print('Email sent!')
70
71 trap.last_status = datetime.now()
72 trap.caught = req['trap']
73 trap.battery = req['battery']
74 trap.temperature = req['temperature']
75 trap.charging = req['charging']
76 trap.location_searching = req['searching']
77 if trap.location_search:
78 trap.location_satellites = req['satellites']
79 if req['accuracy'] != 0:
80 trap.location_acc = req['accuracy']
81 trap.location_lat = req['latitude']
82 trap.location_lon = req['longitude']
83
84 db.session.commit()
85
86 if trap.owner and trap.owner in sockets:
87 socket.emit('trap-change', trap.to_json(), to=sockets[trap.owner])
88 socket.emit('statistics', make_statistics(
89 trap.owner), to=sockets[trap.owner])
90
91 return jsonify(dict(location_search=trap.location_search))
92
93
94def make_statistics(user: int):
95 year = datetime.now().year
96 months = [0] * 12
97 table = []
98 stc: Statistic
99 for stc in Statistic.query.filter_by(user=user):
100 table.append([stc.id, Trap.query.get(stc.trap).name,
101 stc.date.strftime('%d-%m-%y %H:%M')])
102 if stc.date.year == year:
103 months[stc.date.month-1] += 1
104
105 return dict(months=months, table=table)
106
107
108@socket.on('connect')
109def socket_connect():
110 if not current_user.is_authenticated:
111 return
112
113 sockets[current_user.id] = request.sid # type: ignore
114
115 for trap in Trap.query.filter_by(owner=current_user.id):
116 emit('trap-change', trap.to_json())
117
118 emit('statistics', make_statistics(current_user.id))
119
120
121@socket.on('disconnect')
122def socket_disconnect():
123 if not current_user.is_authenticated:
124 return
125
126 if current_user.id in sockets:
127 del sockets[current_user.id]
128
129
130@socket.on('token')
131def socket_token(token):
132 if not token or not current_user.is_authenticated:
133 return
134
135 trap: Trap = Trap.query.filter_by(token=token).first()
136
137 if trap.owner != current_user.id:
138 trap.owner = current_user.id
139 trap.owned_date = datetime.now()
140 db.session.commit()
141
142 emit('trap-change', trap.to_json())
143
144
145@socket.on('location-search')
146def socket_location(data):
147 if not data or not current_user.is_authenticated:
148 return
149
150 print(data['id'])
151 trap: Trap = Trap.query.get(data['id'])
152 if not trap or trap.owner != current_user.id:
153 return
154
155 trap.location_search = data['search']
156 db.session.commit()
157
158 emit('trap-change', trap.to_json())
159
160
161@socket.on('delete')
162def socket_delete(data):
163 if not data or not current_user.is_authenticated:
164 return
165
166 print(data['id'])
167 trap: Trap = Trap.query.get(data['id'])
168 if not trap or trap.owner != current_user.id:
169 return
170
171 Statistic.query.filter_by(trap=trap.id).delete()
172
173 trap.owner = False
174 trap.name = "n/a"
175
176 db.session.commit()
177
178
179@socket.on('name')
180def socket_name(data):
181 if not data or not current_user.is_authenticated:
182 return
183
184 trap: Trap = Trap.query.get(data['id'])
185 if not trap or trap.owner != current_user.id:
186 return
187
188 trap.name = data['name']
189 db.session.commit()
190
191 emit('trap-change', trap.to_json())
192
193
194@socket.on('delete-statistic')
195def socket_delete_statistic(id: int):
196 if not id or not current_user.is_authenticated:
197 return
198
199 Statistic.query.filter_by(id=id).delete()
200
201 db.session.commit()
202
203 emit('statistics', make_statistics(current_user.id))