1
Fork 0
mirror of https://github.com/Steffo99/patched-porobot.git synced 2024-12-23 01:54:22 +00:00

Again, I'm not sure of what is currently being merged

This commit is contained in:
Steffo 2022-10-20 14:32:57 +00:00 committed by GitHub
commit 23d504b0cc
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 29 deletions

View file

@ -72,7 +72,7 @@
//! //!
//! Since [@patchedporobot] uses [`tantivy`] internally, you might find more information on even more advanced queries in the [documentation of their `QueryParser`](tantivy::query::QueryParser)! //! Since [@patchedporobot] uses [`tantivy`] internally, you might find more information on even more advanced queries in the [documentation of their `QueryParser`](tantivy::query::QueryParser)!
//! //!
//! ### Deck queries //! ### Deck parsing
//! //!
//! You can have [@patchedporobot] display a deck and its cards by pasting the deck code after the bot's username: //! You can have [@patchedporobot] display a deck and its cards by pasting the deck code after the bot's username:
//! //!
@ -82,6 +82,15 @@
//! //!
//! Then, select the "Deck with N cards" option to send the deck's card list in the chat! //! Then, select the "Deck with N cards" option to send the deck's card list in the chat!
//! //!
//! #### Named decks
//!
//! Optionally, you may add a name to your deck, which will be displayed above the deck code:
//!
//! ```text
//! @patchedporobot CIBQCAICAQAQGBQIBEBAMBAJBMGBUHJNGE4AEAIBAIYQEAQGEU2QCAIBAIUQ Gimbo's Depths
//! ```
//!
//! If entered correctly, the bot will display a slightly different option containing the deck's name (_Deck "NAME" with N cards_), which you can check before the message is sent to the chat.
//! //!
//! [@patchedporobot]: https://t.me/patchedporobot //! [@patchedporobot]: https://t.me/patchedporobot

View file

@ -198,9 +198,7 @@ impl Deck {
let card_count = reader.read_u32_varint().map_err(DeckDecodingError::Read)?; let card_count = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
let set = reader.read_u32_varint().map_err(DeckDecodingError::Read)?; let set = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
let set = CardSet::from(set) let set = format!("{:02}", &set);
.to_code()
.ok_or(DeckDecodingError::UnknownSet)?;
let region = reader.read_u32_varint().map_err(DeckDecodingError::Read)?; let region = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
let region = CardRegion::from(region) let region = CardRegion::from(region)
@ -229,8 +227,7 @@ impl Deck {
.write_u32_varint(len) .write_u32_varint(len)
.map_err(DeckEncodingError::Write)?; .map_err(DeckEncodingError::Write)?;
let set: u32 = CardSet::from_code(set) let set: u32 = set.parse()
.try_into()
.map_err(|_| DeckEncodingError::UnknownSet)?; .map_err(|_| DeckEncodingError::UnknownSet)?;
writer writer
.write_u32_varint(set) .write_u32_varint(set)
@ -484,9 +481,9 @@ pub type DeckEncodingResult<T> = Result<T, DeckEncodingError>;
#[macro_export] #[macro_export]
macro_rules! deck { macro_rules! deck {
[$($cd:literal: $qty:literal),* $(,)?] => { [$($cd:literal: $qty:literal),* $(,)?] => {
crate::data::deckcode::deck::Deck { $crate::data::deckcode::deck::Deck {
contents: std::collections::HashMap::from([ contents: std::collections::HashMap::from([
$((crate::data::setbundle::code::CardCode { full: $cd.to_string() }, $qty),)* $(($crate::data::setbundle::code::CardCode { full: $cd.to_string() }, $qty),)*
]) ])
} }
} }

View file

@ -55,7 +55,9 @@ impl CardSet {
hm.get(self) hm.get(self)
} }
/// Get the [`CardSet`] from its short code, **assuming it is not an [`CardSet::Events`] card**. /// Get the [`CardSet`] from its short code.
///
/// [`CardSet::Worldwalker`] and [`CardSet::TheDarkinSaga`] share the same code `06`, so a variant cannot be determined.
/// ///
/// [`CardSet::Events`] cards have the short code of the set they were released in, so it is impossible to determine if a card belongs to that set from its short code. /// [`CardSet::Events`] cards have the short code of the set they were released in, so it is impossible to determine if a card belongs to that set from its short code.
pub fn from_code(value: &str) -> Self { pub fn from_code(value: &str) -> Self {
@ -65,7 +67,6 @@ impl CardSet {
"03" => Self::CallOfTheMountain, "03" => Self::CallOfTheMountain,
"04" => Self::EmpiresOfTheAscended, "04" => Self::EmpiresOfTheAscended,
"05" => Self::BeyondTheBandlewood, "05" => Self::BeyondTheBandlewood,
"06" => Self::Worldwalker,
_ => Self::Unsupported, _ => Self::Unsupported,
} }
@ -84,6 +85,7 @@ impl CardSet {
Self::EmpiresOfTheAscended => Some("04".to_string()), Self::EmpiresOfTheAscended => Some("04".to_string()),
Self::BeyondTheBandlewood => Some("05".to_string()), Self::BeyondTheBandlewood => Some("05".to_string()),
Self::Worldwalker => Some("06".to_string()), Self::Worldwalker => Some("06".to_string()),
Self::TheDarkinSaga => Some("06".to_string()),
_ => None, _ => None,
} }
@ -92,6 +94,8 @@ impl CardSet {
/// Get the [`CardSet`] from its internal id. /// Get the [`CardSet`] from its internal id.
/// ///
/// [`CardSet::Worldwalker`] and [`CardSet::TheDarkinSaga`] share the same id, so a variant cannot be determined.
///
/// [`CardSet::Events`] cards have the id of the set they were released in, so it is impossible to determine if a card belongs to that set from its id. /// [`CardSet::Events`] cards have the id of the set they were released in, so it is impossible to determine if a card belongs to that set from its id.
impl From<u32> for CardSet { impl From<u32> for CardSet {
fn from(value: u32) -> Self { fn from(value: u32) -> Self {
@ -101,7 +105,6 @@ impl From<u32> for CardSet {
3 => CardSet::CallOfTheMountain, 3 => CardSet::CallOfTheMountain,
4 => CardSet::EmpiresOfTheAscended, 4 => CardSet::EmpiresOfTheAscended,
5 => CardSet::BeyondTheBandlewood, 5 => CardSet::BeyondTheBandlewood,
6 => CardSet::Worldwalker,
_ => CardSet::Unsupported, _ => CardSet::Unsupported,
} }
} }
@ -121,6 +124,7 @@ impl TryFrom<CardSet> for u32 {
CardSet::EmpiresOfTheAscended => Ok(4), CardSet::EmpiresOfTheAscended => Ok(4),
CardSet::BeyondTheBandlewood => Ok(5), CardSet::BeyondTheBandlewood => Ok(5),
CardSet::Worldwalker => Ok(6), CardSet::Worldwalker => Ok(6),
CardSet::TheDarkinSaga => Ok(6),
_ => Err(()), _ => Err(()),
} }
} }

View file

@ -153,10 +153,10 @@ fn display_levelup(levelup: &String) -> String {
} }
} }
/// Render a [Deck] in [Telegram Bot HTML]. /// Render a [Deck] in [Telegram Bot HTML], with an optional `name`.
/// ///
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style /// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
pub fn display_deck(index: &CardIndex, deck: &Deck, code: String) -> String { pub fn display_deck(index: &CardIndex, deck: &Deck, code: &str, name: &Option<&str>) -> String {
// TODO: optimize this // TODO: optimize this
let cards = deck let cards = deck
.contents .contents
@ -182,5 +182,8 @@ pub fn display_deck(index: &CardIndex, deck: &Deck, code: String) -> String {
}) })
.join("\n"); .join("\n");
format!("<code>{}</code>\n\n{}", &code, &cards) match name {
Some(name) => format!("<b><u>{}</u></b>\n<code>{}</code>\n\n{}", &name, &code, &cards),
None => format!("<code>{}</code>\n\n{}", &code, &cards),
}
} }

View file

@ -10,6 +10,8 @@ use teloxide::payloads::{AnswerInlineQuery, SendMessage};
use teloxide::prelude::*; use teloxide::prelude::*;
use teloxide::requests::{JsonRequest, ResponseResult}; use teloxide::requests::{JsonRequest, ResponseResult};
use teloxide::types::{ParseMode, Recipient}; use teloxide::types::{ParseMode, Recipient};
use lazy_static::lazy_static;
use regex::Regex;
/// Handle inline queries by searching cards on the [CardSearchEngine]. /// Handle inline queries by searching cards on the [CardSearchEngine].
pub fn inline_query_handler( pub fn inline_query_handler(
@ -33,11 +35,20 @@ pub fn inline_query_handler(
}; };
} }
if let Ok(deck) = Deck::from_code(&query.query.to_ascii_uppercase()) { lazy_static! {
static ref DECK_RE: Regex = Regex::new(r#"^(?P<code>[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]+)(?:\s+(?P<name>.+?))?\s*$"#).unwrap();
}
if let Some(deck_captures) = DECK_RE.captures(&query.query) {
if let Some(deck_code) = deck_captures.name("code") {
if let Ok(deck) = Deck::from_code(&deck_code.as_str()) {
debug!("Parsed deck successfully!"); debug!("Parsed deck successfully!");
let name = deck_captures.name("name").map(|m| m.as_str());
break AnswerInlineQuery { break AnswerInlineQuery {
inline_query_id: query.id.clone(), inline_query_id: query.id.clone(),
results: vec![deck_to_inlinequeryresult(&engine.cards, &deck)], results: vec![deck_to_inlinequeryresult(&engine.cards, &deck, &name)],
cache_time: None, cache_time: None,
is_personal: Some(false), is_personal: Some(false),
next_offset: None, next_offset: None,
@ -45,6 +56,8 @@ pub fn inline_query_handler(
switch_pm_parameter: None, switch_pm_parameter: None,
}; };
} }
}
}
debug!("Querying the card search engine..."); debug!("Querying the card search engine...");
let results = engine.query(&query.query, 50); let results = engine.query(&query.query, 50);

View file

@ -43,17 +43,20 @@ pub fn card_to_inlinequeryresult(
}) })
} }
/// Convert a [Deck] into a [InlineQueryResult]. /// Convert a [Deck] with an optional name into a [InlineQueryResult].
pub fn deck_to_inlinequeryresult(index: &CardIndex, deck: &Deck) -> InlineQueryResult { pub fn deck_to_inlinequeryresult(index: &CardIndex, deck: &Deck, name: &Option<&str>) -> InlineQueryResult {
let code = deck let code = deck
.to_code(DeckCodeFormat::F1) .to_code(DeckCodeFormat::F1)
.expect("serialized deck to deserialize properly"); .expect("serialized deck to deserialize properly");
InlineQueryResult::Article(InlineQueryResultArticle { InlineQueryResult::Article(InlineQueryResultArticle {
id: format!("{:x}", md5::compute(&code)), id: format!("{:x}", md5::compute(&code)),
title: format!("Deck with {} cards", deck.contents.len()), title: match &name {
Some(name) => format!(r#"Deck "{}" with {} cards"#, name, deck.contents.len()),
None => format!("Deck with {} cards", deck.contents.len())
},
input_message_content: InputMessageContent::Text(InputMessageContentText { input_message_content: InputMessageContent::Text(InputMessageContentText {
message_text: display_deck(index, deck, code), message_text: display_deck(index, deck, &code, &name),
parse_mode: Some(ParseMode::Html), parse_mode: Some(ParseMode::Html),
entities: None, entities: None,
disable_web_page_preview: Some(true), disable_web_page_preview: Some(true),