socket.py (5534B)
1 from datetime import datetime 2 import os 3 import random 4 import sys 5 from typing import Dict 6 from flask import request, jsonify 7 from flask_login import current_user 8 from flask_socketio import emit 9 10 from .app import app, db, socket, domain 11 from .models import Statistic, Trap, User 12 13 current_user: User 14 15 sockets: Dict[int, str] = {} 16 17 accuracy_min = 80 18 19 20 def make_token(): 21 return ''.join(random.choice('0123456789abcdefghijklmnopqrstuvwxyz') for _ in range(16)) 22 23 24 @app.post("/api/hello") 25 def 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") 53 def 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 94 def 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') 109 def 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') 122 def 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') 131 def 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') 146 def 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') 162 def 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') 180 def 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') 195 def 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))