This commit is contained in:
MrRaph_
2024-12-03 11:44:43 +01:00
parent 9688aa5957
commit a270bc3296
3 changed files with 182 additions and 31 deletions

View File

@@ -1,3 +1,4 @@
hoarder_url: "http://hoarder.local" hoarder_url: "http://hoarder.local"
hoarder_api_key: "votre_cle_api" hoarder_api_key: "votre_cle_api"
hoarder_list_name: "list_name"
command_prefix: hoarder command_prefix: hoarder

View File

@@ -4,13 +4,13 @@ from typing import Type
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
from maubot import Plugin, MessageEvent from maubot import Plugin, MessageEvent
from maubot.handlers import event, command from maubot.handlers import event, command
from datetime import datetime
# Setup config file # Setup config file
class Config(BaseProxyConfig): class Config(BaseProxyConfig):
def do_update(self, helper: ConfigUpdateHelper) -> None: def do_update(self, helper: ConfigUpdateHelper) -> None:
helper.copy("hoarder_url") helper.copy("hoarder_url")
helper.copy("hoarder_api_key") helper.copy("hoarder_api_key")
helper.copy("hoarder_list_name")
helper.copy("command_prefix") helper.copy("command_prefix")
class HoarderForwarder(Plugin): class HoarderForwarder(Plugin):
@@ -22,35 +22,54 @@ class HoarderForwarder(Plugin):
def get_config_class(cls) -> Type[BaseProxyConfig]: def get_config_class(cls) -> Type[BaseProxyConfig]:
return Config return Config
async def get_page_title(self, url: str) -> str: async def send_message(evt: MessageEvent, message: str, formatted: bool = False, in_thread: bool = False):
"""Récupère le titre de la page web à partir de l'URL sans utiliser BeautifulSoup.""" """
try: Envoie un message en réponse à un événement Matrix, avec support des threads.
async with aiohttp.ClientSession() as session:
async with session.get(url) as response: Args:
if response.status == 200: evt (MessageEvent): L'événement de type message auquel répondre.
html = await response.text() message (str): Le texte du message à envoyer.
# Rechercher la balise <title> formatted (bool): Si True, le message sera envoyé en tant que texte formaté (HTML).
match = re.search(r"<title>(.*?)</title>", html, re.IGNORECASE | re.DOTALL) in_thread (bool): Si True, le message sera envoyé en tant que réponse dans un thread.
if match: """
return match.group(1).strip() content = {
else: "body": message,
return "Sans titre" "msgtype": "m.text" if not formatted else "m.notice",
else: }
return "Titre introuvable"
except Exception as e: if formatted:
print(f"Erreur lors de la récupération du titre: {e}") content["formatted_body"] = message
return "Erreur" content["format"] = "org.matrix.custom.html"
@command.new( if in_thread:
"hoarder", # Ajouter des métadonnées pour créer un thread
) content["m.relates_to"] = {
"rel_type": "m.thread",
"event_id": evt.event_id # ID de l'événement original pour le thread
}
# Envoyer le message
await evt.client.send_message(
room_id=evt.room_id, # Envoyer dans la même salle
content=content
)
@command.new("hoarder", require_subcommand=True, help="Commandes pour gérer Hoarder.")
async def base_command(self, evt: MessageEvent):
"""Commande principale pour Hoarder (placeholder)."""
#await evt.reply("Utilisez `!hoarder help` pour voir les commandes disponibles.")
pass
@base_command.subcommand("bookmark", help="Ajoute un bookmark à Hoarder.")
@command.argument("url", pass_raw=True, required=True) @command.argument("url", pass_raw=True, required=True)
async def send_to_hoarder(self, evt: MessageEvent, url: str) -> None: async def bookmark(self, evt: MessageEvent, url: str) -> None:
await evt.mark_read() await evt.mark_read()
hoarder_url = self.config["hoarder_url"] + '/api/trpc/bookmarks.createBookmark' hoarder_list = await self.ensure_list_exists(evt, self.config["hoarder_list_name"])
hoarder_url = self.config["hoarder_url"]
api_key = self.config["hoarder_api_key"] api_key = self.config["hoarder_api_key"]
create_endpoint = f"{hoarder_url}/api/trpc/bookmarks.createBookmark"
self.log.info(hoarder_url) self.log.info(hoarder_url)
#title = await self.get_page_title(url) # Récupère le titre de la page #title = await self.get_page_title(url) # Récupère le titre de la page
@@ -73,10 +92,141 @@ class HoarderForwarder(Plugin):
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.post(hoarder_url, json=payload, headers=headers) as response: async with session.post(create_endpoint, json=payload, headers=headers) as response:
if response.status == 201: if response.status == 200 or response.status == 201 or response.status == 204:
self.log.info(f"URL envoyée avec succès à Hoarder : {url}") data = await response.json()
bookmark_id = data[0]["result"]["data"]["json"]["id"]
await self.send_message(evt, f"Bookmark créé avec succès : {bookmark_id}", in_thread=True)
self.add_bookmark_to_list(bookmark_id, hoarder_list)
return bookmark_id
else: else:
self.log.error(f"Échec de l'envoi de l'URL à Hoarder : {response.status}") await self.send_message(evt, f"Erreur lors de la création du bookmark : {response.status}", in_thread=True)
print(await response.text())
except Exception as e: except Exception as e:
self.log.exception(f"Erreur lors de l'envoi de l'URL à Hoarder : {e}") await self.send_message(evt, f"Erreur lors de la création du bookmark : {e}", in_thread=True)
return None
async def get_all_lists(self, evt: MessageEvent):
"""Récupère la liste des listes sur Hoarder."""
hoarder_url = self.config["hoarder_url"]
api_key = self.config["hoarder_api_key"]
list_endpoint = f"{hoarder_url}/api/v1/lists"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
}
try:
async with aiohttp.ClientSession() as session:
async with session.get(list_endpoint, headers=headers) as response:
if response.status == 200:
data = await response.json()
return data.get("lists", [])
else:
await self.send_message(evt, f"Erreur lors de la récupération des listes : {response.status}", in_thread=True)
return []
except Exception as e:
await self.send_message(evt, f"Erreur lors de la récupération des listes : {e}", in_thread=True)
return []
async def find_list_by_name(self, evt: MessageEvent, name: str) -> str:
"""Vérifie si une liste existe et retourne son ID si elle est trouvée."""
lists = await self.get_all_lists(evt)
for lst in lists:
if lst["name"] == name:
await self.send_message(evt, f"Liste trouvée : {name} (ID : {lst['id']})", in_thread=True)
return lst["id"]
await self.send_message(evt, f"Aucune liste trouvée avec le nom : {name}", in_thread=True)
return None
async def create_list(self, evt: MessageEvent, name: str) -> str:
"""Crée une nouvelle liste avec le nom donné et retourne son ID."""
hoarder_url = self.config["hoarder_url"]
api_key = self.config["hoarder_api_key"]
create_endpoint = f"{hoarder_url}/api/trpc/lists.createList"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
}
payload = {
"json": {
"icon": "💬", # Icône par défaut
"name": name
}
}
try:
async with aiohttp.ClientSession() as session:
async with session.post(create_endpoint, json=payload, headers=headers) as response:
if response.status == 200 or response.status == 201 or response.status == 204:
data = await response.json()
list_id = data["result"]["data"]["json"]["id"]
await self.send_message(evt, f"Liste créée avec succès : {name} (ID : {list_id})", in_thread=True)
return list_id
else:
await self.send_message(evt, f"Erreur lors de la création de la liste : {response.status}", in_thread=True)
return None
except Exception as e:
await self.send_message(evt, f"Erreur lors de la création de la liste : {e}", in_thread=True)
return None
async def ensure_list_exists(self, evt: MessageEvent, name: str) -> str:
"""Vérifie si une liste existe, sinon la crée."""
list_id = await self.find_list_by_name(evt, name)
if list_id is None:
await self.send_message(evt, f"La liste '{name}' n\'existe pas, création en cours...", in_thread=True)
list_id = await self.create_list(evt, name)
return list_id
async def add_bookmark_to_list(self, evt: MessageEvent, bookmark_id: str):
"""Ajoute un bookmark à une liste donnée."""
hoarder_url = self.config["hoarder_url"]
api_key = self.config["hoarder_api_key"]
list_id = await self.ensure_list_exists(evt, self.config["hoarder_list_name"])
add_to_list_endpoint = f"{hoarder_url}/api/v1/lists/{list_id}/bookmarks"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
}
payload = {
"bookmarkId": bookmark_id
}
try:
async with aiohttp.ClientSession() as session:
async with session.put(add_to_list_endpoint, headers=headers) as response:
if response.status == 200 or response.status == 201 or response.status == 204:
await self.send_message(evt, f"Bookmark {bookmark_id} ajouté à la liste {list_id} avec succès.", in_thread=True)
return True
else:
await self.send_message(evt, f"Erreur lors de l'ajout à la liste : {response.status}", in_thread=True)
await self.send_message(evt, await response.text(), in_thread=True)
return False
except Exception as e:
await self.send_message(evt, f"Erreur lors de l'ajout du bookmark à la liste : {e}", in_thread=True)
return False
@base_command.subcommand("help", help="Affiche l'aide pour les commandes Hoarder.")
async def hoarder_help(self, evt: MessageEvent):
"""Affiche un message d'aide pour les commandes Hoarder."""
help_message = (
"💬 **Commandes disponibles pour Hoarder Bot** 💬\n"
"- `!hoarder bookmark <url>` : Ajoute le lien spécifié à votre liste Hoarder.\n"
"- `!hoarder help` : Affiche ce message d'aide.\n\n"
"⚙️ **Configuration** :\n"
"Assurez-vous que l'URL de base de votre installation d'Hoarder est définie dans la configuration sous `hoarder_url`.\n\n"
"Assurez-vous que la clef API d'Hoarder est définie dans la configuration sous `hoarder_api_key`.\n\n"
"Assurez-vous que la liste cible est définie dans la configuration sous `hoarder_list_name`.\n\n"
"📘 **Documentation supplémentaire** :\n"
"Consultez les guides sur [Hoarder](https://docs.hoarder.app)."
)
await evt.reply(help_message)

View File

@@ -8,7 +8,7 @@ maubot: 0.1.0
id: fr.mrraph.hoarder-bot id: fr.mrraph.hoarder-bot
# A PEP 440 compliant version string. # A PEP 440 compliant version string.
version: 0.0.2 version: 0.1.0
# The SPDX license identifier for the plugin. https://spdx.org/licenses/ # The SPDX license identifier for the plugin. https://spdx.org/licenses/
# Optional, assumes all rights reserved if omitted. # Optional, assumes all rights reserved if omitted.