Files
Matirx-Manager/main.py
2025-12-08 13:10:43 +01:00

93 lines
3.0 KiB
Python

from fastapi import FastAPI, HTTPException, BackgroundTasks
from pydantic import BaseModel
from bot import MatrixBot
import asyncio
from contextlib import asynccontextmanager
bot = MatrixBot()
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
await bot.login()
yield
# Shutdown
await bot.close()
app = FastAPI(lifespan=lifespan)
class Notification(BaseModel):
service_name: str
content: str
room_id: str | None = None
level: str = "info"
class JellyfinPayload(BaseModel):
notification_type: str
item_type: str
name: str
series_name: str | None = None
season: int | None = None
episode: int | None = None
year: int | None = None
overview: str | None = None
room_id: str | None = None
@app.post("/notify")
async def send_notification(notification: Notification, background_tasks: BackgroundTasks):
"""
Send a notification to a Matrix room.
"""
try:
# Format the message to include the service name
# Plain text fallback
plain_message = f"[{notification.service_name}]\n{notification.content}"
# HTML message
html_message = f"<b>[{notification.service_name}]</b><br>{notification.content}"
# We can send it in background to not block the API response
background_tasks.add_task(bot.send_message, plain_message, html_message, notification.room_id)
return {"status": "queued"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/jellyfin")
async def receive_jellyfin_webhook(payload: JellyfinPayload, background_tasks: BackgroundTasks):
"""
Receive webhook from Jellyfin and forward to Matrix.
"""
try:
if payload.notification_type != "ItemAdded":
return {"status": "ignored", "reason": "Not an ItemAdded event"}
# content construction
content = ""
if payload.item_type == "Movie":
content = f"New Movie: {payload.name}"
if payload.year:
content += f" ({payload.year})"
if payload.overview:
content += f"\n{payload.overview}"
elif payload.item_type == "Episode":
show = payload.series_name or "Unknown Series"
s = f"S{payload.season:02d}" if payload.season is not None else "S??"
e = f"E{payload.episode:02d}" if payload.episode is not None else "E??"
content = f"New Episode: {show} - {s}{e} - {payload.name}"
else:
# Fallback for Series, Season, etc.
content = f"New {payload.item_type}: {payload.name}"
plain_message = f"[Jellyfin]\n{content}"
html_message = f"<b>[Jellyfin]</b><br>{content.replace(chr(10), '<br>')}"
background_tasks.add_task(bot.send_message, plain_message, html_message, payload.room_id)
return {"status": "queued"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/health")
async def health_check():
return {"status": "ok"}