Files
maubot-syno-photo-uploader/syno-media-uploader.py
MrRaph_ 25c3470e17 .
2024-12-20 16:09:36 +01:00

215 lines
8.2 KiB
Python

import os
import aiohttp
import asyncio
from typing import Type
from mautrix.client import Client
from maubot import Plugin, MessageEvent
from maubot.handlers import command, event
from mautrix.types import EventType, MessageType, RelationType, TextMessageEventContent, Format,RelatesTo,InReplyTo
from synology_api.filestation import FileStation
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
import pyotp
class Config(BaseProxyConfig):
def do_update(self, helper: ConfigUpdateHelper) -> None:
helper.copy("synology_host")
helper.copy("synology_port")
helper.copy("use_ssl")
helper.copy("username")
helper.copy("password")
helper.copy("default_folder")
helper.copy("room_folders")
helper.copy("api_version")
helper.copy("otp_secret_key")
class SynologyPhotoPlugin(Plugin):
# def __init__(self, bot):
# super().__init__(bot)
# self.synology = None
@classmethod
def get_config_class(cls) -> Type[BaseProxyConfig]:
return Config
def save_config(self) -> None:
self.config.save()
async def update_config(self, new_config: dict) -> None:
self.config.update(new_config)
self.save_config()
self.log.debug("Configuration updated and saved")
async def start(self):
await super().start()
# Récupérer la configuration
self.config.load_and_update()
self.synology_host = self.config['synology_host']
self.synology_port = self.config['synology_port']
self.use_ssl = self.config['use_ssl']
self.username = self.config['username']
self.password = self.config['password']
self.default_folder = self.config['default_folder']
self.room_folders = self.config['room_folders']
self.api_version = self.config['api_version']
self.otp_secret_key = self.config['otp_secret_key']
self.synology = None
otp = pyotp.TOTP(self.otp_secret_key)
self.otp_code = otp.now()
self.log.info("SynologyPhotoPlugin démarré")
# Initialiser la connexion Synology
try:
self.synology = FileStation(
ip_address=self.config["synology_host"],
port=self.config["synology_port"],
username=self.config["username"],
password=self.config["password"],
secure=bool(self.config["use_ssl"]),
cert_verify=False,
dsm_version=int(self.config["api_version"]),
debug=True,
otp_code=self.otp_code
)
self.log.info("Connexion à Synology réussie")
except Exception as e:
self.log.error(f"Échec de la connexion à Synology : {e}")
@event.on(EventType.ROOM_MESSAGE)
async def on_event(self, event):
await self.client.set_typing(event.room_id, timeout=0)
# Vérifier si l'événement est un message contenant du contenu multimédia
msgtype = str(event.content.msgtype)
if msgtype in ["m.image", "m.video"]:
self.log.info(f"Reçu un {event.content.msgtype} dans le canal {event.room_id}")
self.log.error(event)
await self.handle_media(event)
# else:
# self.log.error("ELSE")
# self.log.error("'" + str(event.content.msgtype) + "'")
async def handle_media(self, event):
# Extraire l'URL du contenu multimédia
content = event.content
url = content.get("url")
if not url:
self.log.warning("URL du média non trouvée")
return
# Télécharger le fichier
file_bytes = await self.client.download_media(url)
filename = str(event.content.filename)
if not filename or filename == "None":
filename = str(event.content.body)
if not file_bytes:
self.log.error("Échec du téléchargement du média")
return
with open('/tmp/'+ filename, "wb") as binary_file:
# Write bytes to file
binary_file.write(file_bytes)
# Déterminer le dossier cible basé sur la room Matrix
room_id = event.room_id
target_folder = self.room_folders.get(room_id, self.default_folder)
self.log.info(f"Dossier cible pour la room {room_id} : {target_folder}")
# Télécharger le média sur Synology Photos
upload_success = await self.upload_to_synology('/tmp/' + filename, target_folder)
if upload_success:
self.log.info(f"Média téléchargé avec succès sur Synology Photos : {filename} dans {target_folder}")
message = f"Média téléchargé avec succès sur Synology Photos : {filename} dans {target_folder}"
# Optionnel : supprimer le fichier local après téléchargement
os.remove('/tmp/' + filename)
else:
self.log.error("Échec du téléchargement sur Synology Photos")
message = "Échec du téléchargement sur Synology Photos"
content = TextMessageEventContent(
msgtype=MessageType.TEXT,
body=message,
format=Format.HTML,
formatted_body=message
)
in_reply_to = InReplyTo(event_id=event.event_id)
if event.content.relates_to and event.content.relates_to.rel_type == RelationType.THREAD:
await event.respond(content, in_thread=True)
else:
content.relates_to = RelatesTo(
in_reply_to=in_reply_to
)
await event.respond(content)
async def get_access_token(self):
# Utiliser le jeton d'accès de Maubot pour télécharger le média
# Vous pouvez personnaliser cette méthode selon votre configuration
token = self.bot.token
return token
async def download_media(self, url, access_token):
headers = {
"Authorization": f"Bearer {access_token}"
}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as resp:
if resp.status == 200:
data = await resp.read()
# Déterminer le nom du fichier
filename = url.split("/")[-1].split("?")[0] # Enlever les paramètres URL
file_path = os.path.join("/tmp/", filename)
with open(file_path, "wb") as f:
f.write(data)
return file_path, filename
else:
self.log.error(f"Erreur lors du téléchargement du média : {resp.status}")
return None, None
async def upload_to_synology(self, file_full_path, target_folder):
if not self.synology:
self.log.error("Connexion Synology non initialisée")
return False
try:
# Vérifier si le dossier cible existe, sinon le créer
### TODO: Gérer les dossiers imbriqués
# folders = self.synology.get_list()
# folder_titles = [folder['title'] for folder in folders['data']['items']]
# if target_folder not in folder_titles:
# self.synology.create_folder(target_folder)
# self.log.info(f"Dossier '{target_folder}' créé sur Synology Photos")
# Télécharger le fichier
with open(file_full_path, 'rb') as f:
file_data = f.read()
# Télécharger le fichier dans le dossier cible
self.synology.upload_file(
dest_path=target_folder,
file_path=file_full_path,
# file_data=file_data,
# path=target_folder,
create_parents=True,
# filename=filename
)
return True
except Exception as e:
self.log.error(f"Erreur lors de l'upload sur Synology Photos : {e}")
return False
async def stop(self):
if self.synology:
try:
self.synology.logout()
self.log.info("Déconnexion de Synology réussie")
except Exception as e:
self.log.error(f"Erreur lors de la déconnexion de Synology : {e}")
await super().stop()