Skip to content

Commit

Permalink
support replies to inaccessible messages
Browse files Browse the repository at this point in the history
  • Loading branch information
jelni committed Dec 30, 2024
1 parent 843f93e commit e0fea46
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 45 deletions.
49 changes: 25 additions & 24 deletions src/commands/gemini.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,39 +75,40 @@ impl CommandTrait for Gemini {
parts.push(Part::Text(Cow::Owned(text)));
}

if let Some(message_image) = telegram_utils::get_message_attachment(
Cow::Owned(message.content),
true,
ctx.client_id,
)
.await?
{
let file = message_image.file()?;

if file.size > 64 * MEBIBYTE {
return Err(CommandError::Custom("files cannot be larger than 64 MiB.".into()));
}
if let Some(content) = message.content {
if let Some(message_image) =
telegram_utils::get_message_attachment(Cow::Owned(content), true, ctx.client_id)
.await?
{
let file = message_image.file()?;

if file.size > 64 * MEBIBYTE {
return Err(CommandError::Custom(
"files cannot be larger than 64 MiB.".into(),
));
}

let File::File(file) =
functions::download_file(file.id, 1, 0, 0, true, ctx.client_id).await?;
let File::File(file) =
functions::download_file(file.id, 1, 0, 0, true, ctx.client_id).await?;

let open_file = tokio::fs::File::open(file.local.path).await.unwrap();
let open_file = tokio::fs::File::open(file.local.path).await.unwrap();

let file = google_aistudio::upload_file(
&ctx.bot_state.http_client,
open_file,
file.size.try_into().unwrap(),
message_image.mime_type()?,
)
.await?;
let file = google_aistudio::upload_file(
&ctx.bot_state.http_client,
open_file,
file.size.try_into().unwrap(),
message_image.mime_type()?,
)
.await?;

parts.push(Part::FileData(FileData { file_uri: file.uri }));
parts.push(Part::FileData(FileData { file_uri: file.uri }));
}
}

if !parts.is_empty() {
contents.push(Content {
parts: Cow::Owned(parts),
role: Some(if message.my { "model" } else { "user" }),
role: Some(if message.bot_author { "model" } else { "user" }),
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/groq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl CommandTrait for Llama {

prompt_messages.extend(messages.into_iter().filter_map(|message| {
message.text.map(|text| Message {
role: if message.my { "assistant" } else { "user" },
role: if message.bot_author { "assistant" } else { "user" },
content: Cow::Owned(text),
})
}));
Expand Down
80 changes: 60 additions & 20 deletions src/utilities/convert_argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::collections::VecDeque;
use std::fmt;

use async_trait::async_trait;
use tdlib::enums::{Message, MessageContent, MessageReplyTo};
use tdlib::enums::{
Message, MessageContent, MessageOrigin, MessageReplyTo, MessageSender, UserType,
};
use tdlib::functions;

use super::command_context::CommandContext;
Expand Down Expand Up @@ -160,8 +162,8 @@ impl ConvertArgument for StringGreedyOrReply {

pub struct ReplyChainMessage {
pub text: Option<String>,
pub content: MessageContent,
pub my: bool,
pub content: Option<MessageContent>,
pub bot_author: bool,
}

pub struct ReplyChain(pub Vec<ReplyChainMessage>);
Expand All @@ -172,33 +174,48 @@ impl ConvertArgument for ReplyChain {
ctx: &CommandContext,
arguments: &'a str,
) -> Result<(Self, &'a str), ConversionError> {
let mut message = ctx.message.clone();

let mut messages = VecDeque::from([ReplyChainMessage {
text: if arguments.is_empty() { None } else { Some(arguments.into()) },
content: message.content,
my: ctx.message.is_outgoing,
content: Some(ctx.message.content.clone()),
bot_author: ctx.message.is_outgoing,
}]);

let mut message = Some(ctx.message.clone());

for _ in 0..15 {
let Some(MessageReplyTo::Message(reply)) = &message.reply_to else {
let Some(current_message) = message else {
break;
};

let mut text = None;
let Some(MessageReplyTo::Message(reply)) = &current_message.reply_to else {
break;
};

if let Some(quote) = reply.quote.as_ref() {
text = Some(quote.text.text.clone());
message = match functions::get_replied_message(
current_message.chat_id,
current_message.id,
ctx.client_id,
)
.await
{
Ok(Message::Message(message)) => Some(message),
Err(err) => {
if err.code == 404 {
None
} else {
return Err(ConversionError::TdError(err));
}
}
};

Message::Message(message) =
functions::get_replied_message(message.chat_id, message.id, ctx.client_id)
.await
.map_err(ConversionError::TdError)?;
let content = reply
.content
.clone()
.or_else(|| message.as_ref().map(|message| message.content.clone()));

messages.push_front(ReplyChainMessage {
text: text.or_else(|| {
telegram_utils::get_message_text(&message.content).and_then(|text| {
let text = reply.quote.as_ref().map(|quote| quote.text.text.clone()).or_else(|| {
content.as_ref().and_then(|content| {
telegram_utils::get_message_text(content).and_then(|text| {
match ParsedCommand::parse(text) {
Some(command) => {
if command.arguments.is_empty() {
Expand All @@ -216,9 +233,32 @@ impl ConvertArgument for ReplyChain {
}
}
})
})
});

let author = reply
.origin
.as_ref()
.and_then(|origin| match origin {
MessageOrigin::User(user) => Some(user.sender_user_id),
_ => None,
})
.or_else(|| {
message.as_ref().and_then(|message| match &message.sender_id {
MessageSender::User(user) => Some(user.user_id),
MessageSender::Chat(_) => None,
})
});

messages.push_front(ReplyChainMessage {
text,
content,
bot_author: author.is_some_and(|author| {
matches!(
ctx.bot_state.cache.lock().unwrap().get_user(author).unwrap().r#type,
UserType::Bot(..)
)
}),
content: message.content,
my: message.is_outgoing,
});
}

Expand Down

0 comments on commit e0fea46

Please sign in to comment.