5e6834c749
Signed-off-by: ynerant <ynerant@zamokv5.crans.org>
138 lines
4.4 KiB
Python
Executable File
138 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import date
|
|
from math import acos, cos, pi, sin
|
|
import requests
|
|
from threading import Thread
|
|
from time import sleep
|
|
|
|
from irc import IRCClient
|
|
|
|
|
|
@dataclass
|
|
class Location:
|
|
longitude: float = 0.0
|
|
latitude: float = 0.0
|
|
city: str = ""
|
|
|
|
def distance(self, other: "Location") -> float:
|
|
earth_radius = 6378
|
|
|
|
phi_a, phi_b = self.latitude * pi / 180, other.latitude * pi / 180
|
|
lambda_a, lambda_b = self.longitude * pi / 180, other.longitude * pi / 180
|
|
unit_dist = acos(sin(phi_a) * sin(phi_b) \
|
|
+ cos(phi_a) * cos(phi_b) * cos(lambda_b - lambda_a))
|
|
|
|
return earth_radius * unit_dist
|
|
|
|
|
|
@dataclass
|
|
class CentreMetadata:
|
|
address: str = ""
|
|
phone_number: str = ""
|
|
business_hours: dict = None
|
|
|
|
|
|
@dataclass
|
|
class Centre:
|
|
departement: str = ""
|
|
nom: str = ""
|
|
url: str = ""
|
|
location: Location = None
|
|
metadata: CentreMetadata = None
|
|
prochain_rdv: str = ""
|
|
plateforme: str = "Doctolib"
|
|
type: str = "vaccination-center"
|
|
appointment_count: int = 0
|
|
internal_id: str = ""
|
|
vaccine_type: list[str] = None
|
|
appointment_by_phone_only: bool = False
|
|
erreur: any = None
|
|
last_scan_with_availabilities: str = ""
|
|
appointment_schedules: list[dict] = None
|
|
gid: str = ""
|
|
|
|
|
|
def check_dpt(dpt_number: int, position: Location, radius: int = 20):
|
|
"""
|
|
Recherche de rendez-vous disponibles pour les majeurs non-prioritaires
|
|
dans le département indiqué.
|
|
Renvoie une liste de couples (centre, nombre de doses dispo).
|
|
"""
|
|
res = requests.get(f'https://vitemadose.gitlab.io/vitemadose/{dpt_number}.json').json()
|
|
|
|
last_update = res['last_updated']
|
|
centres_dispo = res['centres_disponibles']
|
|
centres_indispo = res['centres_indisponibles']
|
|
print(len(centres_dispo), "centres disponibles sur", len(centres_indispo), "dans le", dpt_number)
|
|
|
|
places = []
|
|
|
|
for centre in centres_dispo:
|
|
centre = Centre(**centre)
|
|
centre.location = Location(**centre.location)
|
|
centre.metadata = CentreMetadata(**centre.metadata)
|
|
|
|
if centre.location.distance(position) > radius:
|
|
# Centre trop loin
|
|
continue
|
|
|
|
for schedule in centre.appointment_schedules:
|
|
if schedule['name'] == 'chronodose':
|
|
if schedule['total']:
|
|
# Places dispo en chronodose
|
|
places.append((centre, schedule['total']))
|
|
return places
|
|
|
|
|
|
def main():
|
|
gif = Location(latitude=48.7090418, longitude=2.1648068, city="Gif-sur-Yvette")
|
|
lyon = Location(latitude=45.7579502, longitude=4.8001017, city="Lyon")
|
|
chambéry = Location(latitude=45.5822142, longitude=5.8713341, city="Chambéry")
|
|
nantes = Location(latitude=47.2382007, longitude=-1.6300954, city="Nantes")
|
|
marseille = Location(latitude=43.2803692, longitude=5.3104571, city="Marseille")
|
|
|
|
irc_client = IRCClient('irc.crans.org', 'chronodose')
|
|
Thread(target=irc_client.start).start()
|
|
sleep(10)
|
|
irc_client.join('#chronodose')
|
|
irc_client.privmsg('#chronodose', 'coucou')
|
|
|
|
already_indicated = []
|
|
|
|
def msg(*mesg: str) -> None:
|
|
# Afficher un message dans la console et sur IRC
|
|
print(*mesg)
|
|
irc_client.privmsg('#chronodose', ' '.join(str(a) for a in mesg))
|
|
|
|
while True:
|
|
places = {}
|
|
for dpt, ville in [(91, gif), (92, gif), (94, gif), (78, gif), (69, lyon),
|
|
(73, chambéry), (44, nantes), (13, marseille)]:
|
|
places[dpt] = check_dpt(dpt, ville)
|
|
|
|
for dpt, places in places.items():
|
|
if not places:
|
|
print("Pas de dose disponible dans le", dpt)
|
|
continue
|
|
print(sum(place[1] for place in places), "doses disponibles dans le", dpt)
|
|
for centre, count in places:
|
|
if (centre.internal_id, date.today()) in already_indicated:
|
|
# Message déjà envoyé, on spam pas
|
|
continue
|
|
already_indicated.append((centre.internal_id, date.today()))
|
|
|
|
msg(count, "doses dans le centre de", centre.nom)
|
|
msg("Type de vaccin :", ", ".join(centre.vaccine_type))
|
|
msg(centre.metadata.address, centre.metadata.phone_number)
|
|
msg("Réserver sur", centre.url)
|
|
msg(" ")
|
|
|
|
# 5 minutes
|
|
sleep(300)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|