# coding: utf8 import simplematrixbotlib as botlib import random import re import copy import configparser import signal import sys import pickle import threading import asyncio import nio from datetime import datetime,timedelta import requests from oauthlib.oauth2 import BackendApplicationClient from requests_oauthlib import OAuth2Session from requests.auth import HTTPBasicAuth import html2text import json # Var bot = None PREFIX = '!' USERNAME = "" RTE_ID = None # Bot's RTE ID RTE_SECRET = None # Bot's RTE SECRET #ecowatt_url = 'https://digital.iservices.rte-france.com/open_api/ecowatt/v4/sandbox/signals' ecowatt_url = 'https://digital.iservices.rte-france.com/open_api/ecowatt/v4/signals' commune_url = 'https://geo.api.gouv.fr/communes?=&fields=nom,code,codesPostaux,population&format=json' eau_url = 'https://hubeau.eaufrance.fr/api/vbeta/qualite_eau_potable/resultats_dis?=&size=5' wattobj = None # Listes et dictionnaires admins = [] # Admins du bot modos = {} # Moderateurs des salons modules = {} # Modules activés par salon prive = {} # Les espaces de message privés du bot avec les utilisateurs liste_mod = [] # Modules disponibles citations = {} #addquote bieres = {} # Boissons a offrir salons = {} # liste de salons recommandés welcome = {} # Messages d'accueil des salons clock = {} # horloges pbta paquets = {} # paquets de cartes des salons stats = {} # Statistiques sur les messages cartes_base = ["As de carreau", "2 de carreau", "3 de carreau", "4 de carreau", "5 de carreau", "6 de carreau", \ "7 de carreau", "8 de carreau", "9 de carreau", "10 de carreau", "Valet de carreau", "Dame de carreau", \ "Roi de carreau", "As de coeur", "2 de coeur", "3 de coeur", "4 de coeur", "5 de coeur", "6 de coeur", \ "7 de coeur", "8 de coeur", "9 de coeur", "10 de coeur", "Valet de coeur", "Dame de coeur", "Roi de coeur", \ "As de pique", "2 de pique", "3 de pique", "4 de pique", "5 de pique", "6 de pique", "7 de pique", "8 de pique", \ "9 de pique", "10 de pique", "Valet de pique", "Dame de pique", "Roi de pique", "As de trefle", "2 de trefle", \ "3 de trefle", "4 de trefle", "5 de trefle", "6 de trefle", "7 de trefle", "8 de trefle", "9 de trefle", \ "10 de trefle", "Valet de trefle", "Dame de trefle", "Roi de trefle", "Joker rouge", "Joker noir"] # Connexion du bot config = configparser.ConfigParser() config.read('asmodee.ini') USERNAME = "" # Bot's username PASSWORD = "" # Bot's password SERVER = "" # Matrix server URL mods = ["roll", "quote", "biere", "stats", "liste", "horloge", "carte", "card", "cristal", "welcome", "salut", "jdr", "gens", "va", "salon", "kick", "mails", "titre", "invidious"] if ('AUTH' in config): USERNAME = config['AUTH']['username'] # Bot's username PASSWORD = config['AUTH']['password'] # Bot's password SERVER = config['AUTH']['server'] # Matrix server URL admins = config['AUTH']['admin'].split(",") # Admins du bot @admin1:host.tld,@admin2:host.tld,... else: print("Probleme de lecture de configuration asmodee.ini") # Create an instance of the MatrixBotAPI creds = botlib.Creds(SERVER, USERNAME, PASSWORD) bot = botlib.Bot(creds) # Chargement des données persistantes def horloge_read(): global clock try: with open("horloge", "rb") as fichier: loader = pickle.Unpickler(fichier) clock = loader.load() except: clock = {} def citations_read(): global citations try: with open("citations", "rb") as fichier: loader = pickle.Unpickler(fichier) citations = loader.load() except: citations = {} def bieres_read(): global bieres try: with open("bieres", "rb") as fichier: loader = pickle.Unpickler(fichier) bieres = loader.load() except: bieres = {} def salons_read(): global salons try: with open("salons", "rb") as fichier: loader = pickle.Unpickler(fichier) salons = loader.load() except: salons = {} def welcome_read(): global welcome try: with open("welcome", "rb") as fichier: loader = pickle.Unpickler(fichier) welcome = loader.load() except: welcome = {} def modos_read(): global modos try: with open("moderateurs", "rb") as fichier: loader = pickle.Unpickler(fichier) modos = loader.load() except: modos = {} def modules_read(): global modules try: with open("modules", "rb") as fichier: loader = pickle.Unpickler(fichier) modules = loader.load() except: modules = {} def prive_read(): global prive try: with open("prive", "rb") as fichier: loader = pickle.Unpickler(fichier) prive = loader.load() except: prive = {} def paquets_read(): global cartes try: with open("paquets", "rb") as fichier: loader = pickle.Unpickler(fichier) paquets = loader.load() except: paquets = {} def stats_read(): global stats try: with open("stats", "rb") as fichier: loader = pickle.Unpickler(fichier) stats = loader.load() except: stats = {} def save_obj(room=None, message=None): with open("moderateurs", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(modos) with open("modules", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(modules) with open("prive", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(prive) if ('horloge' in liste_mod): with open("horloge", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(clock) if ('quote' in liste_mod): #with open("quotes", "wb") as fichier: # saver = pickle.Pickler(fichier) # saver.dump(quotes) with open("citations", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(citations) if ('biere' in liste_mod): with open("bieres", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(bieres) if ('salon' in liste_mod): with open("salons", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(salons) if ('welcome' in liste_mod): with open("welcome", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(welcome) if ('cartes' in liste_mod): with open("paquets", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(paquets) if ('stats' in liste_mod): with open("stats", "wb") as fichier: saver = pickle.Pickler(fichier) saver.dump(stats) def signal_handler(signal, frame): # Sauvegarder les données persistantes avant sortie save_obj(None,None) sys.exit(0) class Wattobject: # Cache du service ecowatt def __init__(self): self.jour = 19000101 self.heure = 0 self.signals = None class Userstats: #Pour garder des stats sur les users def __init__(self,room,user,nick): self.room = room self.user = user self.nick = nick.strip() if nick and nick != None else "" self.date = 0 self.mess = 0 self.char = 0 class Parser: #Pour parser la ligne de commande def __init__(self, str, nick, room): self._str = str.strip() self._nick = nick self._old = "" self._mtch = "" self._room = room self._arg = {} self._option = [False,False,False,0,0,0,0,0,False,0,0,False] @property def str(self): return self._str @str.setter def str(self, str): self._str = str @property def nick(self): return self._nick @nick.setter def nick(self, nick): self._nick = nick @property def old(self): return self._old @old.setter def old(self, old): self._old = old @property def mtch(self): return self._mtch @mtch.setter def mtch(self, mtch): self._mtch = mtch @property def room(self): return self._room @room.setter def room(self, room): self._room = room @property def arg(self): return self._arg @arg.setter def arg(self, arg): self._arg = arg @property def option(self): return self._option @option.setter def option(self, option): self._option = option def space(self): if (re.match("^\s", self._str) or re.match("^$", self._str)): return True else: return False def restaure(self): self._str += self._mtch self._old def eat(self,mtch,opt): pattern=r"^(\s*)(" + mtch + r")(.*)" if (re.match(pattern,self._str)): if (opt == 1): self._mtch = re.sub(pattern,r"\2",self._str) self._old += re.sub(pattern,r"\1\2",self._str) self._str = re.sub(pattern,r"\3",self._str) return True return False def roll(result,type,explosif,nb,f,noadd,ars,relance,mitige): # Lancement d'un dé # verif type et contenu params? roll = 0 new = 0 moins = 0 if (ars): roll = 1 if (type > 1): tmp = 1 while (ars and tmp == 1): roll *= 2 tmp = random.randrange(1,type+1) roll = ((roll//2)*tmp) else: tmp = random.randrange(1,type+1) roll += int(tmp) #print("roll " + str(roll)) while (explosif and tmp == type): tmp = random.randrange(1,type+1) roll += int(tmp) if (relance != 0 and relance != 1 and relance <= roll): new = 1 if (mitige != 0 and mitige >= roll): moins = 1 result += (' ' if nb>0 else '') + str(roll) if (f != 0 and roll < f): roll = 0 elif (f != 0 and roll >= f and noadd): tmp = int(roll//type) roll = tmp + ((roll - tmp*type) >= 1 if f else 0) roll -= moins #print("fin roll " + str(result) + " " + str(roll) + " " + str(new)) return (result,roll,new) def rolls(result,jet,type,nb,explosif,noadd,wild,f,g,ars,relance,mitige,z): # Lancement d'un groupe de dés y = 0 total = 0 allresult = [] if (nb > 100): nb = 100 tmp=(type and nb) if (tmp): jet += str(nb)+"d"+str(type) #print(jet) for i in range(nb): new = 0 # Star Wars if (z == True and i == 0): result, res1, new = roll(result,type,True,nb,f,noadd,ars,relance,mitige) allresult.append(res1) if (res1 == 1): y = 1 # Autre else: result, res1, new = roll(result,type,explosif,nb,f,noadd,ars,relance,mitige) allresult.append(res1) # Tant qu'il faut relancer while (new == 1): result, res1, new = roll(result,type,explosif,nb,f,noadd,ars,relance,mitige) allresult.append(res1) # Wild die de Savage Worlds if (wild != 0): jet += "w" + str(wild) result, res1, new = roll(result,wild,wild!=1,nb if nb else 0,f,noadd,ars,relance,mitige) allresult.append(res1) result += 'w' #print(allresult) allresult.sort(reverse=True) # 1 au de joker de Star Wars if (y == 1): del allresult[-1] del allresult[0] for i in range((len(allresult)) if (g == 0 and ((f != 0 and noadd) or not noadd)) else (0 if (noadd and f == 0) else g)): if (g == 0 or len(allresult) >= g): total += allresult[i] if allresult[i] else 0 if (noadd and f == 0): total += max(allresult) #print("total : " + str(total)) jet += (("g" + str(g)) if g != 0 else "#g") if g != parser.option[5] else (("g" + str(g)) if g != 0 else "") jet += (("f" + str(f)) if f != 0 else "#f") if f != parser.option[4] else (("f" + str(f)) if f != 0 else "") jet += (("r" + str(relance)) if relance != 0 else "#r") if relance != parser.option[9] else (("r" + str(relance)) if relance != 0 else "") jet += (("m" + str(mitige)) if mitige != 0 else "#m") if mitige != parser.option[9] else (("m" + str(mitige)) if mitige != 0 else "") if (tmp): jet += ("e" if explosif == True else "#e") if explosif != parser.option[0] else "" jet += ("n" if noadd == True else "#n") if noadd != parser.option[1] else "" jet += ("a" if ars == True else "#a") if ars != parser.option[8] else "" #print("fin rolls : " + str(result) + "|" + str(total) + "|" + str(jet)) return (result,total,jet) async def entryPoint(room, message): # Analyse des commandes ":", point d'entrée pour les jets de dés global modules try: rmod = modules[room.room_id, 'roll'] except: modules[room.room_id, 'roll'] = False if (modules[room.room_id, 'roll']): global parser text = getMessage(message) user = getUser(message) nick = getNick(room,message) parser = Parser(text,nick,room) if (parser.eat(":roll",1)): parser.option = [False,False,False,0,0,0,0,0,False,0,0,False] await rollXPoint() elif (parser.eat(":dom",1)): parser.option = [True,False,True,0,0,0,4,4,False,0,0,False] await rollXPoint() elif (parser.eat(":sw",1)): parser.option = [True,True,True,0,0,0,4,4,False,0,0,False] await rollXPoint() elif (parser.eat(":ars",1)): parser.option = [False,True,True,0,0,0,0,0,True,0,0,False] await rollXPoint() elif (parser.eat(":des",1)): parser.option = [False,True,True,0,10,0,0,0,False,0,0,False] await rollXPoint() elif (parser.eat(":wod",1)): parser.option = [False,True,True,0,8,0,0,0,False,10,0,False] await rollXPoint() elif (parser.eat(":adv",1)): parser.option = [False,True,False,0,5,0,0,0,False,0,0,False] await rollXPoint() elif (parser.eat(":owod",1)): parser.option = [False,True,True,0,6,0,0,0,False,10,1,False] await rollXPoint() elif (parser.eat(":star",1)): parser.option = [False,False,True,0,0,0,0,0,False,0,0,True] await rollXPoint() elif (parser.eat(":fate",1)): text = text[5:] + " 4d3-8" parser = Parser(text,nick,room) parser.option = [False,False,False,0,0,0,0,0,False,0,0,False] await rollXPoint() else: parser.arg["error"] = True if (not parser.arg.get("error",None) and not parser.eat("$",0)): parser.arg["noerror"] = True await msg(room,"Je n'ai pas compris " + text,user) def rollOptionPoint(): # Parse des options global parser while (True): if (parser.eat("[Ee]",1)): parser.option[0] = True elif (parser.eat("#[Ee]",1)): parser.option[0] = False elif (parser.eat("[Nn]",1)): parser.option[1] = True elif (parser.eat("#[Nn]",1)): parser.option[1] = False elif (parser.eat("[Vv]",1)): parser.option[2] = True elif (parser.eat("#[Vv]",1)): parser.option[2] = False elif (parser.eat("[Ww]",1)): if (parser.space()): parser.option[3] = 6 elif (parser.eat(r"\d+",1)): parser.option[3] = int(parser.mtch) else: parser.option[3] = 6 elif (parser.eat("#[Ww]",1)): parser.option[3] = 0 elif (parser.eat("[Ff]",1)): if (parser.space()): parser.option[4] = 6 elif (parser.eat(r"\d+",1)): parser.option[4] = int(parser.mtch) else: parser.option[4] = 6 elif (parser.eat("#[Ff]",1)): parser.option[4] = 0 elif (parser.eat("[Gg]",1)): if (parser.space()): parser.option[5] = 6 elif (parser.eat(r"\d+",1)): parser.option[5] = int(parser.mtch) else: parser.option[5] = 6 elif (parser.eat("#[Gg]",1)): parser.option[5] = 0 elif (parser.eat("[Ss]",1)): if (parser.space()): parser.option[6] = 4 elif (parser.eat(r"\d+",1)): parser.option[6] = int(parser.mtch) else: parser.option[6] = 4 if (parser.eat("[/]",1)): if (parser.space()): parser.option[7] = 4 elif (parser.eat(r"\d+",1)): parser.option[7] = int(parser.mtch) else: parser.option[7] = 4 else: parser.option[7] = 4 elif (parser.eat("#[Ss]",1)): parser.option[6] = 0 parser.option[7] = 0 elif (parser.eat("[Aa]",1)): parser.option[8] = True elif (parser.eat("#[Aa]",1)): parser.option[8] = False elif (parser.eat("[Rr]",1)): if (parser.space()): parser.option[9] = 10 elif (parser.eat(r"\d+",1)): parser.option[9] = int(parser.mtch) else: parser.option[9] = 10 elif (parser.eat("#[Rr]",1)): parser.option[9] = 0 elif (parser.eat("[Mm]",1)): if (parser.space()): parser.option[10] = 1 elif (parser.eat(r"\d+",1)): parser.option[10] = int(parser.mtch) else: parser.option[10] = 1 elif (parser.eat("#[Mm]",1)): parser.option[10] = 0 elif (parser.eat("[Zz]",1)): parser.option[11] = True elif (parser.eat("#[Zz]",1)): parser.option[11] = False else: break def dupli(orig): # Duplication d'un parser salon = orig.room orig.room = None nouv = copy.deepcopy(orig) nouv.option = [orig.option[0],orig.option[1],orig.option[2],orig.option[3],orig.option[4],orig.option[5],orig.option[6],orig.option[7],orig.option[8],orig.option[9],orig.option[10],orig.option[11]] orig.room = salon nouv.room = salon return nouv async def rollXPoint(): # Parser le nombre de lancers de dés identiques global parser await rollPlusMoinsPoint() if (parser.eat("[xX]",1)): if (parser.eat(r"\d+",1)): tmp = dupli(parser) str = parser.arg["jet"] xtime = int(parser.mtch)-1 xtime = xtime if (xtime < 11) else 10 for _ in range(xtime): parser = dupli(parser) parser.str = str #print (parser.str) await rollPlusMoinsPoint() parser = tmp else: parser.arg["error"] = True async def rollPlusMoinsPoint(): # Gérer les bloc du jet séparés par les + et -, afficher le résultat global parser parser.arg["roll_sig"] = True parser.arg["error"] = None result = "" res1 = "" res2 = "" jet = "" rollOptionPoint() #print(parser.option) exp,noa,ver,will,f,g,s,d,ars,r,m,z = parser.option rollEntityPoint() #print("de " + str(parser.arg.get("roll_nb",None)) + "|" + str(parser.arg.get("roll_typ",None))) if (not parser.arg["error"]): if (not parser.arg.get("roll_sig",True)): jet += "-" result += "-" if (parser.arg.get("roll_typ",None) or parser.arg.get("roll_wil",None)): result += "(" exp2,noa2,ver2,will2,f2,g2,s2,d2,ars2,r2,m2,z2 = parser.option parser.option = [exp,noa,ver,will,f,g,s,d,ars,r,m,z] result, res1, jet = rolls(result,jet,parser.arg.get("roll_typ",None),parser.arg.get("roll_nb",None),exp2,noa2,will2,f2,g2,ars2,r2,m2,z2) result += " = " + str(res1) + ")" else: jet += str(parser.arg.get("roll_nb",None)) result += str(parser.arg.get("roll_nb",None)) res1 = parser.arg["roll_nb"] #print("prem " + result + " " +str(res1)) if (not parser.arg.get("roll_sig",True)): res1 = -res1 while (parser.eat("[+-]",1)): parser.arg["roll_sig"] = True if (parser.mtch == "-"): parser.arg["roll_sig"] = not parser.arg.get("roll_sig",True) rollEntityPoint() if (not parser.arg.get("error",None)): jet += " +" if parser.arg.get("roll_sig",True) else " -" result += " + " if parser.arg.get("roll_sig",True) else " - " if (parser.arg.get("roll_typ",None) or parser.arg.get("roll_wil",None)): result += "(" exp2,noa2,ver2,will2,f2,g2,s2,d2,ars2,r2,m2,z2 = parser.option parser.option = [exp,noa,ver,will,f,g,s,d,ars,r,m,z] result, res2, jet = rolls(result,jet,parser.arg.get("roll_typ",None),parser.arg.get("roll_nb",None),exp2,noa2,will2,f2,g2,ars2,r2,m2,z2) result += " = " + str(res2) + ")" else: jet += str(parser.arg.get("roll_nb",None)) result += str(parser.arg.get("roll_nb",None)) res2 = parser.arg.get("roll_nb",None) res1 += res2 if parser.arg.get("roll_sig",None) else -res2 #print("deux " + result + " " +str(res1)) if (res1): if (ver): result = jet + " = (" + result + ") = " + str(res1) else: result = jet + " = " + str(res1) if (d <= 0): d=1 tmp = (res1 - s) // d + 1 result += ("/" + ("0" if (tmp < 0) else str(tmp))) if (s != 0) else "" parser.arg["jet"] = jet await msg(parser.room,parser.nick + " rolls " + ("e" if exp else "") + ("n" if noa else "") + ("v" if ver else "") + ("a" if ars else "") + ("s"+str(s)+"/"+str(d) if (s != 0) else "") + (" " if (exp or noa or ver or s != 0) else "") + result, "dice") elif (not parser.arg.get("noerror",False)): await msg(parser.room,"match = " + parser.mtch + "\nstr = " + parser.str, "dice") await msg(parser.room,"Rien compris. Essayez '!help' pour obtenir de l'aide.", "dice") def rollEntityPoint(): # Parser les séparateurs de bloc + et - global parser if (parser.eat("[-+]", 1)): if (parser.mtch == "-"): parser.arg["roll_sig"] = not parser.arg.get("roll_sig",True) rollOptionPoint() rollNbPoint() def rollNbPoint(): # Parser le nombre de dés global parser parser.arg["roll_nb"] = None if (parser.eat(r"\d+",1)): parser.arg["roll_nb"] = int(parser.mtch) #print("nb " + str(parser.arg.get("roll_nb",1))) rollDPoint() def rollDPoint(): # Parser le mot clé identifiant un dé global parser if (parser.eat("[dD]",1)): if (not parser.arg.get("roll_nb",False)): parser.arg["roll_nb"] = 1 parser.arg["roll_bon"] = 0 rollTypePoint() elif (parser.arg.get("roll_nb",False)): parser.arg["roll_typ"] = None else: parser.arg["error"] = True def rollTypePoint(): # Parser le nombre de faces du dé global parser if (parser.space()): parser.arg["roll_typ"] = 6 elif (parser.eat(r"\d+",1)): parser.arg["roll_typ"] = int(parser.mtch) if (parser.mtch == "1"): parser.option[0] = False else: parser.arg["roll_typ"] = 6 rollOptionPoint() if (not parser.arg.get("roll_nb",False)): parser.arg["error"] = True def getMessage(message): try: return(str(message).split(":",2)[2].strip()) except: return(str(message)) def getUser(message): match = re.search(r"^(@\w+:[^ :]+)", str(message)) if match: return str(match.group()) else: return "personne" def getNick(room, message): # Obtenir le DisplayName à partir du mxid. sender = getUser(message) nick = None try: nick = room.user_name(sender).split(' ')[0] except: nick = room.user_name(sender) return(nick) async def msg(room,mess,sender,content=False): try: try: lmod = modos.get(room.room_id) if (sender not in admins and lmod != None and sender not in lmod): mess = mess.replace('@room', 'tout le monde') except: try: mess = mess.replace('@room', 'tout le monde') except: print(mess) print("id : " + str(room.room_id) + " message : " + str(mess)) if (content): await bot.api.send_markdown_message(room.room_id, mess) else: await bot.api.send_text_message(room.room_id, mess) except: print("Impossible d'envoyer le message") async def modo(room,message): # Definition d'un moderateur global modos sender = getUser(message) texte = getMessage(message) print("texte : " + texte + " sender : " + sender) lmod = [] try: lmod = modos.get(room.room_id) except: lmod = [] if (sender in admins or sender in lmod or sender == bot.client.user_id): args = texte.split() args.pop(0) if (len(args) > 1 and args[0] == "add"): args.pop(0) candidat = " ".join(args) if (not candidat in lmod): lmod.append(candidat) modos[room.room_id] = lmod await msg(room,candidat + " devient moderateur.",sender) else: await msg(room,candidat + " est déjà moderateur.",sender) elif (len(args) > 1 and args[0] == "del"): args.pop(0) candidat = " ".join(args) if (candidat in lmod): place = lmod.index(candidat) del lmod[place] modos[room.room_id] = lmod await msg(room,candidat + " n'est plus moderateur.",sender) else: await msg(room,candidat + " n'est pas moderateur.",sender) else: await msg(room,"\n".join(lmod),sender) else: await msg(room,"Vous n'êtes pas autorisés à définir les modérateurs.",sender) async def module(room,message): # Definition des modules d'un salon lmod = [] sender = getUser(message) texte = getMessage(message) try: lmod = modos.get(room.room_id) except: lmod = [] if (sender in admins or sender in lmod or sender == bot.client.user_id): global modules args = texte.split() args.pop(0) if (len(args) == 2 and args[0] == "add"): args.pop(0) rmod = args[0] if (rmod in liste_mod): modules[room.room_id, rmod] = True await msg(room,"Module : " + rmod + " activé.",sender) else: await msg(room,"Module : " + rmod + " inconnu.",sender) elif (len(args) == 2 and args[0] == "del"): args.pop(0) rmod = args[0] if (rmod in liste_mod): modules[room.room_id, rmod] = False await msg(room,"Module : " + rmod + " désactivé.",sender) else: await msg(room,"Module : " + rmod + " inconnu.",sender) else: # Lister les modules actifs du salon rmod = "" for cle,valeur in modules.items(): if (cle[0] == room.room_id and valeur == True): rmod = rmod + cle[1] + ", " if (len(rmod) > 1): rmod = rmod[:-2] await msg(room,"Modules actuels : " + rmod,sender) # Lister les modules disponibles dmod = "" for val in liste_mod: dmod = dmod + val + ", " if (len(dmod) > 1): dmod = dmod[:-2] await msg(room,"Modules disponibles : " + dmod,sender) else: await msg(room,"Vous n'êtes pas autorisés à définir les modules du salon.",sender) async def liste(room, message): # Afficher un élement aléatoire d'une liste fournie global modules try: rmod = modules[room.room_id, 'liste'] except: modules[room.room_id, 'liste'] = False if (modules[room.room_id, 'liste']): res = [] nick = getNick(room,message) args = getMessage(message).split() args.pop(0) try: nb = int(args[len(args)-1]) args.pop(len(args)-1) except: nb = 1 args = ' '.join(args) list = args.split('/') if (nb <= len(list)): for i in range(nb): id = random.randrange(0,len(list)) res.append(list.pop(id)) await msg(room,nick + " obtient :\n" + '\n'.join(res),nick) else: await msg(room,"Utilisation : !liste [nombre d elements]",nick) async def aff_hor(room, hor, valeur): # affichage des horloges if (int(valeur) == 0): await msg(room,hor + " : " + chr(128320) + "\n", "horloge") elif (int(valeur) == 1): await msg(room,hor + " : " + chr(128338) + "\n", "horloge") elif (int(valeur) == 2): await msg(room,hor + " : " + chr(128341) + "\n", "horloge") elif (int(valeur) == 3): await msg(room,hor + " : " + chr(128344) + "\n", "horloge") elif (int(valeur) == 4): await msg(room,hor + " : " + chr(128345) + "\n", "horloge") elif (int(valeur) == 5): await msg(room,hor + " : " + chr(128346) + "\n", "horloge") elif (int(valeur) == 6): await msg(room,hor + " : " + chr(128347) + "\n", "horloge") else: await msg(room,hor + " : " + str(valeur) + " \n", "horloge") async def horloge(room, message): # Gestion des horloges PBTA global modules try: rmod = modules[room.room_id, 'horloge'] except: modules[room.room_id, 'horloge'] = False if (modules[room.room_id, 'horloge']): global clock nick = getNick(room,message) args = getMessage(message).split() args.pop(0) if (len(args) == 0): # Liste des horloges du salon for cle,valeur in clock.items(): if (cle[0] == room.room_id): await aff_hor(room, cle[1], valeur) elif (len(args) >= 2 and args[len(args)-1].isnumeric()): # Place le niveau de l'horloge entre 0 et 6 nv = int(args[len(args)-1]) clock[room.room_id, ' '.join(args[0:-1])] = nv elif (len(args) >= 2 and (args[len(args)-1][:1] == "+" or args[len(args)-1][:1] == "-")): nv = 0 hor = ' '.join(args[0:-1]) if ((room.room_id, hor) in clock): nv = clock[room.room_id, hor] val = 0 if (args[len(args)-1][1:].isnumeric()): val = int(args[len(args)-1][1:]) if (args[len(args)-1][:1] == "+"): nv = nv + val if (nv > 6): nv = 6 else: nv = nv - val if (nv < 0): nv = 0 clock[room.room_id, hor] = nv await aff_hor(room, hor, nv) elif (len(args) >= 2 and args[0] == "del"): # Supprime une horloge args.pop(0) del clock[room.room_id, ' '.join(args)] else: await msg(room,"Utilisation : \n- !horloge : Affiche les horloges. \n- !horloge : Place ou crée l'horloge au niveau spécifié.\n- !horloge del : Supprime l'horloge.",getUser(message)) async def reponses(room, phrases, content=False): # Afficher une réponse aléatoire dans la liste i = random.randrange(0,len(phrases)) await msg(room,phrases[i],"reponses",content) async def verifPMRoom(room, message): # Pour obtenir ou créer un salon pour les messages privés avec l'utilisateur global prive nick = "" sender = "" sender = getUser(message) nick = getNick(room, message) client_id = bot.creds.username.split(':')[0].split('@')[1] client_host = bot.creds.username.split(':')[1] room_nick = client_id + "_" + nick bot_nick = getNick(room, message) salon = None room_id = prive.get(sender) if (room_id): await bot.async_client.room_invite(room_id=room_id, user_id=sender) new_salon = nio.rooms.MatrixRoom(room_id, client_id) new_salon.name=bot_nick new_salon.topic="Informations d'Asmodee" new_salon.is_direct=True return(new_salon) else: salon = await bot.async_client.room_create(alias=room_nick, name=bot_nick, topic="Informations d'Asmodee",is_direct=True,invite=[sender]) if isinstance(salon, nio.responses.RoomCreateError): print("Impossible de creer : " + room_nick + " pour " + sender) return(room) else: prive[sender]=salon.room_id return(salon) #TODO : room_delete_alias(access_token, room_alias) async def biere(room,message): # Gestion des boissons global modules try: rmod = modules[room.room_id, 'biere'] except: modules[room.room_id, 'biere'] = False power = 0 if (modules[room.room_id, 'biere']): sender = getUser(message) mess = getMessage(message) lmod = modos.get(room.room_id) if (sender in admins or sender in lmod): power = 1 global bieres args = mess.split() args.pop(0) breuvages = {} give = False elu = "" envoyeur = getNick(room, message) try: breuvages = bieres[room.room_id] except: breuvages = {} if (len(args) > 1 and args[0] == "give"): give = True args.pop(0) submit = " ".join(args).split(":") elu = submit[0] if (power == 0): elu = elu.replace('@room', 'tout le monde') try: args = submit[1].split() except: args = "" if (len(args) > 2 and args[0] == "add"): #ajoute une biere args.pop(0) submit = " ".join(args).split(":") if (len(submit) > 1): # Ajout de la citation nick = submit[0].strip() nick = nick.replace('@room', 'tous') submit.pop(0) citation = ":".join(submit) citation = citation.replace('@room', 'tout le monde') tps = datetime.now().microsecond breuvages[nick,tps] = citation bieres[room.room_id] = breuvages await msg(room,"Ajout du breuvage " + nick + ":" + citation,sender) else: # message d'aide await msg(room,"!biere add :",sender) elif (len(args) > 0 and args[0] == "list"): # liste les quotes args.pop(0) salon = await verifPMRoom(room,message) print(salon) if (len(args) == 0): # Liste les breuvages du salon reponse = "Voici les reponses du salon " + room.room_id + "\n" alias = None if room.name: alias = room.name elif room.canonical_alias: alias = room.canonical_alias elif room.names: alias = room.names[0] else: alias = "" reponse = reponse + "(alias : " + alias + ")\n" for cle,valeur in breuvages.items(): reponse = reponse + cle[0] + " / " + str(cle[1]) + " : " + valeur + "\n" if (len(reponse) > 500): await msg(salon,reponse,sender) reponse = "" await msg(salon,reponse,sender) elif (args[0] == "all"): # tous les breuvages de tous les salons reponse = "Les breuvages de tous les salons : " + "\n" await msg(salon,reponse,sender) for rid,fame in bieres.items(): reponse = "Voici les reponses du salon " + rid + "\n" for cle,valeur in fame.items(): reponse = reponse + cle[0] + " / " + str(cle[1]) + " : " + valeur + "\n" if (len(reponse) > 500): await msg(salon,reponse,sender) reponse = "" await msg(salon,reponse,sender) else: # les breuvages du pseudo spécifié nick = " ".join(args) reponse = "Voici les reponses du breuvage " + nick + "\n" for cle,valeur in breuvages.items(): if (cle[0] == nick): reponse = reponse + cle[0] + " / " + str(cle[1]) + " : " + valeur + "\n" await msg(salon,reponse,sender) elif (len(args) > 1 and args[0] == "del"): salon = await verifPMRoom(room,message) lmod = modos.get(room.room_id) if (sender in admins): id = args[1] reponse = "Voici le breuvage supprimé : \n" for rid,fame in bieres.items(): for cle,valeur in fame.items(): if (str(cle[1]) == id): del fame[cle[0],cle[1]] reponse = reponse + rid + " / " + cle[0] + " / " + str(cle[1]) + " : " + valeur + "\n" break await msg(salon,reponse,sender) elif (sender in lmod): id = args[1] reponse = "Voici le breuvage supprimé : \n" rid = room.room_id fame = bieres[rid] for cle,valeur in fame.items(): if (str(cle[1]) == id): del fame[cle[0],cle[1]] reponse = reponse + rid + " / " + cle[0] + " / " + str(cle[1]) + " : " + valeur + "\n" break await msg(salon,reponse,sender) else: await msg(salon,"Vous n'êtes pas autorisés à supprimer des breuvages.",sender) elif (len(args) > 0): # cite une reponse d'un breuvage precis nick = " ".join(args) phrases = [] for cle,valeur in breuvages.items(): if (cle[0] == nick): if (give): phrases.append(valeur + " pour " + elu + " de la part de " + envoyeur) else: phrases.append(valeur + " pour " + envoyeur) if (len(phrases) > 0 ): await reponses(room,phrases) else: await msg(room,"Je n'ai pas de " + nick + " en stock!",sender) else: # cite une réponse d'un breuvage aleatoire phrases = [] for cle,valeur in breuvages.items(): if (give): phrases.append(valeur + " pour " + elu + " de la part de " + envoyeur) else: phrases.append(valeur + " pour " + envoyeur) if (len(phrases) > 0 ): await reponses(room,phrases) else: await msg(room,"Je n'ai pas de breuvages pour ce salon",sender) async def boissons(room,message): # Gestion des alias de boissons global modules try: rmod = modules[room.room_id, 'biere'] except: modules[room.room_id, 'biere'] = False if (modules[room.room_id, 'biere']): sender = getUser(message) mess = getMessage(message) boisson = "" elu = "" args = mess.split() try: boisson = args[0][1:] except: boisson = "" args.pop(0) if (len(args) > 0): elu = " ".join(args) if (len(elu) > 0 and len(boisson) > 0): mess = "!biere give " + elu + ":" + boisson elif (len(elu) > 0): mess = "!biere give " + elu elif (len(boisson) > 0): mess = "!biere " + boisson else: mess = "!biere" message = sender + " : " + mess await biere(room,message) async def salon(room,message): # Gestion des listes de salons recommandes global modules try: rmod = modules[room.room_id, 'salon'] except: modules[room.room_id, 'salon'] = False if (modules[room.room_id, 'salon']): sender = getUser(message) mess = getMessage(message) global salons args = mess.split() args.pop(0) famous = {} try: famous = salons[room.room_id] except: famous = {} if (len(args) > 3 and args[0] == "add"): #ajoute un salon recommande ref = "" desc = "" args.pop(0) if (args[0] == "desc"): args.pop(0) ref = "desc" desc = " ".join(args) else: ref = args[0] args.pop(0) desc = " ".join(args) famous[ref] = desc salons[room.room_id] = famous await msg(room,"Ajout du salon " + ref + " : " + desc,sender) elif (len(args) > 1 and args[0] == "del"): salon = await verifPMRoom(room,message) lmod = modos.get(room.room_id) if (sender in admins): id = args[1] reponse = "Voici le salon supprimé : \n" rid = room.room_id fame = salons[rid] for cle,valeur in fame.items(): if (str(cle) == id): del fame[cle] reponse = reponse + rid + " / " + cle + " : " + valeur + "\n" break await msg(room,reponse,sender) elif (sender in lmod): id = args[1] reponse = "Voici le salon supprimé : \n" rid = room.room_id fame = salons[rid] for cle,valeur in fame.items(): if (str(cle) == id): del fame[cle] reponse = reponse + rid + " / " + cle + " : " + valeur + "\n" break await msg(room,reponse,sender) else: await msg(salon,"Vous n'êtes pas autorisés à supprimer des salons.",sender) elif (len(args) > 0): # cite un salon precis ref = args[0] trouve = 0 for cle,valeur in famous.items(): if (cle == ref): await msg(salon,cle + " : " + valeur,sender) trouve = 1 break if (trouve == 0): await msg(room,"Je n'ai pas de salons nomme " + ref,sender) else: # cite tous les salons reponse = "" trouve = 0 if ("desc" in famous): reponse = reponse + famous["desc"] + "\n" for cle,valeur in famous.items(): if (cle != "desc"): reponse = reponse + cle + " : " + valeur + "\n" trouve = 1 if (trouve == 0): await msg(room,"Je n'ai pas de salons recommandes pour ce salon",sender) else: await msg(room,reponse,sender) async def accueil(room,message): # Mettre un message d'accueil global modules try: rmod = modules[room.room_id, 'welcome'] except: modules[room.room_id, 'welcome'] = False if (modules[room.room_id, 'welcome']): sender = getUser(message) mess = getMessage(message) lmod = modos.get(room.room_id) if (sender in admins or sender in lmod): global welcome args = mess.split() args.pop(0) reponse = " ".join(args) if (len(args) > 0): welcome[room.room_id] = reponse await msg(room,"Le message d'accueil est désormais : " + reponse,sender) else: await msg(salon,"Vous n'êtes pas autorisés à modifier le message d'accueil.",sender) async def bienvenue(room,message): # Affichage d'un message d'accueil aux nouveaux venus global modules try: rmod = modules[room.room_id, 'welcome'] except: modules[room.room_id, 'welcome'] = False if (modules[room.room_id, 'welcome']): sender = message.sender nick = room.user_name(message.state_key) if room.user_name(message.state_key) else message.state_key membership = message.membership prev_member = message.prev_membership if room.name: alias = room.name elif room.canonical_alias: alias = room.canonical_alias elif room.names: alias = room.names[0] else: alias = "" reponse = "" try: reponse = welcome[room.room_id] except: reponse = "" if (membership == "join" and prev_member != "join"): await msg(room,"Bienvenue sur " + alias + ", " + nick + ". " + reponse,sender) elif (membership == "leave" and prev_member != "leave"): await msg(room,"Au revoir " + nick + "!",sender) else: try: print("current: " + membership + " prev: " + prev_member) except: print(message) async def titre(room, message): # cherche le titre d'une page global modules try: rmod = modules[room.room_id, 'titre'] except: modules[room.room_id, 'titre'] = False if (modules[room.room_id, 'titre']): args = getMessage(message).split() sender = getUser(message) args.pop(0) try: invidious = modules[room.room_id, 'invidious'] except: invidious = False try: url=args[0] print(url) if (re.search(r"^.*://",url) is None): url = "http://" + url r = requests.get(url) res = re.search(r"(.*)",r.text) if (res is not None): await msg(room,html2text.html2text(str(re.sub("", "", res.group()))),sender) else: await msg(room,"Titre non trouvé",sender) if (re.search(r"http[s]?://(www\.)?youtube\.",url) is not None and invidious is False): res = re.sub(r"^.*\?v=(\w+).*$", r"\1", url, 0, re.MULTILINE) await msg(room,str("https://invidious.fdn.fr/watch?v=" + res),sender) except: await msg(room,"URL invalide",sender) async def addquote(room,message): # enregistrer les citations mode reponses matrix global modules try: rmod = modules[room.room_id, 'quote'] except: modules[room.room_id, 'quote'] = False if (modules[room.room_id, 'quote']): global citations content = getMessage(message) sender = getUser(message) if len(content) > 42: # Récupération de l'auteur auteur = "Un nain connu" match = re.search(r"<(@\w+:\w+.\w+)>", content) if match: auteur = match.group(1) nick = room.user_name(auteur) # Enlève la commande de la citation try: content = content.replace("\n!addquote", " ") content = content.replace("\n!", "\n") content = content.replace("

!addquote

\n", "") content = content.replace("

!", "

") content = content.replace("<"+auteur+">",nick+" <"+auteur+">") except: print("erreur content " + content) # Id tps = datetime.now().microsecond # récupérations des citations du salon famous = {} try: famous = citations[room.room_id] except: famous = {} # enregistrement de la citation famous[auteur,tps] = content citations[room.room_id] = famous await bot.api.send_markdown_message(room_id=room.room_id,message="Ajout de la citation de " + nick + ":\n" + content) async def showquote(room, message): # afficher les citations mode reponse matrix global modules try: rmod = modules[room.room_id, 'quote'] except: modules[room.room_id, 'quote'] = False if (modules[room.room_id, 'quote']): args = getMessage(message).split() sender = getUser(message) args.pop(0) famous = {} try: famous = citations[room.room_id] except: famous = {} if (len(args) == 1): # cite une quote d'une personne precise nick = args[0] phrases = [] for cle,valeur in famous.items(): if (cle[0] == nick): phrases.append(valeur) if (len(phrases) > 0 ): await reponses(room,phrases,True) else: await msg(room,"Je n'ai pas de citations pour " + nick,sender) else: # cite une quote aleatoire phrases = [] for cle,valeur in famous.items(): phrases.append(valeur) if (len(phrases) > 0 ): await reponses(room,phrases,True) else: await msg(room,"Je n'ai pas de citations pour ce salon",sender) async def card(room, message): # Tirer une carte du paquet sans la retirer global modules try: rmod = modules[room.room_id, 'card'] except: modules[room.room_id, 'card'] = False if (modules[room.room_id, 'card']): reponse = cartes_base[random.randrange(0,len(cartes_base))] await msg(room,reponse,getUser(message)) async def carte(room, message): # Tirer une carte du paquet en la retirant ensuite global modules try: rmod = modules[room.room_id, 'carte'] except: modules[room.room_id, 'carte'] = False if (modules[room.room_id, 'carte']): global paquets sender = getUser(message) cartes = paquets.get(room.room_id) if (cartes is None): cartes = list(cartes_base) args = getMessage(message).split() if (len(args) > 1): cartes=list(cartes_base) await msg(room,"Le paquet est melange",sender) else: if (len(cartes) < 1): cartes=list(cartes_base) await msg(room,"Le paquet est melange",sender) i = random.randrange(0,len(cartes)) await msg(room,cartes[i],sender) cartes.pop(i) paquets[room.room_id]=cartes #async def last(room, message): # dernière connexion d'un utilisateur # global modules # try: # rmod = modules[room.room_id, 'stats'] # except: # modules[room.room_id, 'stats'] = False # if (modules[room.room_id, 'stats']): # args = getMessage(message).split() # sender = getUser(message) # args.pop(0) # print("analyse args " + str(args)) # if (len(args) == 1): # try: # print("into try") # target = room.users.get(args[0]) # print("get target") # if (target): # ago = target.last_active_ago # await msg(room,"d" + str(ago),sender) # else: # await msg(room,args[0] + " non trouvé.",sender) # except: # print(args[0]) # else: # await msg(room,"!last ",sender) async def last(room,message): # Regarde la dernière fois que quelqu'un a écrit un message global modules try: rmod = modules[room.room_id, 'stats'] except: modules[room.room_id, 'stats'] = False if (modules[room.room_id, 'stats']): global stats args = getMessage(message).split() sender = getUser(message) usrstats = None args.pop(0) pers = "" if (len(args) >= 1 and args[0] == "all"): max_sign = "+" max_duree = 0 if (len(args) > 1): max_sign = args[1][0] max_duree = int(args[1][1:]) ref_duree = datetime.now() - timedelta(days=max_duree) salon = await verifPMRoom(room,message) all_usr = {} reponse = "Les gens ayant posté à " + max_sign + " de " + str(max_duree) + " jours :\n" for cle,valeur in stats.items(): if (cle[0] == room.room_id): usrstats = stats[room.room_id,cle[1]] if ((usrstats.user in all_usr and all_usr[usrstats.user].date < usrstats.date) or not usrstats.user in all_usr): all_usr[usrstats.user] = usrstats for user,usrstats in all_usr.items(): if ((max_sign == "+" and usrstats.date < ref_duree) or ((max_sign == "-" and usrstats.date > ref_duree))): reponse += "- " + usrstats.nick + "(" + user + ")" + " le " + usrstats.date.strftime("%Y-%m-%d %H:%M:%S") + ")\n" await msg(salon, reponse,sender) elif (len(args) >= 1 and args[0] == "inactifs"): max_sign = "+" max_duree = 0 max_mess = 0 if (len(args) > 2): max_sign = args[1][0] max_duree = int(args[1][1:]) max_mess = int(args[2]) ref_duree = datetime.now() - timedelta(days=max_duree) salon = await verifPMRoom(room,message) all_usr = {} reponse = "Les gens ayant posté à " + max_sign + " de " + str(max_duree) + " jours et n'ayant pas plus de " + str(max_mess) + " messages :\n" for cle,valeur in stats.items(): if (cle[0] == room.room_id): usrstats = stats[room.room_id,cle[1]] if ((usrstats.user in all_usr and all_usr[usrstats.user].date < usrstats.date) or not usrstats.user in all_usr): all_usr[usrstats.user] = usrstats for user,usrstats in all_usr.items(): if (((max_sign == "+" and usrstats.date < ref_duree) or ((max_sign == "-" and usrstats.date > ref_duree))) and usrstats.mess <= max_mess): reponse += "- " + usrstats.nick + "(" + user + ")" + " le " + usrstats.date.strftime("%Y-%m-%d %H:%M:%S") + ")\n" await msg(salon, reponse, sender) else: if (len(args) == 0): await msg(room,"!last ",sender) else: pers=" ".join(args) id_pers=None try: usrstats = stats[room.room_id,pers] except: try: for cle,valeur in room.users.items(): if (valeur.display_name == pers): id_pers = valeur.user_id try: usrstats = stats[room.room_id, cle] except: usrstats = None if (usrstats is not None): break except: print(pers + " non reconnu") if (usrstats is not None): target = room.users.get(usrstats.user) if (target and target.last_active_ago is not None): ago = datetime.fromtimestamp(datetime.now().timestamp() - target.last_active_ago/1000) await msg(room,"J'ai vu " + usrstats.nick + " pour la dernière fois le : " + ago.strftime("%Y-%m-%d %H:%M:%S") + ". Et il a posté pour la dernière fois le : " + usrstats.date.strftime("%Y-%m-%d %H:%M:%S"),sender) else: await msg(room,"J'ai vu " + usrstats.nick + " poster pour la dernière fois le " + usrstats.date.strftime("%Y-%m-%d %H:%M:%S"),sender) else: target = None if (id_pers is not None): target = room.users.get(id_pers) else: target = room.users.get(pers) if (target and target.last_active_ago is not None): ago = datetime.fromtimestamp(datetime.now().timestamp() - target.last_active_ago/1000) await msg(room,"Dernière présence de " + pers + " : " + ago.strftime("%Y-%m-%d %H:%M:%S"),sender) else: await msg(room,pers + " : Personne non reconnue",sender) def statistiques(room,message): # Enregistrement des statistiques global modules try: rmod = modules[room.room_id, 'stats'] except: modules[room.room_id, 'stats'] = False if (modules[room.room_id, 'stats']): global stats nick = getNick(room, message) user = getUser(message) mess = getMessage(message) usrstats = None try: usrstats = stats[room.room_id,user] except: usrstats = Userstats(room.room_id,user,nick) # date de la phrase date = datetime.now() usrstats.date = date # recup nb phrases +1, 1 sinon usrstats.mess = usrstats.mess + 1 # recup nb lettres +lettres phrase, lettres phrases sinon usrstats.char = usrstats.char + len(mess) # insertion des objets stats[room.room_id,user] = usrstats async def actif(room,message): # Stats d'activité d'une personne global modules try: rmod = modules[room.room_id, 'stats'] except: modules[room.room_id, 'stats'] = False if (modules[room.room_id, 'stats']): global stats args = getMessage(message).split() sender = getUser(message) args.pop(0) if (len(args) > 0 and args[0] == "list"): salon = await verifPMRoom(room,message) room_act = [] for cle,valeur in stats.items(): if (cle[0] == room.room_id): room_act.append(valeur) room_act.sort(key=lambda us: us.mess, reverse=True) reponse="Voici le tableau des plus gros posteurs!\n" for us in room_act: reponse = reponse + us.nick + " : " + str(us.mess) + "\n" await msg(salon,reponse,sender) else: pers = "" usrstats = None if (len(args) == 0): pers = getUser(message) else: pers=" ".join(args) print(pers) try: usrstats = stats[room.room_id,pers] except: for cle,valeur in room.users.items(): if (valeur.display_name == pers): try: usrstats = stats[room.room_id, cle] except: usrstats = None if (usrstats is not None): break if(usrstats): try: moy = "{:10.2f}".format(usrstats.char / usrstats.mess) await msg(room,usrstats.nick + " a posté " + str(usrstats.mess) + " messages avec une moyenne de " + moy + " caractères par message",sender) except: print("erreur usrstats") else: await msg(room,pers + " : Personne non reconnue\n",sender) def getNiveau(niveau): if (niveau == 1): return("vert") elif (niveau == 2): return("orange") elif (niveau == 3): return("rouge") else: return("Inconnu") async def ecowatt(room, message): global modules try: rmod = modules[room.room_id, 'ecowatt'] except: modules[room.room_id, 'ecowatt'] = False if (modules[room.room_id, 'ecowatt']): args = getMessage(message).split() sender = getUser(message) jn = int(datetime.today().strftime("%Y%m%d")) hn = int(datetime.today().strftime("%H")) signals = None global wattobj if (wattobj.jour < jn or (wattobj.jour == jn and wattobj.heure + 1 < hn)): try: oauth = rte_token() result = oauth.get(ecowatt_url) watt = json.loads(result.text) except Exception as e: print(e) await msg(room, "Veuillez attendre 15 minutes", sender) return sign = watt["signals"] signals = sorted(sign, key=lambda signal: signal["jour"][0:10]) wattobj.jour = jn wattobj.heure = hn wattobj.signals = signals else: signals = wattobj.signals args.pop(0) mess = "" if (len(args) > 0 and args[0] == "details"): i=False for jour in signals: if (jour["dvalue"] > 1): if (i): mess = mess + "\n" i=True mess = mess + jour["jour"][0:10] + " : " + jour["message"] heures = sorted(jour["values"], key=lambda h: h["pas"]) for heure in heures: if (heure["hvalue"] > 1): alerte = getNiveau(heure["hvalue"]) mess = mess + "\n" + str(heure["pas"]) + "h : niveau " + alerte if (len(mess) < 10): mess = "Aucune alerte sur le réseau RTE dans les trois prochains jours." elif (len(args) > 0 and args[0].isnumeric()): j = int(args[0]) if (len(signals) > j): jour = signals[j] alerte = getNiveau(jour["dvalue"]) mess = mess + "La météo RTE du " + jour["jour"][0:10] + " est de niveau " + alerte + " (" + jour["message"] + ")\n" else: for jour in signals: alerte = getNiveau(jour["dvalue"]) mess = mess + "La météo RTE du " + jour["jour"][0:10] + " est de niveau " + alerte + " (" + jour["message"] + ")\n" await msg(room, mess, sender) async def commune(room, message): global modules try: rmod = modules[room.room_id, 'commune'] except: modules[room.room_id, 'commune'] = False if (modules[room.room_id, 'commune']): args = getMessage(message).split() sender = getUser(message) args.pop(0) mess = "" if (len(args) > 0): ville = " ".join(args) cette_commune = None if (ville.isnumeric()): cette_commune = commune_url.replace("", ville).replace("", "codePostal") else: cette_commune = commune_url.replace("", ville).replace("", "nom") oauth = rte_token() result = oauth.get(cette_commune) villes = json.loads(result.text) if (len(villes) > 0): try: cites = sorted(villes, key=lambda v: str(v["population"]).zfill(10), reverse=True) cite = cites[0] codePoste = cite["codesPostaux"][0] pop = cite["population"] insee = cite["code"] nom = cite["nom"] await msg(room, nom + ". CP : " + codePoste + ". Code INSEE : " + insee + ". Population : " + str(pop), sender) except: await msg(room, str(villes), sender) else: await msg(room, "Commune non trouvée", sender) else: await msg(room, "!commune ", sender) async def eau(room, message): global modules try: rmod = modules[room.room_id, 'eau'] except: modules[room.room_id, 'eau'] = False if (modules[room.room_id, 'eau']): args = getMessage(message).split() sender = getUser(message) args.pop(0) mess = "" if (len(args) > 0): ville = " ".join(args) cette_commune = None if (ville.isnumeric()): cette_commune = eau_url.replace("", ville).replace("", "code_commune") else: cette_commune = eau_url.replace("", ville).replace("", "nom_commune") oauth = rte_token() result = oauth.get(cette_commune) eaux = None try: eaux = json.loads(result.text) except: eaux = None if (eaux is not None): if (len(eaux["data"]) > 0): try: f = True for eau in eaux["data"]: if (f): nom = eau["nom_commune"] distrib = eau["nom_distributeur"] concl = eau["conclusion_conformite_prelevement"] await msg(room, "Prélèvement à " + nom + " réseau " + distrib + ". " + concl, sender) f = False date = eau["date_prelevement"][0:10] res = eau["resultat_alphanumerique"] unite = str(eau["libelle_unite"]) if (unite == "SANS OBJET"): unite = "" limite = "(" + str(eau["limite_qualite_parametre"]) + ")" if (limite == "(None)"): limite = "" param = eau["libelle_parametre"] + " " + limite await msg(room, "Résultat du " + date + " : " + res + unite + " / " + param + ".", sender) except: await msg(room, str(eaux), sender) else: await msg(room, "Commune non trouvée", sender) else: await msg(room, "Rapport d'eaux non trouvé", sender) else: await msg(room, "!eau ", sender) async def help(room, message): # Aide en message privé await help_center(room,message,"help",True) async def aide(room, message): # Aide dans le salon await help_center(room,message,"aide",False) async def help_center(room,message,name,private): # Aide sur les commandes disponibles args = getMessage(message).split() args.pop(0) salon = room sender = getUser(message) if (private): salon = await verifPMRoom(room,message) if (len(args) > 0): if (re.search("roll", args[0])): await msg(salon,":roll (+-modifs ou des)\n\n- exemple :roll vr4g3 6d6 - \#g\#r3d6 +2 x3 : lance avec les details 6d6 en relancant les des avec un resultat de 4+ et en gardant les trois meilleurs, puis en retranchant 3d6 sans relancer les 4+ et en gardant tout, enfin ajouter 2. L'operation sera executee trois fois.\n\n- v : details (verbose) du jet\n- n : no add, chaque de est traite separement\n- e : explosif, si un de fait le maximum, on le relance et on additionne\n- z : Star Zars, le premier de est explosif. Mais s'il sort un 1, on retire ce 1 et la plus grande valeur des autres des\n- f : difficulte a atteindre par de avec option n\n- g : nombre de des conserves\n- r : relance si le de a obtenu au moins ce nombre\n- m : Enleve un succes si ce nombre ou moins est atteint\n- s : seuil a atteindre et niveaux de reussites\n- w : lance un wild die avec les autres.",sender, False) elif (re.search("sw", args[0])): await msg(salon,"- :sw : Lance les des en mode Savage Worlds\nVerbose/Noadd/Explosif/Seuil 4/Niveau de reussite 4/Wild Die d6.",sender, False) elif (re.search("dom", args[0])): await msg(salon,"- :dom : Lance les dommages en mode Savage Worlds\nVerbose/Explosif/seuil 4/Niveau de reussite 4.",sender, False) elif (re.search("owod", args[0])): await msg(salon,"- :owod : Lance les des en mode Ancien Monde des Tenebres\nVerbose/Noadd/Difficulte 6/Relance les 10/Les 1 enleve un succes.",sender, False) elif (re.search("wod", args[0])): await msg(salon,"- :wod : Lance les des en mode Nouveau Monde des Tenebres\nVerbose/Noadd/Difficulte 8/Relance les 10.",sender, False) elif (re.search("ars", args[0])): await msg(salon,"- :ars : Lance les des en mode Ars Magicka : de de tension\nVerbose/Noadd/Sur un 1, on relance et on double.",sender, False) elif (re.search("des", args[0])): await msg(salon,"- :des : Lance des des de desastre\nVerbose/Noadd/Difficulte 10.",sender, False) elif (re.search("star", args[0])): await msg(salon,"- :star : Lance des des en mode star wars. Le premier de est explosif. Mais s'il sort un 1, on retire ce 1 et la plus grande valeur des autres des.",sender, False) elif (re.search("carte", args[0])): await msg(salon,"- !carte : Tire une carte et la retire du paquet\n- !carte m : remelange le paquet.",sender, False) elif (re.search("card", args[0])): await msg(salon,"- !card : tire une carte sans la retirer du paquet.",sender, False) elif (re.search("liste", args[0])): await msg(salon,"- !liste [Nombre d'elements souhaites] : retourne ce nombre d'elements de la liste.",sender, False) elif (re.search("horloge", args[0])): await msg(salon,"- !horloge : Affiche les horloges\n- !horloge : Crée ou modifie une horloge en lui mettant un niveau (normalement de 0 à 6)\n- !horloge del : Supprime cette horloge.",sender, False) elif (re.search("last", args[0])): await msg(salon,"- !last : Date de son dernier post\n- !last : Date du dernier post de la personne\n- !last inactifs <[+-]nombre de jours> : liste de personnes (en privé) ayant posté depuis + ou - le nombre de jours spécifiés et ayant au maximum le nombre de messages spécifiés.\n",sender, False) elif (re.search("actif", args[0])): await msg(salon,"- !actif : Nombre de ses messages et taille moyenne de ceux ci\n- !actif : Nombre des messages de cette personne et taille moyenne de ceux ci\n",sender, False) elif (re.search("quote", args[0])): await msg(salon,"- !quote : Affiche une citation du salon au hasard\n- !quote : Affiche une citation d'une personne du salon au hasard\n- !addquote après une réponse matrix : Enregistre une citation",sender, False) elif (re.search("biere", args[0])): await msg(salon,"- !biere : Fournit une boisson du salon au hasard\n- !biere : Fournit une boisson spécifique du salon\n- !biere give [:Nom du Breuvage] : Offre une boisson (spécifique en option) à la personne spécifiée\n- !biere add : : Enregistre une phrase pour ce breuvage\n- !biere list [Nom de Breuvage] : Affiche les phrases des breuvages du salon ou celles d'un breuvage spécifique du salon en message privé\n- !biere list all : Affiche toutes les citations de tous breuvages de tous les salons en message privé\n- !biere del : Supprime la phrase avec l'id spécifié",sender, False) elif (re.search("accueil", args[0])): await msg(salon,"- !accueil : Modifie le message d'accueil avec message. Il sera affiché à tout nouvel arrivant précédé de la mention 'Bienvenue sur le salon XXX, YYY.'",sender, False) elif (re.search("kick", args[0])): await msg(salon,"- !kick <@mxid> [@mxid] ... : kick les users listés",sender, False) elif (re.search("titre", args[0])): await msg(salon,"- !titre : retourne le titre de la page",sender, False) elif (re.search("mails", args[0]) or re.search("mail", args[0])): await msg(salon,"- !mail add : s'abonner aux messages du salon par mail.\n -!mail del : se désabonner aux messages du salon par mail.",sender, False) elif (re.search("modo", args[0])): await msg(salon,"- !modo : Affiche la liste des modérateurs (ils peuvent gérer le message d'accueil, supprimer des citations ou des boissons, ajouter/retirer des modules, ajouter/retirer des modérateurs)\n- !modo add : Ajoute une personne comme modérateur du salon\n- !modo del : Retire une personne des modérateurs.",sender, False) elif (re.search("module", args[0])): await msg(salon,"- !module : Affiche la liste des modules actifs sur le salon ainsi que celle des modules disponibles\n- !module add : Active un module sur le salon\n- !module del : Désactive un module sur le salon.",sender, False) elif (re.search("cristal", args[0])): await msg(salon,"- !cristal : Réponds à une question posée commençant par Est-ce, Combien, Pourquoi, Quand, Comment, Où et se terminant par un point d'interrogation.",sender, False) elif (re.search("ecowatt", args[0])): await msg(salon,"- !ecowatt : Météo RTE des prochains jours.\n- !ecowatt 0-3 : Météo RTE d'une journée entre J et J+3.\n- !ecowatt details : Météo RTE des prochains jours, chaque heure orange ou rouge spécifiquement.",sender, False) else: await msg(salon,"A venir",sender, False) else: rid = room.room_id message = "Commandes disponibles:" for cle,valeur in modules.items(): if (cle[0] == rid and cle[1] == "card" and valeur): message += "\n- !card" if (cle[0] == rid and cle[1] == "carte" and valeur): message += "\n- !carte" if (cle[0] == rid and cle[1] == "liste" and valeur): message += "\n- !liste [Nombre d'elements souhaites]" if (cle[0] == rid and cle[1] == "horloge" and valeur): message += "\n- !horloge : gestion des horloges PBTA" if (cle[0] == rid and cle[1] == "stats" and valeur): message += "\n- !last : Date de dernier post\n- !actif : Nombre de message et taille moyenne de ceux ci" if (cle[0] == rid and cle[1] == "quote" and valeur): message += "\n- !quote : citations du salon" if (cle[0] == rid and cle[1] == "biere" and valeur): message += "\n- !biere : breuvages du salon" if (cle[0] == rid and cle[1] == "cristal" and valeur): message += "\n- !cristal : Posez une question à la boule de cristal" if (cle[0] == rid and cle[1] == "welcome" and valeur): message += "\n- !accueil : Modifie le message d'accueil" if (cle[0] == rid and cle[1] == "kick" and valeur): message += "\n- !kick <@mxid> [@mxid] ... : kick les users listés" if (cle[0] == rid and cle[1] == "titre" and valeur): message += "\n- !titre : retourne le titre de la page en paramètre si celle ci possède une balise titre" if (cle[0] == rid and cle[1] == "mails" and valeur): message += "\n- !mail : s'abonner aux messages du salon par mail." if (cle[0] == rid and cle[1] == "ecowatt" and valeur): message += "\n- !ecowatt : Météo des prochains jours du réseau électrique RTE." if (cle[0] == rid and cle[1] == "roll" and valeur): message += "\n- :roll \n- :sw \n- :dom \n- :wod \n- :owod \n- :ars \n- :des \n- :star " message += "\n- !modo : Gère les modérateurs du salon\n- !module : Gère les modules actifs sur le salon\n\n- Pour plus de details, tapez !" + name + " \n\nRetrouvez Asmodee sur https://git.ombreport.info/nemesis/asmodee_matrix" await msg(salon,message,sender, False) @bot.listener.on_message_event async def callCommune(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("commune"): await commune(room, message) @bot.listener.on_message_event async def callEau(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("eau"): await eau(room, message) @bot.listener.on_message_event async def callEcowatt(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("ecowatt"): await ecowatt(room, message) @bot.listener.on_message_event async def callActif(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("actif"): await actif(room, message) @bot.listener.on_message_event async def callLast(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("last"): await last(room, message) @bot.listener.on_message_event async def callSave(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("save"): save_obj(room, message) @bot.listener.on_message_event async def callCard(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("card"): await card(room, message) @bot.listener.on_message_event async def callCarte(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("carte"): await carte(room, message) @bot.listener.on_message_event async def callHelp(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("help"): await help(room, message) @bot.listener.on_message_event async def callAide(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("aide"): await aide(room, message) @bot.listener.on_message_event async def callShowquote(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("quote"): await showquote(room, message) @bot.listener.on_message_event async def callAddquote(room, message): match = botlib.MessageMatch(room, message, bot) if match.is_not_from_this_bot() and match.contains("!addquote"): await addquote(room, message) @bot.listener.on_message_event async def callTitre(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("titre"): await titre(room, message) @bot.listener.on_custom_event(nio.RoomMemberEvent) async def callBienvenue(room, message): match = botlib.MessageMatch(room, message, bot) if match.is_not_from_this_bot(): await bienvenue(room, message) @bot.listener.on_message_event async def callAccueil(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("accueil"): await accueil(room, message) @bot.listener.on_message_event async def callSalon(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("salon"): await salon(room, message) @bot.listener.on_message_event async def callBoisson(room, message): match = botlib.MessageMatch(room, message, bot, "%") if match.is_not_from_this_bot() and match.prefix(): await boissons(room, message) @bot.listener.on_message_event async def callBiere(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("biere"): await biere(room, message) @bot.listener.on_message_event async def callHor(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("horloge"): await horloge(room, message) @bot.listener.on_message_event async def callListe(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("liste"): await liste(room, message) @bot.listener.on_message_event async def callRoll(room, message): match = botlib.MessageMatch(room, message, bot, ":") if match.is_not_from_this_bot() and match.prefix(): await entryPoint(room, message) @bot.listener.on_message_event async def callModule(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("module"): await module(room, message) @bot.listener.on_message_event async def callModo(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("modo"): await modo(room, message) @bot.listener.on_message_event async def echo(room, message): match = botlib.MessageMatch(room, message, bot, PREFIX) if match.is_not_from_this_bot() and match.prefix() and match.command("echo"): print(message) await bot.api.send_text_message( room.room_id, " ".join(arg for arg in match.args()) ) @bot.listener.on_message_event async def callStats(room, message): match = botlib.MessageMatch(room, message, bot) if match.is_not_from_this_bot(): statistiques(room, message) def rte_token(): auth = HTTPBasicAuth(RTE_ID, RTE_SECRET) client = BackendApplicationClient(client_id=RTE_ID) oauth = OAuth2Session(client=client) token = oauth.fetch_token(token_url='https://digital.iservices.rte-france.com/token/oauth/', auth=auth) return(oauth) def main(): config = configparser.ConfigParser() config.read('asmodee.ini') USERNAME = "" # Bot's username PASSWORD = "" # Bot's password SERVER = "" # Matrix server URL mods = ["roll", "quote", "biere", "stats", "liste", "horloge", "carte", "card", "cristal", "welcome", "salut", "jdr", "gens", "va", "salon", "kick", "mails", "titre", "invididious", "ecowatt", "commune"] global admins if ('AUTH' in config): USERNAME = config['AUTH']['username'] # Bot's username PASSWORD = config['AUTH']['password'] # Bot's password SERVER = config['AUTH']['server'] # Matrix server URL admins = config['AUTH']['admin'].split(",") # Admins du bot @admin1:host.tld,@admin2:host.tld,... else: print("Probleme de lecture de configuration asmodee.ini (AUTH)") if ('RTE' in config): global RTE_ID global RTE_SECRET global wattobj RTE_ID = config['RTE']['client_id'] # Bot's username RTE_SECRET = config['RTE']['client_secret'] # Bot's password wattobj = Wattobject() else: RTE_ID = None RTE_SECRET = None print("Probleme de lecture de configuration asmodee.ini (RTE)") global liste_mod if ('MOD' in config): try: liste_mod = config['MOD']['liste'].split(',') # Liste des modules except: liste_mod = mods else: liste_mod = mods if (threading.current_thread().__class__.__name__ == '_MainThread'): print("main thread") signal.signal(signal.SIGINT, signal_handler) modules_read() modos_read() prive_read() if ('horloge' in liste_mod): horloge_read() if ('quote' in liste_mod): #quotes_read() citations_read() if ('biere' in liste_mod): bieres_read() if ('salon' in liste_mod): salons_read() if ('welcome' in liste_mod): welcome_read() if __name__ == "__main__": main() bot.run()