hanze/muizenval

server/socket.py in master
Repositories | Summary | Log | Files

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))