112 lines
4.2 KiB
Python
112 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import discord
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
|
|
from zyrarbot.music.music_player import MusicPlayer
|
|
from zyrarbot.music.notification_channel_resolver import NotificationChannelResolver
|
|
from zyrarbot.storage.ports.guild_config import GuildConfigRepository
|
|
from zyrarbot.ui.api.dependencies import (
|
|
get_active_guild,
|
|
get_broadcaster,
|
|
get_config,
|
|
get_guilds,
|
|
get_player,
|
|
)
|
|
from zyrarbot.ui.api.requests.connect_request import ConnectRequest
|
|
from zyrarbot.ui.api.requests.notification_channel_request import NotificationChannelRequest
|
|
from zyrarbot.ui.api.status_broadcaster import StatusBroadcaster
|
|
from zyrarbot.ui.api.auth import current_user
|
|
from zyrarbot.ui.bot.guild_resolver import GuildResolver
|
|
|
|
router = APIRouter(prefix="/api", tags=["voice"])
|
|
|
|
|
|
@router.post("/notification_channel")
|
|
async def set_notification_channel(
|
|
request: NotificationChannelRequest,
|
|
guild: discord.Guild = Depends(get_active_guild),
|
|
guilds: GuildResolver = Depends(get_guilds),
|
|
player: MusicPlayer = Depends(get_player),
|
|
config: GuildConfigRepository = Depends(get_config),
|
|
broadcaster: StatusBroadcaster = Depends(get_broadcaster),
|
|
) -> dict[str, str]:
|
|
try:
|
|
channel_id = int(request.channel_id)
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=400, detail="Invalid text channel ID") from error
|
|
|
|
channel = guilds.channel(channel_id)
|
|
if not isinstance(channel, discord.TextChannel) or channel.guild.id != guild.id:
|
|
raise HTTPException(status_code=404, detail="Text channel not found on this server")
|
|
if channel not in NotificationChannelResolver.writable_channels(guild):
|
|
raise HTTPException(status_code=403, detail="Bot cannot send messages to this channel")
|
|
|
|
player.set_notification_channel(guild.id, channel)
|
|
config.set_notification_channel_id(guild.id, channel.id)
|
|
await broadcaster.broadcast()
|
|
return {"status": "success", "channel_id": str(channel.id)}
|
|
|
|
|
|
@router.post("/connect")
|
|
async def connect(
|
|
request: ConnectRequest,
|
|
http_request: Request,
|
|
user: dict = Depends(current_user),
|
|
guilds: GuildResolver = Depends(get_guilds),
|
|
player: MusicPlayer = Depends(get_player),
|
|
broadcaster: StatusBroadcaster = Depends(get_broadcaster),
|
|
) -> dict[str, str]:
|
|
try:
|
|
channel_id = int(request.channel_id)
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=400, detail="Invalid channel ID") from error
|
|
|
|
channel = guilds.channel(channel_id)
|
|
if not isinstance(channel, discord.VoiceChannel):
|
|
raise HTTPException(status_code=404, detail="Voice channel not found")
|
|
allowed = http_request.app.state.auth.guild_ids(
|
|
user, [item.id for item in guilds.guilds()]
|
|
)
|
|
if channel.guild.id not in allowed:
|
|
raise HTTPException(status_code=403, detail="Brak dostępu do tego serwera")
|
|
|
|
if channel.guild.me and not channel.permissions_for(channel.guild.me).connect:
|
|
raise HTTPException(
|
|
status_code=403,
|
|
detail=f"Bot nie ma uprawnień do połączenia z kanałem {channel.name}",
|
|
)
|
|
|
|
guild_id = channel.guild.id
|
|
# Rozłączamy wyłącznie na tym samym serwerze - inne serwery grają dalej.
|
|
existing = guilds.voice_client(guild_id)
|
|
if existing:
|
|
await existing.disconnect()
|
|
|
|
await channel.connect()
|
|
|
|
if not player.notification_channel(guild_id):
|
|
player.set_notification_channel(
|
|
guild_id, NotificationChannelResolver.first_writable(channel.guild)
|
|
)
|
|
|
|
await broadcaster.broadcast()
|
|
return {"status": "connected", "channel": channel.name}
|
|
|
|
|
|
@router.post("/disconnect")
|
|
async def disconnect(
|
|
guild: discord.Guild = Depends(get_active_guild),
|
|
player: MusicPlayer = Depends(get_player),
|
|
broadcaster: StatusBroadcaster = Depends(get_broadcaster),
|
|
) -> dict[str, str]:
|
|
voice_client = player.voice_client(guild.id)
|
|
if not voice_client:
|
|
raise HTTPException(status_code=400, detail="Bot not connected to voice on this server")
|
|
|
|
player.save_queue(guild.id)
|
|
await voice_client.disconnect()
|
|
player.clear(guild.id)
|
|
await broadcaster.broadcast()
|
|
return {"status": "disconnected"}
|