from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper from maubot import Plugin, MessageEvent from maubot.handlers import command import aiohttp import asyncio from bs4 import BeautifulSoup import random import re from difflib import SequenceMatcher from heapq import nlargest as _nlargest class ChefMou(Plugin): async def start(self) -> None: self.on_external_config_update() def get_close_matches_indexes(self, word, possibilities, n=3, cutoff=0.6): if not n > 0: raise ValueError("n must be > 0: %r" % (n,)) if not 0.0 <= cutoff <= 1.0: raise ValueError("cutoff must be in [0.0, 1.0]: %r" % (cutoff,)) result = [] s = SequenceMatcher() s.set_seq2(word) for idx, x in enumerate(possibilities): s.set_seq1(x) if s.real_quick_ratio() >= cutoff and \ s.quick_ratio() >= cutoff and \ s.ratio() >= cutoff: result.append((s.ratio(), idx)) # Move the best scorers to head of list result = _nlargest(n, result) # Strip scores for the best n matches return [x for score, x in result] async def get_site_content(self): async with aiohttp.ClientSession() as session: async with session.get("https://partoches.pustule.org") as resp: text = await resp.read() return BeautifulSoup(text.decode('iso-8859-1'), 'html.parser') @command.new("chefmou") @command.argument("pattern", pass_raw=True, required=False) async def morceau(self, evt: MessageEvent, pattern: str) -> None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) if not pattern: await evt.respond( """ !chefmou morceau -> Donne un morceau aléatoire !chefmou partition instru titre -> Renvoi le lien vers la partition de ce morceau pour cet instrument """ ) else: if pattern == "morceau": soup = await self.get_site_content() s = soup.findAll('th', background='/fond3.gif') ps = random.choice(s) await evt.respond(ps.text) elif pattern.__contains__("partition"): chunks = pattern.split(None, 2) if len(chunks) != 3 : await evt.respond( """ !chefmou morceau -> Donne un morceau aléatoire !chefmou partition instru titre -> Renvoi le lien vers la partition de ce morceau pour cet instrument """ ) loop.close() return soup = await self.get_site_content() # Récuperer liste morceaux s = soup.select('th', background='/fond3.gif') # Object bts en str parsedList=[] originalList=[] for ts in s: fullTitre = ts.text #Supression des () parsedList.append(re.sub("[\(\[].*?[\)\]]", "", fullTitre)) #On garde une copie pour la recherche originalList.append(ts.text) # Fonction qui retourne l'index du string le plus proche idxTitre = self.get_close_matches_indexes(chunks[2], parsedList, cutoff=0.4) # Si trouvé le chercher sinon erreur if len(idxTitre) > 0 : #Et on recherche dans la liste originale avec le titre original s = soup.find('th', string=originalList[idxTitre[0]]) t = s.parent.findAll('a') idx = 9 if chunks[1].lower() == "souba" or chunks[1].lower() == "soubassophone" or chunks[1].lower() == "sb": idx = 0 elif chunks[1].lower() == "basse" or chunks[1].lower() == "bs" : idx = 1 elif chunks[1].lower() == "trombone" or chunks[1].lower() == "tb": idx = 2 elif chunks[1].lower() == "trompette" or chunks[1].lower() == "tp": idx = 3 elif chunks[1].lower() == "sax" or chunks[1].lower() == "saxophone": idx = 4 elif chunks[1].lower() == "clarinette" or chunks[1].lower() == "cl": idx = 5 else: await evt.respond("Pas trouvé cet instru") loop.close() return try : await evt.respond("["+originalList[idxTitre[0]]+ " " + chunks[1]+"]"+"()") except IndexError: await evt.respond("Le morceau "+ strTitre[0] + " existe mais pas ta partoche") else: await evt.respond("Morceau non trouvé") else: await evt.respond("Nope !") loop.close()