Compare commits

...

23 Commits

Author SHA1 Message Date
tfa
04475f8158 MAJ json arrêts 2025-09-29 15:49:00 +02:00
tfa
85b059702f MAJ version 2025-09-29 15:38:44 +02:00
tfa
aa1813533e Changement codes lignes 2025-09-29 15:38:07 +02:00
tfa
d66213275f Gestion retour null dans le json 2023-07-03 09:26:11 +02:00
tfa
2b73d5b251 horaire peut être écrit au singulier 2023-03-22 08:32:06 +01:00
tfa
53dd903886 Meilleur affichage des messages long 2023-03-21 16:27:03 +01:00
tfa
37e239a252 Ajout sécurité si aucune alerte sur le réseau + filtre multiple messages identiques 2023-03-21 10:24:32 +01:00
tfa
82426e7c69 Demande de 300 résultats pour les alertes trafic 2023-01-18 09:45:29 +01:00
tfa
6cdde8dfce Correction lignes en majuscules, MAJ help, MAJ version 2023-01-05 17:21:39 +01:00
tfa
d02eee7340 Ajout des horaires théoriques si les estimés pas dispo 2023-01-04 16:37:03 +01:00
tfa
bdc2a516d6 Meilleur affichage et plus rapide 2023-01-04 14:33:28 +01:00
tfa
014da4fc29 Suppression affichage terminus vers terminus 2023-01-04 14:12:14 +01:00
tfa
41a99facd6 Réparation conneries, putain de python 2023-01-04 14:03:47 +01:00
tfa
d4dbb6a99f Revert "Correction message aide"
This reverts commit b1ae69ebfa.
2023-01-04 13:05:06 +01:00
tfa
5e5c81fd8b Suppression affichage terminus vers terminus 2023-01-04 10:54:06 +01:00
tfa
949607a96e Amélioration horaires, prend les valeurs théoriques et estimées (pour la ligne B notamment) 2023-01-04 10:29:26 +01:00
tfa
b1ae69ebfa Correction message aide 2023-01-04 09:33:54 +01:00
tfa
f98f3429d8 Ligne passé en majuscule avant la recherche 2022-12-21 08:40:14 +01:00
tfa
0e7800ab7d Fichier d'arrêt en chemin relatif 2022-12-19 14:17:18 +01:00
tfa
96786dc28c Ajout texte aide et nettoyage 2022-12-19 14:08:42 +01:00
tfa
d595c4d1d6 Réponse en md plutôt que html pour un meilleur rendu sur Element 2022-12-19 11:10:21 +01:00
tfa
2d545decb2 Mise en forme des horaires à l'arrêt 2022-12-16 11:12:37 +01:00
tfa
0fafc044f0 Ajout du fichier nom arrêt <-> id de tcl 2022-12-16 11:12:02 +01:00
3 changed files with 216 additions and 47 deletions

View File

@@ -1,6 +1,6 @@
maubot: 0.1.0
id: tfa.tcl
version: 0.0.1
version: 1.1.0
license: AGPL-3.0-or-later
modules:
- tcl

260
tcl.py
View File

@@ -8,6 +8,67 @@ import asyncio
import json
import base64
import difflib
import re
class Terminus:
def __init__(self, name):
self.name = name
self.horaires = []
self.estimated = False
def add_horaire(self, horaire, est):
if self.estimated == False:
if est == "E":
self.horaires = []
self.horaires.append(horaire)
self.estimated = True
else:
self.horaires.append(horaire)
else:
if est == "E":
self.horaires.append(horaire)
def get_horaires(self):
return self.sort_horaires()
def get_name(self):
return self.name
def sort_horaires(self):
inth = []
for h in self.horaires:
if h == "Proche":
inth.append(0)
else :
inth.append(int(h[:-4]))
inth.sort()
return inth
def get_estimated(self):
return self.estimated
class Ligne:
def __init__(self, name):
self.name = name
self.terminus = []
def add_terminus(self, newterminus):
if newterminus in self.terminus:
return
self.terminus.append(newterminus)
def get_terminus(self, term):
for t in self.terminus:
if t.get_name() == term:
return t
return None
def get_all_terminus(self):
return self.terminus
def get_name(self):
return self.name
class Config(BaseProxyConfig):
@@ -19,20 +80,34 @@ class Config(BaseProxyConfig):
class Tcl(Plugin):
async def start(self) -> None:
self.config.load_and_update()
def help_msg(self):
return(
"""
!tcl alerte ligne -> Retourne les alertes TCL sur la ligne donnée
ligne peut être :
- Metros : A, B, C, D
- Trams : T1, T2 ...
- Renforcés : C1, C2 ...
- Bus : 1, 2 ...
- Funis : F1, F2
ATTENTION : Le bot ne vérifie pas que la ligne existe
!tcl horaires arrêt (-- ligne) -> Retourne les horaires à l'arrêt (et filtre par ligne)
La réponse indique si les horaires sont théoriques (T) ou estimés (E)
Les horaires estimés sont préférés, si pas dispo, les horaires théoriques
sont affichés
Optionnellement le paramètre "-- ligne" permet de filtrer l'affichage pour ne garder que la ligne souhaitée
"""
)
@command.new(name="tcl", help="")
@command.new(name="tcl", help="Permet d'avoir des informations sur les TCL")
@command.argument("pattern", pass_raw=True, required=True)
async def tclInfos(self, evt: MessageEvent, pattern: str) -> None:
await evt.mark_read()
strToEncode = self.config["mail"] + ':' + self.config["password"]
base64string = base64.b64encode(strToEncode.encode('utf-8'))
if not pattern:
await evt.respond(
"""
!tcl alerte ligne -> Retourne les alertes TCL sur la ligne donnée
"""
)
await evt.respond(self.help_msg())
else:
self.log.info("Commande : " + pattern)
if pattern.__contains__("alerte"):
@@ -41,9 +116,16 @@ class Tcl(Plugin):
await evt.respond(
"""
!tcl alerte ligne -> Retourne les alertes TCL sur la ligne donnée
ligne peut être :
- Metros : A, B, C, D
- Trams : T1, T2 ...
- Renforcés : C1, C2 ...
- Bus : 1, 2 ...
- Funis : F1, F2
ATTENTTION : Le bot ne vérifie pas que la ligne existe
"""
)
url = 'https://download.data.grandlyon.com/ws/rdata/tcl_sytral.tclalertetrafic_2/all.json?maxfeatures=200&start=1'
url = 'https://data.grandlyon.com/fr/datapusher/ws/rdata/tcl_sytral.tclalertetrafic_2/all.json?maxfeatures=300&start=1'
resp = await self.http.get(url, headers={'Authorization' : 'Basic ' + base64string.decode('utf-8')})
ans = await resp.text()
try:
@@ -55,35 +137,52 @@ class Tcl(Plugin):
try:
values = objet["values"]
alerte=False
for value in values:
if(value["ligne_cli"] == chunks[1]):
alerte=True
debut = datetime.fromisoformat(value["debut"])
fin = datetime.fromisoformat(value["fin"])
respText = "<h3>" + value["type"] + "</h3><p><strong>" + value["titre"] + "</strong></p><p>" \
+ value["message"] + "</p><strong>" + debut.strftime("%d/%m/%Y à %H:%M") + " au " \
+ fin.strftime("%d/%m/%Y à %H:%M") + "</strong></p>"
await evt.respond(respText, allow_html=True)
if(alerte==False):
await evt.respond("<h3>Pas d'alerte sur cette ligne</h3>", allow_html=True)
if(len(objet["values"]) == 0):
await evt.respond("<h3>Erreur, aucune réponse</h3>", allow_html=True)
else:
msg = []
for value in values:
if(value["ligne_cli"] == chunks[1].upper()):
alerte=True
#Il peut y avoir 100 fois le même message...
if value["message"] not in msg:
msg.append(value["message"])
debut = datetime.fromisoformat(value["debut"])
fin = datetime.fromisoformat(value["fin"])
newMsg = value["message"].replace('\t', '<br>')
newMsg = re.sub(r"(?<![ '-])[A-Z]", r"<br>\g<0>", newMsg)
newMsg = newMsg.replace('<br> <br>', '<br>')
self.log.info(newMsg)
respText = "<h3>" + value["type"] + "</h3><p><strong>" + value["titre"] + "</strong></p><p>" \
+ newMsg + "</p><strong>" + debut.strftime("%d/%m/%Y à %H:%M") + " au " \
+ fin.strftime("%d/%m/%Y à %H:%M") + "</strong></p>"
await evt.respond(respText, allow_html=True)
if(alerte==False):
await evt.respond("<h3>Pas d'alerte sur cette ligne</h3>", allow_html=True)
except KeyError:
await evt.respond("Erreur d'analyse JSON ")
elif pattern.__contains__("horaires"):
elif pattern.__contains__("horaire"):
chunks = pattern.split(None, 1)
if len(chunks) != 2:
await evt.respond(
"""
!tcl horaires arrêt -> Retourne les horaires à l'arrêt
!tcl horaires arrêt (-- ligne) -> Retourne les horaires à l'arrêt (et filtre par ligne)
La réponse indique si les horaires sont théoriques (T) ou estimés (E)
Les horaires estimés sont préférés, si pas dispo, les horaires théoriques
sont affichés
Optionnellement le paramètre "-- ligne" permet de filtrer l'affichage pour ne garder que la ligne souhaitée
"""
)
return
with open("/home/tfa/maubot/tcl/tcl_sytral.tclarret.json") as file:
with open("./tcl/tcl_sytral.tclarret.json") as file:
objet = json.load(file)
values = objet["values"]
arrets = []
for value in values:
arrets.append(value["nom"].lower())
arret = difflib.get_close_matches(chunks[1].lower(),arrets,n=1,cutoff=0.8)
subCmd = chunks[1].split("--",1)
arret = difflib.get_close_matches(subCmd[0].lower(),arrets,n=1,cutoff=0.8)
if len(arret) == 0:
await evt.respond("Arrêt non trouvé")
return
@@ -91,13 +190,13 @@ class Tcl(Plugin):
nomArret = ""
for value in values:
if value["nom"].lower() == arret[0]:
self.log.info(value["id"])
nomArret = value["nom"]
Ids.append(value["id"])
url = 'https://download.data.grandlyon.com/ws/rdata/tcl_sytral.tclpassagearret/all.json?maxfeatures=2000&start=1'
respText = "<h3>Prochains départs " + nomArret + " :</h3><ul>"
self.log.info(respText)
url ='https://data.grandlyon.com/fr/datapusher/ws/rdata/tcl_sytral.tclpassagearret/all.json?maxfeatures=30000&start=1'
respText = "### Prochains départs " + nomArret + " :\n"
lines = []
while len(url) > 0:
resp = await self.http.get(url, headers={'Authorization' : 'Basic ' + base64string.decode('utf-8')})
ans = await resp.text()
@@ -115,27 +214,96 @@ class Tcl(Plugin):
for value in values:
if value["id"] in Ids:
if value["type"] == "E": #Filtré sur les estimés et non théoriques
if value["coursetheorique"].split('-')[0] == "301A" :
transport = "A"
elif value["coursetheorique"].split('-')[0] == "303" :
transport = "C"
elif value["coursetheorique"].split('-')[0] == "325" :
transport = "F1"
elif value["coursetheorique"].split('-')[0] == "326" :
transport = "F2"
elif value["coursetheorique"].split('-')[0] == "304" :
transport = "D"
elif value["coursetheorique"].split('-')[0] == "302A" :
transport = "B"
# Les metros ont leur propre code
code = value["coursetheorique"].split('_')[0]
if code == "301" :
transport = "A"
elif code == "303" :
transport = "C"
elif code == "325" :
transport = "F1"
elif code == "326" :
transport = "F2"
elif code == "304" :
transport = "D"
elif code == "302" :
transport = "B"
elif code == "520" :
transport = "T1"
elif code == "530" :
transport = "T2"
elif code == "540" :
transport = "T3"
elif code == "550" :
transport = "T4"
elif code == "570" :
transport = "T5"
elif code == "590" :
transport = "T6"
elif code == "510" :
transport = "T7"
elif code.isdigit() and int(code) >= 900:
transport = "C" + str(int(code) - 900)
else:
l = value["coursetheorique"].split('_')[0]
if l[-1:].isdigit():
transport = l
else:
transport = value["coursetheorique"].split('-')[0][:-1]
respText += "<li>Ligne " + transport + " - direction " \
+ value["direction"] + " : " + value["delaipassage"] + "</li>"
self.log.info(respText)
transport = value["coursetheorique"].split('-')[0][:-1]
if value["delaipassage"].find('min') < 0 :
continue
found = False
for line in lines:
if line.get_name() == transport:
term = line.get_terminus(value["direction"])
if term is None:
newterm = Terminus(value["direction"])
newterm.add_horaire(value["delaipassage"], value["type"])
line.add_terminus(newterm)
else:
term.add_horaire(value["delaipassage"], value["type"])
found = True
if not found :
newLine = Ligne(transport)
newterm = Terminus(value["direction"])
newterm.add_horaire(value["delaipassage"], value["type"])
newLine.add_terminus(newterm)
lines.append(newLine)
for line in lines:
if len(subCmd) == 2:
if line.get_name() != "".join(subCmd[1].split()).upper():
continue
self.log.info("Ligne " + line.get_name())
respText += "#### Ligne " + line.get_name() + "\n"
terms = line.get_all_terminus()
for t in terms:
self.log.info(t.get_name())
if t.get_name() == nomArret:
continue
if t.get_name() is not None:
respText += "***Direction " + t.get_name()
else:
respText += "***Direction ?"
respText += "</ul>"
await evt.respond(respText, allow_html=True)
if t.get_estimated() == True:
respText += " (E)***\n"
else:
respText += " (T)***\n"
hs = t.get_horaires()
hs.sort()
for idx, h in enumerate(hs):
self.log.info(h)
if h == 0:
respText += "- Proche\n"
else:
respText += "- " + str(h) + " min\n"
if idx == 2: ##On limite à 3 items
break
respText += "\n"
await evt.respond(respText)
else:
await evt.respond(self.help_msg())
@classmethod

1
tcl_sytral.tclarret.json Normal file

File diff suppressed because one or more lines are too long