57 lines
1.8 KiB
Python
57 lines
1.8 KiB
Python
"""Speech commands: text-to-speech and the voice catalog."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from discord.ext import commands
|
|
|
|
from vibe_bot.commands._state import require_app, set_app
|
|
from vibe_bot.config import VOICES_LIST
|
|
from vibe_bot.textutil import split_message
|
|
|
|
if TYPE_CHECKING:
|
|
from discord.ext.commands import Bot
|
|
from discord.ext.commands import Context as CommandsContext
|
|
|
|
from vibe_bot.app import App
|
|
|
|
|
|
def register(bot: commands.Bot, app: App) -> None:
|
|
"""Register the speech commands."""
|
|
set_app(app)
|
|
bot.command(name="speak")(speak)
|
|
bot.command(name="voices")(voices)
|
|
|
|
|
|
async def voices(ctx: CommandsContext[Bot]) -> None:
|
|
"""List all available TTS voices organized by category."""
|
|
voice_list = "Available Voices:\n\n"
|
|
for category, info in VOICES_LIST.items():
|
|
voice_list += f"{category} ({info['language']}):\n"
|
|
for v in info["voices"]:
|
|
voice_list += f"- {v}\n"
|
|
voice_list += "\n"
|
|
voice_list += "Use `!speak <text> --voice <voice_name>` to choose a voice."
|
|
|
|
for chunk in split_message(voice_list):
|
|
await ctx.send(chunk)
|
|
|
|
|
|
@commands.cooldown(rate=3, per=30, type=commands.BucketType.user)
|
|
async def speak(
|
|
ctx: CommandsContext[Bot],
|
|
*,
|
|
message: str,
|
|
) -> None:
|
|
"""Have the bot speak the given text using Kokoro TTS, or have a custom bot speak.
|
|
|
|
Usage: !speak <text> --voice <voice_name> - plain text to speech
|
|
Usage: !speak <bot_name> <text> --voice <voice_name> - have a custom bot respond and speak
|
|
Example: !speak hello world
|
|
Example: !speak hello world --voice af_bella
|
|
Example: !speak alfred what time is it --voice am_puck
|
|
"""
|
|
app = require_app()
|
|
await app.speech.speak(ctx, message=message)
|