Add modular TMDb-first movie pipeline and Discord bot
This commit is contained in:
113
discord_bot.py
Normal file
113
discord_bot.py
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
|
||||
import discord
|
||||
from discord import app_commands
|
||||
from discord.ext import commands
|
||||
|
||||
from app_config import get_settings
|
||||
from movie_pipeline import get_upcoming_movie_records
|
||||
from embed_builder import build_movie_embed, make_links_view
|
||||
|
||||
|
||||
async def fetch_records(locale: str, tmdb_token: str, schedule_token: str) -> list[dict]:
|
||||
return await asyncio.to_thread(
|
||||
get_upcoming_movie_records,
|
||||
locale,
|
||||
None,
|
||||
schedule_token,
|
||||
tmdb_token,
|
||||
)
|
||||
|
||||
|
||||
def create_bot() -> commands.Bot:
|
||||
settings = get_settings()
|
||||
intents = discord.Intents.default()
|
||||
bot = commands.Bot(command_prefix="!", intents=intents)
|
||||
guild_obj = discord.Object(id=int(settings.discord_guild_id)) if settings.discord_guild_id.isdigit() else None
|
||||
|
||||
async def sync_commands() -> None:
|
||||
if guild_obj:
|
||||
try:
|
||||
# Remove stale global commands to avoid duplicate /anime entries.
|
||||
cleared_global = await bot.tree.sync()
|
||||
cleared_names = ", ".join(cmd.name for cmd in cleared_global) if cleared_global else "keine"
|
||||
print(f"Globale Slash Commands aktualisiert: {len(cleared_global)} ({cleared_names})")
|
||||
|
||||
synced = await bot.tree.sync(guild=guild_obj)
|
||||
names = ", ".join(cmd.name for cmd in synced) if synced else "keine"
|
||||
print(f"Slash Commands fuer Guild synchronisiert: {len(synced)} ({names})")
|
||||
return
|
||||
except Exception as exc:
|
||||
print(f"Guild-Sync fehlgeschlagen, nutze globalen Sync: {exc}")
|
||||
|
||||
synced = await bot.tree.sync()
|
||||
names = ", ".join(cmd.name for cmd in synced) if synced else "keine"
|
||||
print(f"Globale Slash Commands synchronisiert: {len(synced)} ({names})")
|
||||
print("Hinweis: Globale Slash Commands koennen bis zu 60 Minuten brauchen.")
|
||||
print("Setze DISCORD_GUILD_ID fuer sofortige Verfuegbarkeit in deinem Server.")
|
||||
|
||||
@bot.event
|
||||
async def setup_hook() -> None:
|
||||
await sync_commands()
|
||||
|
||||
@bot.event
|
||||
async def on_ready() -> None:
|
||||
print(f"Bot online als {bot.user}")
|
||||
|
||||
async def anime_handler(interaction: discord.Interaction, limit: app_commands.Range[int, 1, 25] = 10) -> None:
|
||||
locale = settings.locale
|
||||
safe_limit = int(limit)
|
||||
|
||||
await interaction.response.defer(thinking=True)
|
||||
try:
|
||||
records = await fetch_records(locale, settings.tmdb_read_access_token, settings.animeschedule_api_token)
|
||||
except Exception as exc:
|
||||
await interaction.followup.send(f"Fehler beim Abruf: {exc}")
|
||||
return
|
||||
|
||||
if not records:
|
||||
await interaction.followup.send("Keine Anime Filme fuer diesen und naechsten Monat gefunden.")
|
||||
return
|
||||
|
||||
selected = records[:safe_limit]
|
||||
await interaction.followup.send(f"Gefunden: {len(selected)} Anime-Filme")
|
||||
|
||||
for idx, item in enumerate(selected, start=1):
|
||||
embed = build_movie_embed(item, idx)
|
||||
view = make_links_view(str(item.get("anilist_url", "")))
|
||||
if view is None:
|
||||
await interaction.followup.send(embed=embed)
|
||||
else:
|
||||
await interaction.followup.send(embed=embed, view=view)
|
||||
|
||||
anime_handler = app_commands.describe(limit="Anzahl Ergebnisse (1-25)")(anime_handler)
|
||||
if guild_obj:
|
||||
bot.tree.command(
|
||||
name="anime",
|
||||
description="Zeigt kommende Anime-Filme",
|
||||
guild=guild_obj,
|
||||
)(anime_handler)
|
||||
else:
|
||||
bot.tree.command(
|
||||
name="anime",
|
||||
description="Zeigt kommende Anime-Filme",
|
||||
)(anime_handler)
|
||||
|
||||
return bot
|
||||
|
||||
|
||||
def main() -> int:
|
||||
settings = get_settings()
|
||||
token = settings.discord_bot_token
|
||||
if not token:
|
||||
print("Fehler: DISCORD_BOT_TOKEN ist nicht gesetzt.")
|
||||
return 1
|
||||
|
||||
bot = create_bot()
|
||||
bot.run(token)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user