1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
use crate::Data;
use crate::error::Error;
use crate::lang;
type Context<'a> = poise::Context<'a, Data, Error>;
/// Query the AI senator via OpenRouter or local LLM
#[poise::command(slash_command)]
pub async fn senator(
ctx: Context<'_>,
#[description = "Wiadomość do wysłania"] text: String,
#[description = "Przemówić w kanale głosowym?"] tts_vc: Option<bool>,
) -> crate::error::Result<()> {
ctx.defer().await?;
let (api_url, api_key, model) = ctx.data().config.resolve_llm();
let client = crate::openrouter::OpenRouterClient::new(api_url, api_key, model);
let response = client.chat(lang::SENATOR_SYSTEM_PROMPT, &text).await?;
if tts_vc.unwrap_or(false) {
let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
let channel_id = ctx
.serenity_context()
.cache
.guild(guild_id)
.and_then(|g| {
g.voice_states
.get(&ctx.author().id)
.and_then(|vs| vs.channel_id)
})
.ok_or_else(lang::err_not_in_voice)?;
let (audio_data, _) =
crate::tts::synthesize(&ctx.data().config, &ctx.data().http_client, &response).await?;
let call = ctx
.data()
.voice_manager
.connect(guild_id, channel_id)
.await?;
let input = crate::voice::decode_audio(&audio_data)?;
let mut call_lock = call.lock().await;
if call_lock.current_channel().is_some() {
call_lock.play_input(input);
}
}
ctx.say(response).await?;
Ok(())
}
pub fn commands() -> Vec<poise::Command<Data, Error>> {
vec![senator()]
}
|