Skip to content

Commit

Permalink
Implement notifications for message tips
Browse files Browse the repository at this point in the history
  • Loading branch information
hpeebles committed Sep 22, 2023
1 parent 079ee0c commit e3a2632
Show file tree
Hide file tree
Showing 16 changed files with 266 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ use types::{ChannelId, CompletedCryptoTransaction, MessageId, MessageIndex, User

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub message_sender: UserId,
pub recipient: UserId,
pub channel_id: ChannelId,
pub thread_root_message_index: Option<MessageIndex>,
pub message_id: MessageId,
pub transfer: CompletedCryptoTransaction,
pub username: String,
pub display_name: Option<String>,
}

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub enum Response {
Success,
MessageNotFound,
CannotTipSelf,
MessageSenderMismatch,
RecipientMismatch,
NotAuthorized,
CommunityFrozen,
UserNotInCommunity,
Expand Down
37 changes: 34 additions & 3 deletions backend/canisters/community/impl/src/updates/c2c_tip_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ use crate::activity_notifications::handle_activity_notification;
use crate::{mutate_state, run_regular_jobs, RuntimeState};
use canister_api_macros::update_msgpack;
use canister_tracing_macros::trace;
use chat_events::Reader;
use community_canister::c2c_tip_message::{Response::*, *};
use group_chat_core::TipMessageResult;
use ledger_utils::format_crypto_amount_with_symbol;
use types::{ChannelMessageTipped, EventIndex, Notification};

#[update_msgpack]
#[trace]
Expand All @@ -26,22 +29,50 @@ fn c2c_tip_message_impl(args: Args, state: &mut RuntimeState) -> Response {

if let Some(channel) = state.data.channels.get_mut(&args.channel_id) {
let now = state.env.now();
let token = args.transfer.token();
let amount = args.transfer.units();

match channel.chat.tip_message(
user_id,
args.message_sender,
args.recipient,
args.thread_root_message_index,
args.message_id,
args.transfer,
now,
) {
TipMessageResult::Success => {
// TODO push notification
if let Some((message_index, message_event_index)) = channel
.chat
.events
.events_reader(EventIndex::default(), args.thread_root_message_index, now)
.and_then(|r| {
r.message_event_internal(args.message_id.into())
.map(|e| (e.event.message_index, e.index))
})
{
let notification = Notification::ChannelMessageTipped(ChannelMessageTipped {
community_id: state.env.canister_id().into(),
channel_id: channel.id,
thread_root_message_index: args.thread_root_message_index,
message_index,
message_event_index,
community_name: state.data.name.clone(),
channel_name: channel.chat.name.clone(),
tipped_by: user_id,
tipped_by_name: args.username,
tipped_by_display_name: args.display_name,
tip: format_crypto_amount_with_symbol(amount, token.decimals().unwrap_or(8), token.token_symbol()),
community_avatar_id: state.data.avatar.as_ref().map(|a| a.id),
channel_avatar_id: channel.chat.avatar.as_ref().map(|a| a.id),
});
state.push_notification(vec![args.recipient], notification);
}
handle_activity_notification(state);
Success
}
TipMessageResult::MessageNotFound => MessageNotFound,
TipMessageResult::CannotTipSelf => CannotTipSelf,
TipMessageResult::MessageSenderMismatch => MessageSenderMismatch,
TipMessageResult::RecipientMismatch => RecipientMismatch,
TipMessageResult::UserNotInGroup => ChannelNotFound,
TipMessageResult::NotAuthorized => NotAuthorized,
TipMessageResult::UserSuspended => UserSuspended,
Expand Down
7 changes: 3 additions & 4 deletions backend/canisters/exchange_bot/impl/src/commands/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::swap_client::SwapClient;
use crate::{mutate_state, RuntimeState};
use exchange_bot_canister::ExchangeId;
use lazy_static::lazy_static;
use ledger_utils::format_crypto_amount;
use ledger_utils::format_crypto_amount_with_symbol;
use rand::Rng;
use regex_lite::{Regex, RegexBuilder};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -118,9 +118,8 @@ impl QuoteCommand {

pub fn build_message_text(&self) -> String {
let mut text = format!(
"Quotes ({} {} to {}):",
format_crypto_amount(self.amount, self.input_token.decimals),
self.input_token.token.token_symbol(),
"Quotes ({} to {}):",
format_crypto_amount_with_symbol(self.amount, self.input_token.decimals, self.input_token.token.token_symbol()),
self.output_token.token.token_symbol()
);
for (exchange_id, status) in self.results.iter() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::commands::CommandSubTaskResult;
use ledger_utils::{convert_to_subaccount, format_crypto_amount};
use ledger_utils::{convert_to_subaccount, format_crypto_amount_with_symbol};
use types::icrc1::Account;
use types::{CanisterId, TokenInfo, UserId};

Expand All @@ -18,11 +18,7 @@ pub(crate) async fn check_user_balance(
.map(|a| u128::try_from(a.0).unwrap())
{
Ok(amount) => {
let text = format!(
"{} {}",
format_crypto_amount(amount, token.decimals),
token.token.token_symbol()
);
let text = format_crypto_amount_with_symbol(amount, token.decimals, token.token.token_symbol());
CommandSubTaskResult::Complete(amount, Some(text))
}
Err(error) => CommandSubTaskResult::Failed(format!("{error:?}")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::swap_client::SwapClient;
use exchange_bot_canister::ExchangeId;
use futures::stream::FuturesUnordered;
use futures::StreamExt;
use ledger_utils::format_crypto_amount;
use ledger_utils::format_crypto_amount_with_symbol;
use std::future::ready;

pub(crate) async fn get_quotes<C: FnMut(ExchangeId, CommandSubTaskResult<u128>)>(
Expand All @@ -30,11 +30,7 @@ async fn get_quote(client: Box<dyn SwapClient>, amount: u128) -> (ExchangeId, Co
let result = match response {
Ok(amount_out) => {
let output_token = client.output_token();
let text = format!(
"{} {}",
format_crypto_amount(amount_out, output_token.decimals),
output_token.token.token_symbol()
);
let text = format_crypto_amount_with_symbol(amount_out, output_token.decimals, output_token.token.token_symbol());
CommandSubTaskResult::Complete(amount_out, Some(text))
}
Err(error) => CommandSubTaskResult::Failed(format!("{error:?}")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use candid::Principal;
use canister_api_macros::update_msgpack;
use canister_tracing_macros::trace;
use exchange_bot_canister::handle_direct_message::*;
use ledger_utils::format_crypto_amount;
use ledger_utils::format_crypto_amount_with_symbol;
use local_user_index_canister_c2c_client::LookupUserError;
use types::{BotMessage, MessageContent, MessageContentInitial, UserId};

Expand All @@ -28,10 +28,10 @@ fn handle_direct_message_impl(message: MessageContent, state: &mut RuntimeState)

if let MessageContent::Crypto(c) = &message {
let token = c.transfer.token();
response_messages.push(convert_to_message(format!(
"{} {} received",
format_crypto_amount(c.transfer.units(), token.decimals().unwrap_or(8)),
token.token_symbol()
response_messages.push(convert_to_message(format_crypto_amount_with_symbol(
c.transfer.units(),
token.decimals().unwrap_or(8),
token.token_symbol(),
)));
}

Expand Down
6 changes: 4 additions & 2 deletions backend/canisters/group/api/src/updates/c2c_tip_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ use types::{CompletedCryptoTransaction, MessageId, MessageIndex, UserId};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub message_sender: UserId,
pub recipient: UserId,
pub thread_root_message_index: Option<MessageIndex>,
pub message_id: MessageId,
pub transfer: CompletedCryptoTransaction,
pub username: String,
pub display_name: Option<String>,
}

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub enum Response {
Success,
MessageNotFound,
CannotTipSelf,
MessageSenderMismatch,
RecipientMismatch,
NotAuthorized,
GroupFrozen,
UserNotInGroup,
Expand Down
37 changes: 34 additions & 3 deletions backend/canisters/group/impl/src/updates/c2c_tip_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ use crate::activity_notifications::handle_activity_notification;
use crate::{mutate_state, run_regular_jobs, RuntimeState};
use canister_api_macros::update_msgpack;
use canister_tracing_macros::trace;
use chat_events::Reader;
use group_canister::c2c_tip_message::{Response::*, *};
use group_chat_core::TipMessageResult;
use ledger_utils::format_crypto_amount_with_symbol;
use types::{EventIndex, GroupMessageTipped, Notification};

#[update_msgpack]
#[trace]
Expand All @@ -20,22 +23,50 @@ fn c2c_tip_message_impl(args: Args, state: &mut RuntimeState) -> Response {

let user_id = state.env.caller().into();
let now = state.env.now();
let token = args.transfer.token();
let amount = args.transfer.units();

match state.data.chat.tip_message(
user_id,
args.message_sender,
args.recipient,
args.thread_root_message_index,
args.message_id,
args.transfer,
now,
) {
TipMessageResult::Success => {
// TODO push notification
if let Some((message_index, message_event_index)) = state
.data
.chat
.events
.events_reader(EventIndex::default(), args.thread_root_message_index, now)
.and_then(|r| {
r.message_event_internal(args.message_id.into())
.map(|e| (e.event.message_index, e.index))
})
{
state.push_notification(
vec![args.recipient],
Notification::GroupMessageTipped(GroupMessageTipped {
chat_id: state.env.canister_id().into(),
thread_root_message_index: args.thread_root_message_index,
message_index,
message_event_index,
group_name: state.data.chat.name.clone(),
tipped_by: user_id,
tipped_by_name: args.username,
tipped_by_display_name: args.display_name,
tip: format_crypto_amount_with_symbol(amount, token.decimals().unwrap_or(8), token.token_symbol()),
group_avatar_id: state.data.chat.avatar.as_ref().map(|a| a.id),
}),
);
}
handle_activity_notification(state);
Success
}
TipMessageResult::MessageNotFound => MessageNotFound,
TipMessageResult::CannotTipSelf => CannotTipSelf,
TipMessageResult::MessageSenderMismatch => MessageSenderMismatch,
TipMessageResult::RecipientMismatch => RecipientMismatch,
TipMessageResult::UserNotInGroup => UserNotInGroup,
TipMessageResult::NotAuthorized => NotAuthorized,
TipMessageResult::UserSuspended => UserSuspended,
Expand Down
3 changes: 3 additions & 0 deletions backend/canisters/user/api/src/updates/c2c_tip_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ pub struct Args {
pub thread_root_message_index: Option<MessageIndex>,
pub message_id: MessageId,
pub transfer: CompletedCryptoTransaction,
pub username: String,
pub display_name: Option<String>,
pub user_avatar_id: Option<u128>,
}

#[derive(CandidType, Serialize, Deserialize, Debug)]
Expand Down
46 changes: 36 additions & 10 deletions backend/canisters/user/impl/src/updates/c2c_tip_message.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::{mutate_state, run_regular_jobs, RuntimeState};
use canister_api_macros::update_msgpack;
use canister_tracing_macros::trace;
use types::{EventIndex, UserId};
use chat_events::{Reader, TipMessageResult};
use ledger_utils::format_crypto_amount_with_symbol;
use types::{DirectMessageTipped, EventIndex, Notification, UserId};
use user_canister::c2c_tip_message::{Response::*, *};

#[update_msgpack]
Expand All @@ -17,15 +19,39 @@ fn c2c_tip_message_impl(args: Args, state: &mut RuntimeState) -> Response {
if let Some(chat) = state.data.direct_chats.get_mut(&user_id.into()) {
let now = state.env.now();
let my_user_id = state.env.canister_id().into();
chat.events.tip_message(
user_id,
my_user_id,
EventIndex::default(),
args.thread_root_message_index,
args.message_id,
args.transfer,
now,
);
let token = args.transfer.token();
let amount = args.transfer.units();

if matches!(
chat.events.tip_message(
user_id,
my_user_id,
EventIndex::default(),
args.thread_root_message_index,
args.message_id,
args.transfer,
now,
),
TipMessageResult::Success
) {
if let Some(event) = chat
.events
.main_events_reader(now)
.message_event_internal(args.message_id.into())
{
let notification = Notification::DirectMessageTipped(DirectMessageTipped {
them: user_id,
thread_root_message_index: args.thread_root_message_index,
message_index: event.event.message_index,
message_event_index: event.index,
username: args.username,
display_name: args.display_name,
tip: format_crypto_amount_with_symbol(amount, token.decimals().unwrap_or(8), token.token_symbol()),
user_avatar_id: args.user_avatar_id,
});
state.push_notification(my_user_id, notification);
}
}
}
Success
}
Loading

0 comments on commit e3a2632

Please sign in to comment.