Files
Anime-Movies-Upcomming-Real…/discord_bot.py
2026-04-22 10:04:59 +02:00

114 lines
4.0 KiB
Python

#!/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())