Skip to content

Commit

Permalink
display stickers by date added, display emoji names
Browse files Browse the repository at this point in the history
  • Loading branch information
avoonix committed Aug 7, 2024
1 parent c8be953 commit 5935fbe
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 35 deletions.
3 changes: 3 additions & 0 deletions fuzzle/src/callback/callback_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub enum CallbackData {
GeneralStats,
PersonalStats,
LatestSets,
LatestStickers,
Info,

RemoveBlacklistedTag(String),
Expand Down Expand Up @@ -190,6 +191,7 @@ fn parse_simple(input: &str) -> IResult<&str, CallbackData> {
map(tag("gstats"), |_| CallbackData::GeneralStats),
map(tag("pstats"), |_| CallbackData::PersonalStats),
map(tag("lsets"), |_| CallbackData::LatestSets),
map(tag("lstickers"), |_| CallbackData::LatestStickers),
map(tag("help"), |_| CallbackData::Help),
map(tag("blacklist"), |_| CallbackData::Blacklist),
map(tag("info"), |_| CallbackData::Info),
Expand Down Expand Up @@ -415,6 +417,7 @@ impl Display for CallbackData {
Self::GeneralStats => write!(f, "gstats"),
Self::PersonalStats => write!(f, "pstats"),
Self::LatestSets => write!(f, "lsets"),
Self::LatestStickers => write!(f, "lstickers"),
Self::FavoriteSticker {
operation,
sticker_id,
Expand Down
11 changes: 11 additions & 0 deletions fuzzle/src/callback/callback_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,17 @@ pub async fn callback_handler(
)
.await
}
CallbackData::LatestStickers => {
let changes = request_context.database.get_n_latest_sticker_changes(20).await?;
answer_callback_query(
request_context.clone(),
q,
Some(Text::latest_stickers(changes.clone())),
Some(Keyboard::latest_stickers(changes)),
None,
)
.await
}
CallbackData::PersonalStats => {
let stats = request_context
.database
Expand Down
15 changes: 13 additions & 2 deletions fuzzle/src/database/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ pub enum DialogState {
negative_sticker_id: Vec<String>,
},
TagCreator(TagCreator),
// TODO: use
// TODO: use
// bot.set_sticker_set_thumb(name, user_id); // as soon as the sticker pack has 4 stickers -> thumnail: first 3 stickers + fuzzle bot icon
// // not existing yet: setStickerEmojiList, setStickerKeywords
}
Expand All @@ -262,11 +262,22 @@ pub struct TagCreator {
pub example_sticker_id: Vec<String>,
#[serde(default)]
pub aliases: Vec<String>,

// TODO: when transitioning from/to other modes, keep some of the data
// eg example_sticker_id could become positive_sticker_id
}

// TODO: test that defaults work
// - database null -> Normal
// - database ContinuousTag {} -> defaults for add_tag and remove_tag

#[derive(QueryableByName, Debug, Clone)]
pub struct StickerChange {
#[diesel(sql_type = diesel::sql_types::Text)]
pub sticker_id: String,
#[diesel(sql_type = diesel::sql_types::Text)]
pub sticker_set_id: String,
#[diesel(sql_type = diesel::sql_types::BigInt)]
pub today: i64,
#[diesel(sql_type = diesel::sql_types::BigInt)]
pub this_week: i64,
}
18 changes: 8 additions & 10 deletions fuzzle/src/database/queries/sticker_set.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
use base64::{engine::general_purpose, Engine};
use diesel::{
delete,
dsl::{count_star, now, sql},
insert_into,
prelude::*,
sql_types::BigInt,
update,
upsert::excluded,
delete, dsl::{count_star, now, sql}, insert_into, prelude::*, sql_query, sql_types::BigInt, update, upsert::excluded
};
use itertools::Itertools;
use r2d2::PooledConnection;
use tracing::warn;

use crate::{
database::{
query_builder::StickerTagQuery,
schema_model::{StickerFile, StickerSet},
Order, Sticker, StickerIdStickerFileId,
query_builder::StickerTagQuery, schema_model::{StickerFile, StickerSet}, Order, Sticker, StickerChange, StickerIdStickerFileId
},
util::Emoji,
};
Expand Down Expand Up @@ -182,6 +174,12 @@ impl Database {
.load(&mut self.pool.get()?)?)
}

#[tracing::instrument(skip(self), err(Debug))]
pub async fn get_n_latest_sticker_changes(&self, n: i64) -> Result<Vec<StickerChange>, DatabaseError> {
Ok(sql_query("select sticker.id AS sticker_id, sticker_set_id, count(case when julianday('now') - julianday(sticker_file.created_at) < 1 then true else null end) as today, count(case when julianday('now') - julianday(sticker_file.created_at) < 7 then true else null end) as this_week from sticker inner join sticker_file on sticker.sticker_file_id = sticker_file.id where julianday('now') - julianday(sticker_file.created_at) < 7 group by sticker_set_id order by max(sticker_file.created_at) desc limit 10;")
.load(&mut self.pool.get()?)?)
}

#[tracing::instrument(skip(self), err(Debug))]
pub async fn get_owned_sticker_sets(
&self,
Expand Down
17 changes: 17 additions & 0 deletions fuzzle/src/inline/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub enum InlineQueryData {
ListOverlappingSets {
sticker_id: String,
},
ListSetStickersByDate {
sticker_id: String,
},
ListSimilarStickers {
unique_id: String,
aspect: SimilarityAspect,
Expand Down Expand Up @@ -188,6 +191,11 @@ impl InlineQueryData {
Self::ListOverlappingSets { sticker_id }
}

#[must_use]
pub fn set_stickers_by_date(sticker_id: String) -> Self {
Self::ListSetStickersByDate { sticker_id }
}

#[must_use]
pub fn all_set_tags(sticker_id: String) -> Self {
Self::ListAllTagsFromSet { sticker_id }
Expand Down Expand Up @@ -328,6 +336,12 @@ fn parse_inline_query_data(input: &str) -> IResult<&str, InlineQueryData> {
sticker_id: sticker_id.to_string(),
},
),
map(
terminated(preceded(tag("(dates:"), sticker_id_literal), tag(")")),
|sticker_id| InlineQueryData::ListSetStickersByDate {
sticker_id: sticker_id.to_string(),
},
),
map(
terminated(preceded(tag("(settags:"), sticker_id_literal), tag(")")),
|sticker_id| InlineQueryData::ListAllTagsFromSet {
Expand Down Expand Up @@ -449,6 +463,9 @@ impl Display for InlineQueryData {
InlineQueryData::ListOverlappingSets { sticker_id } => {
write!(f, "(overlap:{sticker_id}) ")
}
InlineQueryData::ListSetStickersByDate { sticker_id } => {
write!(f, "(dates:{sticker_id}) ")
}
InlineQueryData::ListAllTagsFromSet { sticker_id } => {
write!(f, "(settags:{sticker_id}) ")
}
Expand Down
76 changes: 71 additions & 5 deletions fuzzle/src/inline/inline_query_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::message::{Keyboard, StartParameter};
use crate::sticker::{compute_similar, find_with_text_embedding, with_sticker_id};
use crate::tags::TagManager;
use crate::text::{Markdown, Text};
use crate::util::{create_sticker_set_id, create_tag_id, Emoji, Required};
use crate::util::{create_sticker_set_id, create_tag_id, format_relative_time, Emoji, Required};
use itertools::Itertools;
use num_traits::ToPrimitive;
use std::convert::TryFrom;
Expand Down Expand Up @@ -662,6 +662,9 @@ pub async fn inline_query_handler(
InlineQueryData::ListOverlappingSets { sticker_id } => {
handle_overlapping_sets(current_offset, sticker_id, q, request_context).await
}
InlineQueryData::ListSetStickersByDate { sticker_id } => {
handle_stickers_by_date(current_offset, sticker_id, q, request_context).await
}
InlineQueryData::ListAllTagsFromSet { sticker_id } => {
handle_all_set_tags(current_offset, sticker_id, q, request_context).await
}
Expand Down Expand Up @@ -926,10 +929,13 @@ async fn handle_most_used_emojis(
let thumbnail_url =
format!("https://placehold.co/{THUMBNAIL_SIZE}/007f0e/black.png?text={rank}");
let thumbnail_url = Url::parse(&thumbnail_url)?;
let emo = emojis::get(&emoji.to_string_with_variant())
.or_else(|| emojis::get(&emoji.to_string_without_variant()));
let description = emo.map_or("".to_string(), |emo| emo.name().to_string());
Ok::<InlineQueryResult, BotError>(
InlineQueryResultArticle::new(
InlineQueryResultId::Emoji(emoji.clone()).to_string(),
emoji.to_string_with_variant(),
format!("{} {}", emoji.to_string_with_variant(), description),
InputMessageContent::Text(InputMessageContentText::new(Markdown::escaped(
emoji.to_string_with_variant(),
))),
Expand Down Expand Up @@ -1178,7 +1184,9 @@ async fn handle_user_sets(

let mut articles = vec![];
for set in sets {
request_context.process_sticker_set(set.id.clone(), false).await;
request_context
.process_sticker_set(set.id.clone(), false)
.await;
// TODO: use futuresunordered
let url = format!(
"https://fuzzle-bot.avoonix.com/thumbnails/sticker-set/{}/image.png",
Expand All @@ -1204,8 +1212,7 @@ async fn handle_user_sets(
set_title,
content,
)
.description(
if sticker_in_set.is_some() {
.description(if sticker_in_set.is_some() {
"❌ Remove from this set"
} else {
"βœ… Add to this set"
Expand Down Expand Up @@ -1260,3 +1267,62 @@ async fn handle_user_sets(

Ok(())
}

#[tracing::instrument(skip(q, request_context))]
async fn handle_stickers_by_date(
current_offset: QueryPage,
sticker_id: String,
q: InlineQuery,
request_context: RequestContext,
) -> Result<(), BotError> {
let set = request_context
.database
.get_sticker_set_by_sticker_id(&sticker_id)
.await?
.required()?;
let stickers = request_context
.database
.get_all_stickers_in_set(&set.id)
.await?;

let r = stickers
.into_iter()
.sorted_by_key(|s| s.created_at) // TODO: should we use the sticker_file created_at here?
.rev()
.chunk_by(|s| format_relative_time(s.created_at))
.into_iter()
.flat_map(|(key, chunk)| {
// TODO: this looks weird in telegram
let mut res = vec![InlineQueryResultArticle::new(
InlineQueryResultId::Other(key.clone()).to_string(),
format!("{}", &key),
InputMessageContent::Text(InputMessageContentText::new(Markdown::escaped(
format!("{}", key),
))),
)
.into()];
for sticker in chunk {
res.push(
InlineQueryResultCachedSticker::new(
InlineQueryResultId::Sticker(sticker.id).to_string(),
sticker.telegram_file_identifier,
)
.into(),
);
}
res
})
.skip(current_offset.skip())
.take(current_offset.page_size())
.collect_vec();

require_some_results("stickers", current_offset, r.len())?;
request_context
.bot
.answer_inline_query(q.id, r.clone())
.next_offset(current_offset.next_query_offset(r.len()))
.cache_time(0) // in seconds // TODO: constant?
.await?;

Ok(())
}
57 changes: 41 additions & 16 deletions fuzzle/src/message/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::{
bot::InternalError,
callback::CallbackData,
database::{Sticker, TagCreator, UserSettings, UserStats},
database::{Sticker, StickerChange, TagCreator, UserSettings, UserStats},
inline::{InlineQueryData, SetOperation, TagKind},
tags::{self, all_count_tags, all_rating_tags, character_count, rating, Category, Characters},
util::{format_relative_time, Emoji},
Expand Down Expand Up @@ -316,7 +316,8 @@ impl Keyboard {
},
),
],
vec![favorite_button(is_favorite, sticker_id),
vec![
favorite_button(is_favorite, sticker_id),
InlineKeyboardButton::switch_inline_query_current_chat(
"πŸ”§ Add to your set",
InlineQueryData::add_to_user_set(sticker_id.to_string()),
Expand Down Expand Up @@ -453,7 +454,7 @@ impl Keyboard {
pub fn general_stats() -> InlineKeyboardMarkup {
InlineKeyboardMarkup::new(vec![
vec![
InlineKeyboardButton::callback("⬅️ Latest Sets", CallbackData::LatestSets),
InlineKeyboardButton::callback("⬅️ Latest Stickers", CallbackData::LatestStickers),
InlineKeyboardButton::callback("Personal Stats ➑️", CallbackData::PersonalStats),
],
vec![InlineKeyboardButton::switch_inline_query_current_chat(
Expand Down Expand Up @@ -487,10 +488,28 @@ impl Keyboard {
pub fn latest_sets() -> InlineKeyboardMarkup {
InlineKeyboardMarkup::new([[
InlineKeyboardButton::callback("⬅️ Popular Tags", CallbackData::PopularTags),
InlineKeyboardButton::callback("General Stats ➑️", CallbackData::GeneralStats),
InlineKeyboardButton::callback("Latest Stickers ➑️", CallbackData::LatestStickers),
]])
}

#[must_use]
pub fn latest_stickers(changes: Vec<StickerChange>) -> InlineKeyboardMarkup {
let mut markup = InlineKeyboardMarkup::new(vec![vec![
InlineKeyboardButton::callback("⬅️ Latest Sets", CallbackData::LatestSets),
InlineKeyboardButton::callback("General Stats ➑️", CallbackData::GeneralStats),
]]);
for change in changes {
markup = markup.append_row(vec![
InlineKeyboardButton::switch_inline_query_current_chat(
format!("{}", change.sticker_set_id),
InlineQueryData::set_stickers_by_date(change.sticker_id), // TODO: change placeholder
),
]);
}

markup
}

#[must_use]
pub fn dialog_exit() -> InlineKeyboardMarkup {
InlineKeyboardMarkup::new([[InlineKeyboardButton::callback(
Expand Down Expand Up @@ -653,31 +672,37 @@ impl Keyboard {
) -> InlineKeyboardMarkup {
let now = chrono::Utc::now().naive_utc();

InlineKeyboardMarkup::new([
[InlineKeyboardButton::callback(
InlineKeyboardMarkup::new(vec![
vec![InlineKeyboardButton::callback(
"πŸ”™ Set",
CallbackData::Sticker {
sticker_id: sticker_id.to_string(),
operation: None,
},
)],
[InlineKeyboardButton::callback(
format!( "πŸ—“οΈ Set added {}", format_relative_time(created_at)),
vec![InlineKeyboardButton::callback(
format!("πŸ—“οΈ Set added {}", format_relative_time(created_at)),
CallbackData::NoAction,
)],
[InlineKeyboardButton::switch_inline_query_current_chat(
vec![InlineKeyboardButton::switch_inline_query_current_chat(
format!("πŸͺž Set overlaps"),
InlineQueryData::overlapping_sets(sticker_id.to_string()),
)],
[InlineKeyboardButton::switch_inline_query_current_chat(
format!("🏷️ All tags"),
InlineQueryData::all_set_tags(sticker_id.to_string()),
)],
[InlineKeyboardButton::switch_inline_query_current_chat(
vec![
InlineKeyboardButton::switch_inline_query_current_chat(
format!("🏷️ All tags"),
InlineQueryData::all_set_tags(sticker_id.to_string()),
),
InlineKeyboardButton::switch_inline_query_current_chat(
format!("πŸ—“οΈ All stickers by date added"),
InlineQueryData::set_stickers_by_date(sticker_id.to_string()),
),
],
vec![InlineKeyboardButton::switch_inline_query_current_chat(
format!("βž• Add tags to all stickers in the set \"{set_id}\""),
InlineQueryData::set_operation(set_id, vec![], SetOperation::Tag),
)],
[InlineKeyboardButton::switch_inline_query_current_chat(
vec![InlineKeyboardButton::switch_inline_query_current_chat(
format!("βž– Remove tags from all stickers in the set \"{set_id}\""),
InlineQueryData::set_operation(set_id, vec![], SetOperation::Untag),
)],
Expand Down Expand Up @@ -707,7 +732,7 @@ impl Keyboard {
},
)],
vec![InlineKeyboardButton::callback(
format!( "πŸ—“οΈ Sticker added {}", format_relative_time(created_at)),
format!("πŸ—“οΈ Sticker added {}", format_relative_time(created_at)),
CallbackData::NoAction,
)],
vec![
Expand Down
Loading

0 comments on commit 5935fbe

Please sign in to comment.