Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending reactions #257

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/grammers-client/examples/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ async fn async_main() -> Result {
// This code uses `select` on Ctrl+C to gracefully stop the client and have a chance to
// save the session. You could have fancier logic to save the session if you wanted to
// (or even save it on every update). Or you could also ignore Ctrl+C and just use
// `while let Some(updates) = client.next_updates().await?`.
// `let update = client.next_update().await?`.
//
// Using `tokio::select!` would be a lot cleaner but add a heavy dependency,
// so a manual `select` is used instead by pinning async blocks by hand.
Expand Down
5 changes: 3 additions & 2 deletions lib/grammers-client/src/client/bots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,19 @@ impl Client {
) -> Result<bool, InvocationError> {
let message: InputMessage = input_message.into();
let entities = parse_mention_entities(self, message.entities);
let dc_id = message_id.dc_id();
let result = self
.invoke_in_dc(
&tl::functions::messages::EditInlineBotMessage {
id: message_id.clone(),
id: message_id,
message: Some(message.text),
media: message.media,
entities,
no_webpage: !message.link_preview,
reply_markup: message.reply_markup,
invert_media: message.invert_media,
},
message_id.dc_id(),
dc_id,
)
.await?;
Ok(result)
Expand Down
53 changes: 51 additions & 2 deletions lib/grammers-client/src/client/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
// except according to those terms.

//! Methods related to sending messages.
use crate::types::{IterBuffer, Message};
use crate::types::{InputReactions, IterBuffer, Message};
use crate::utils::{generate_random_id, generate_random_ids};
use crate::{types, ChatMap, Client};
use chrono::{DateTime, FixedOffset};
pub use grammers_mtsender::{AuthorizationError, InvocationError};
use grammers_session::PackedChat;
use grammers_tl_types as tl;
use grammers_tl_types::enums::InputPeer;
use std::collections::HashMap;
use tl::enums::InputPeer;
use tl::functions::messages::SendReaction;

fn get_message_id(message: &tl::enums::Message) -> i32 {
match message {
Expand Down Expand Up @@ -1024,4 +1025,52 @@ impl Client {
.await?;
Ok(())
}

/// Send reaction.
///
/// # Examples
///
/// Via emoticon
///
/// ```
/// # async fn f(chat: grammers_client::types::Chat, client: grammers_client::Client) -> Result<(), Box<dyn std::error::Error>> {
/// let message_id = 123;
///
/// client.send_reaction(&chat, message_id, "👍").await?;
/// # Ok(())
/// # }
/// ```
///
/// Make animation big & Add to recent
///
/// ```
/// # async fn f(chat: grammers_client::types::Chat, client: grammers_client::Client) -> Result<(), Box<dyn std::error::Error>> {
/// use grammers_client::types::InputReactions;
///
/// let message_id = 123;
/// let reactions = InputReactions::emoticon("🤯").big().add_to_recent();
///
/// client.send_reaction(&chat, message_id, reactions).await?;
/// # Ok(())
/// # }
/// ```
pub async fn send_reaction<C: Into<PackedChat>, R: Into<InputReactions>>(
&self,
chat: C,
message_id: i32,
reactions: R,
) -> Result<(), InvocationError> {
let reactions = reactions.into();

self.invoke(&SendReaction {
big: reactions.big,
add_to_recent: reactions.add_to_recent,
peer: chat.into().to_input_peer(),
msg_id: message_id,
reaction: Some(reactions.reactions),
})
.await?;

Ok(())
}
}
7 changes: 4 additions & 3 deletions lib/grammers-client/src/types/inline/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use grammers_tl_types as tl;
use std::fmt;
use std::sync::Arc;

/// Represents an update of user choosing the result of inline query and sending it to their chat partner.
#[derive(Clone)]
pub struct InlineSend {
raw: tl::types::UpdateBotInlineSend,
Expand Down Expand Up @@ -63,14 +64,14 @@ impl InlineSend {
/// Identifier of sent inline message.
/// Available only if there is an inline keyboard attached.
/// Will be also received in callback queries and can be used to edit the message.
pub fn msg_id(&self) -> Option<tl::enums::InputBotInlineMessageId> {
pub fn message_id(&self) -> Option<tl::enums::InputBotInlineMessageId> {
self.raw.msg_id.clone()
}

/// Edits this inline message.
///
/// **This method will return Ok(None) if message id is None (e.g. if an inline keyboard is not attached)**
pub async fn edit_msg(
pub async fn edit_message(
&self,
input_message: impl Into<InputMessage>,
) -> Result<Option<bool>, InvocationError> {
Expand All @@ -93,7 +94,7 @@ impl fmt::Debug for InlineSend {
.field("text", &self.text())
.field("sender", &self.sender())
.field("result_id", &self.result_id())
.field("msg_id", &self.msg_id())
.field("message_id", &self.message_id())
.finish()
}
}
36 changes: 35 additions & 1 deletion lib/grammers-client/src/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// except according to those terms.
#[cfg(any(feature = "markdown", feature = "html"))]
use crate::parsers;
use crate::types::reactions::InputReactions;
use crate::types::{Downloadable, InputMessage, Media, Photo};
use crate::utils;
use crate::ChatMap;
Expand Down Expand Up @@ -123,7 +124,7 @@ impl Message {
edit_hide: false,
pinned: false,
noforwards: false, // TODO true if channel has noforwads?
invert_media: false,
invert_media: input.invert_media,
id: updates.id,
from_id: None, // TODO self
from_boosts_applied: None,
Expand Down Expand Up @@ -377,6 +378,39 @@ impl Message {
}
}

/// React to this message.
///
/// # Examples
///
/// ```
/// # async fn f(message: grammers_client::types::Message, client: grammers_client::Client) -> Result<(), Box<dyn std::error::Error>> {
/// message.react("👍").await?;
/// # Ok(())
/// # }
/// ```
///
/// Make animation big & Add to recent
///
/// ```
/// # async fn f(message: grammers_client::types::Message, client: grammers_client::Client) -> Result<(), Box<dyn std::error::Error>> {
/// use grammers_client::types::InputReactions;
///
/// let reactions = InputReactions::emoticon("🤯").big().add_to_recent();
///
/// message.react(reactions).await?;
/// # Ok(())
/// # }
/// ```
pub async fn react<R: Into<InputReactions>>(
&self,
reactions: R,
) -> Result<(), InvocationError> {
self.client
.send_reaction(self.chat(), self.id(), reactions)
.await?;
Ok(())
}

/// How many reactions does this message have, when applicable.
pub fn reaction_count(&self) -> Option<i32> {
match &self.raw.reactions {
Expand Down
2 changes: 2 additions & 0 deletions lib/grammers-client/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub mod participant;
pub mod password_token;
pub mod permissions;
pub mod photo_sizes;
pub mod reactions;
pub mod reply_markup;
pub mod terms_of_service;
pub mod update;
Expand All @@ -53,6 +54,7 @@ pub use message_deletion::MessageDeletion;
pub use participant::{Participant, Role};
pub use password_token::PasswordToken;
pub use permissions::{Permissions, Restrictions};
pub use reactions::InputReactions;
pub(crate) use reply_markup::ReplyMarkup;
pub use terms_of_service::TermsOfService;
pub use update::Update;
91 changes: 91 additions & 0 deletions lib/grammers-client/src/types/reactions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2020 - developers of the `grammers` project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use grammers_tl_types as tl;
use tl::enums::Reaction;

#[derive(Clone, Debug)]
pub struct InputReactions {
pub(crate) reactions: Vec<Reaction>,
pub(crate) add_to_recent: bool,
pub(crate) big: bool,
}

impl InputReactions {
/// Make reaction animation big.
pub fn big(mut self) -> Self {
self.big = true;
self
}

/// Add this reaction to the recent reactions list.
///
/// More about that: \
/// https://core.telegram.org/api/reactions#recent-reactions
pub fn add_to_recent(mut self) -> Self {
self.add_to_recent = true;
self
}

/// Create new InputReactions with one emoticon reaction
pub fn emoticon<S: Into<String>>(emoticon: S) -> Self {
Self {
reactions: vec![Reaction::Emoji(tl::types::ReactionEmoji {
emoticon: emoticon.into(),
})],
..Self::default()
}
}

/// Create new InputReactions with one custom emoji reaction
pub fn custom_emoji(document_id: i64) -> Self {
Self {
reactions: vec![Reaction::CustomEmoji(tl::types::ReactionCustomEmoji {
document_id,
})],
..Self::default()
}
}
}

impl Default for InputReactions {
fn default() -> Self {
Self {
reactions: vec![],
add_to_recent: false,
big: false,
}
}
}

impl Into<InputReactions> for String {
fn into(self) -> InputReactions {
InputReactions::emoticon(self)
}
}

impl Into<InputReactions> for &str {
fn into(self) -> InputReactions {
InputReactions::emoticon(self)
}
}

impl From<Vec<Reaction>> for InputReactions {
fn from(reactions: Vec<Reaction>) -> Self {
Self {
reactions,
..Self::default()
}
}
}

impl Into<Vec<Reaction>> for InputReactions {
fn into(self) -> Vec<Reaction> {
return self.reactions;
}
}
11 changes: 4 additions & 7 deletions lib/grammers-client/src/types/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

use std::sync::Arc;

use super::{inline::send::InlineSend, CallbackQuery, ChatMap, InlineQuery, Message};
use super::{CallbackQuery, ChatMap, InlineQuery, InlineSend, Message};
use crate::{types::MessageDeletion, Client};
use grammers_tl_types as tl;

Expand All @@ -27,7 +27,7 @@ pub enum Update {
/// Occurs whenever you sign in as a bot and a user sends an inline query
/// such as `@bot query`.
InlineQuery(InlineQuery),
/// Occurs whenever you sign in as a bot and a user chooses result from an inline query answer.
/// Represents an update of user choosing the result of inline query and sending it to their chat partner.
InlineSend(InlineSend),
/// Raw events are not actual events.
/// Instead, they are the raw Update object that Telegram sends. You
Expand All @@ -40,11 +40,8 @@ pub enum Update {
}

impl Update {
pub(crate) fn new(
client: &Client,
update: tl::enums::Update,
chats: &Arc<ChatMap>,
) -> Option<Self> {
/// Create new friendly to use Update from its raw version and chat map
pub fn new(client: &Client, update: tl::enums::Update, chats: &Arc<ChatMap>) -> Option<Self> {
match update {
// NewMessage
tl::enums::Update::NewMessage(tl::types::UpdateNewMessage { message, .. }) => {
Expand Down
Loading