From 6134e0215bffd350031eff876a0cfa442461b2a4 Mon Sep 17 00:00:00 2001 From: tretrauit Date: Sun, 7 Jan 2024 15:24:12 +0700 Subject: [PATCH] feat(katana): implement wl fetch from klu results --- swordfish-common/src/utils/katana.rs | 121 ++++++++++++++++++++++++++- swordfish/src/debug.rs | 112 ++++++++++++++++++++++++- swordfish/src/main.rs | 106 +++++++++++++++++++++-- 3 files changed, 331 insertions(+), 8 deletions(-) diff --git a/swordfish-common/src/utils/katana.rs b/swordfish-common/src/utils/katana.rs index f876fb4..8509c11 100644 --- a/swordfish-common/src/utils/katana.rs +++ b/swordfish-common/src/utils/katana.rs @@ -79,7 +79,7 @@ pub fn parse_cards_from_katana_kc_ow(content: &String) -> Vec { break; } wl_block.to_string() - }, + } None => break, }; wl_block.remove(0); @@ -115,3 +115,122 @@ pub fn parse_cards_from_katana_kc_ow(content: &String) -> Vec { } cards } + +// klu (Character Results) +/// +/// Given a string of the results of a katana klu command, parse it into a vector of cards. +/// +/// "content" is `fields[0].value` +/// +pub fn parse_cards_from_katana_klu_results(content: &String) -> Vec { + let mut cards: Vec = Vec::new(); + for line in content.split("\n") { + trace!("Parsing line: {}", line); + if !line.ends_with("**") { + continue; + } + // Split into ['', '1', '. ', '♡448', " · Frieren: Beyond Journey's End · **Frieren**"] + // But we need 4th and 5th ones. + let mut line_split = line.split("`"); + let mut wl_str = match line_split.nth(3) { + Some(wl_str) => wl_str.to_string(), + None => { + error!("Failed to parse wishlist number: {}", line); + continue; + } + }; + wl_str.remove(0); + wl_str = wl_str.trim().to_string(); + let wishlist = match wl_str.parse::() { + Ok(wishlist) => wishlist, + Err(_) => { + error!("Failed to parse wishlist number: {}", wl_str); + continue; + } + }; + // Split to get character name and series + let mut char_series_split = match line_split.next() { + Some(char_series_split) => char_series_split.split(" · "), + None => { + error!("Failed to parse character name and series: {}", line); + continue; + } + }; + let series = match char_series_split.nth(1) { + Some(series) => series.to_string(), + None => { + error!("Failed to parse series: {}", line); + continue; + } + }; + let name = match char_series_split.next() { + Some(name) => { + let mut name_string = name.to_string(); + name_string.remove_matches("**"); + name_string + } + None => { + error!("Failed to parse character name: {}", line); + continue; + } + }; + let card = Card { + wishlist: Some(wishlist), + name, + series, + print: 0, + last_update_ts: 0, + }; + trace!("Parsed card: {:?}", card); + cards.push(card); + } + cards +} + +// klu (Character Lookup) +pub fn parse_cards_from_katana_klu_lookup(content: &String) -> Option { + let mut lines = content.split("\n"); + // Character + let mut line_split = lines.nth(0).unwrap().split(" · "); + let name = match line_split.nth(1) { + Some(name) => { + let mut name_string = name.to_string(); + name_string.remove_matches("**"); + name_string + } + None => return None, + }; + // Series + let mut line_split = lines.nth(0).unwrap().split(" · "); + let series = match line_split.nth(1) { + Some(series) => { + let mut series_string = series.to_string(); + series_string.remove_matches("**"); + series_string + } + None => return None, + }; + // Wishlist + let mut line_split = lines.nth(1).unwrap().split(" · "); + let wishlist = match line_split.nth(1) { + Some(series) => { + let mut series_string = series.to_string(); + series_string.remove_matches("**"); + match series_string.parse::() { + Ok(wishlist) => wishlist, + Err(_) => { + error!("Failed to parse wishlist number: {}", series_string); + return None; + } + } + } + None => return None, + }; + Some(Card { + wishlist: Some(wishlist), + name, + series, + print: 0, + last_update_ts: 0, + }) +} diff --git a/swordfish/src/debug.rs b/swordfish/src/debug.rs index 7426210..a82b238 100644 --- a/swordfish/src/debug.rs +++ b/swordfish/src/debug.rs @@ -1,7 +1,7 @@ -use crate::CONFIG; use crate::helper; use crate::katana; use crate::utils; +use crate::CONFIG; use serenity::framework::standard::CommandResult; use serenity::model::{ channel::Message, @@ -169,6 +169,91 @@ pub async fn dbg_parse_katana_kc_ow(ctx: &Context, msg: &Message) -> CommandResu Ok(()) } +pub async fn dbg_parse_katana_klu_results(ctx: &Context, msg: &Message) -> CommandResult { + let target_msg = match dbg_get_message("embed", ctx, msg).await { + Ok(msg) => msg, + Err(_) => { + return Ok(()); + } + }; + if target_msg.embeds.len() == 0 { + helper::error_message( + ctx, + msg, + "Message does not contain any embeds".to_string(), + None, + ) + .await; + return Ok(()); + } + let embed = &target_msg.embeds[0]; + let fields = match embed.fields.len() { + 0 => { + helper::error_message( + ctx, + msg, + "Embed does not contain any fields".to_string(), + None, + ) + .await; + return Ok(()); + } + _ => &embed.fields, + }; + let embed_field = fields.get(0).unwrap(); + let cards = utils::katana::parse_cards_from_katana_klu_results(&embed_field.value); + helper::info_message( + ctx, + msg, + format!("Parsed cards: ```\n{:?}\n```", cards), + None, + ) + .await; + Ok(()) +} + +pub async fn dbg_parse_katana_klu_lookup(ctx: &Context, msg: &Message) -> CommandResult { + let target_msg = match dbg_get_message("embed", ctx, msg).await { + Ok(msg) => msg, + Err(_) => { + return Ok(()); + } + }; + if target_msg.embeds.len() == 0 { + helper::error_message( + ctx, + msg, + "Message does not contain any embeds".to_string(), + None, + ) + .await; + return Ok(()); + } + let embed = &target_msg.embeds[0]; + let embed_description = match embed.description { + Some(ref description) => description, + None => { + helper::error_message( + ctx, + msg, + "Embed does not contain a description".to_string(), + None, + ) + .await; + return Ok(()); + } + }; + let card = match utils::katana::parse_cards_from_katana_klu_lookup(embed_description) { + Some(card) => card, + None => { + helper::error_message(ctx, msg, "Failed to parse card".to_string(), None).await; + return Ok(()); + } + }; + helper::info_message(ctx, msg, format!("Parsed card: ```\n{:?}\n```", card), None).await; + Ok(()) +} + pub async fn dbg_embed(ctx: &Context, msg: &Message) -> CommandResult { let target_msg = match dbg_get_message("embed", ctx, msg).await { Ok(msg) => msg, @@ -195,6 +280,23 @@ pub async fn dbg_embed(ctx: &Context, msg: &Message) -> CommandResult { Some(ref description) => description, None => "None", }; + let embed_footer_text = match embed.footer { + Some(ref footer) => footer.text.as_str(), + None => "None", + }; + let fields_text = match embed.fields.len() { + 0 => "```\nNone\n```".to_string(), + _ => { + let mut fields_text = String::new(); + for field in &embed.fields { + fields_text.push_str(&format!( + "Name: `{}`\nValue: ```\n{}\n```\nInline: `{}`\n", + field.name, field.value, field.inline + )); + } + fields_text + } + }; helper::info_message( ctx, msg, @@ -206,8 +308,14 @@ pub async fn dbg_embed(ctx: &Context, msg: &Message) -> CommandResult { Description: \n\ ```\n\ {}\n\ + ```\n\ + Fields: \n\ + {}\n\ + Footer Text: \n\ + ```\n\ + {}\n\ ```", - embed_title, embed_description + embed_title, embed_description, fields_text, embed_footer_text ), Some("Embed information".to_string()), ) diff --git a/swordfish/src/main.rs b/swordfish/src/main.rs index 1ccce3d..4015978 100644 --- a/swordfish/src/main.rs +++ b/swordfish/src/main.rs @@ -1,6 +1,6 @@ #![feature(lazy_cell)] use dotenvy::dotenv; -use serenity::all::MessageUpdateEvent; +use serenity::all::{Embed, MessageUpdateEvent}; use serenity::async_trait; use serenity::framework::standard::macros::{command, group}; use serenity::framework::standard::{CommandResult, Configuration, StandardFramework}; @@ -67,13 +67,19 @@ impl EventHandler for Handler { } }; trace!("Message update: {}, sender: {}", content, author.id); - if author.id.get() == constants::QINGQUE_ID { - parse_qingque(&ctx, event).await.unwrap(); + match author.id.get() { + constants::KATANA_ID => { + parse_katana_event(&ctx, event).await.unwrap(); + } + constants::QINGQUE_ID => { + parse_qingque_event(&ctx, event).await.unwrap(); + } + _ => {} } } } -async fn parse_qingque(ctx: &Context, event: MessageUpdateEvent) -> Result<(), String> { +async fn parse_qingque_event(ctx: &Context, event: MessageUpdateEvent) -> Result<(), String> { if event.embeds.is_none() || event.embeds.clone().unwrap().len() == 0 { return Ok(()); } @@ -106,6 +112,15 @@ async fn parse_qingque(ctx: &Context, event: MessageUpdateEvent) -> Result<(), S Ok(()) } +async fn parse_katana_event(ctx: &Context, event: MessageUpdateEvent) -> Result<(), String> { + if event.embeds.is_none() || event.embeds.clone().unwrap().len() == 0 { + return Ok(()); + } + let embed = &event.embeds.unwrap()[0]; + parse_katana_embed(embed).await; + Ok(()) +} + async fn parse_katana(ctx: &Context, msg: &Message) -> Result<(), String> { if msg.content.contains("is dropping 3 cards!") || msg @@ -171,10 +186,89 @@ async fn parse_katana(ctx: &Context, msg: &Message) -> Result<(), String> { .await; } }; + } else { + if msg.embeds.len() == 0 { + return Ok(()); + } + let embed = &msg.embeds[0]; + parse_katana_embed(embed).await; } Ok(()) } +async fn parse_katana_embed(embed: &Embed) { + match embed.author { + Some(ref author) => match author.name.as_str() { + "Card Collection" => { + let cards = utils::katana::parse_cards_from_katana_kc_ow( + &embed.description.as_ref().unwrap(), + ); + if cards.len() == 0 { + return; + } + trace!("Begin importing cards"); + match database::katana::write_cards(cards).await { + Ok(_) => { + trace!("Imported successully"); + } + Err(why) => { + error!("Failed to import card: {:?}", why); + } + } + } + _ => {} + }, + None => {} + }; + match embed.title { + Some(ref title) => match title.as_str() { + "Character Lookup" => { + let card = match utils::katana::parse_cards_from_katana_klu_lookup( + &embed.description.as_ref().unwrap(), + ) { + Some(card) => card, + None => { + return; + } + }; + trace!("Begin importing a card"); + match database::katana::write_card(card).await { + Ok(_) => { + trace!("Imported successully"); + } + Err(why) => { + error!("Failed to import card: {:?}", why); + } + } + } + "Character Results" => { + let fields = match embed.fields.len() { + 0 => { + return; + } + _ => &embed.fields, + }; + let embed_field = fields.get(0).unwrap(); + let cards = utils::katana::parse_cards_from_katana_klu_results(&embed_field.value); + if cards.len() == 0 { + return; + } + trace!("Begin importing cards"); + match database::katana::write_cards(cards).await { + Ok(_) => { + trace!("Imported successully"); + } + Err(why) => { + error!("Failed to import card: {:?}", why); + } + } + } + _ => {} + }, + None => {} + }; +} + #[tokio::main] async fn main() { match dotenv() { @@ -229,7 +323,7 @@ async fn ping(ctx: &Context, msg: &Message) -> CommandResult { #[command] async fn debug(ctx: &Context, msg: &Message) -> CommandResult { let config = CONFIG.get().unwrap(); - if !["debug", "trace"].contains(&config.log.level.as_str()){ + if !["debug", "trace"].contains(&config.log.level.as_str()) { return Ok(()); } if !config.debug.allowed_users.contains(&msg.author.id.get()) { @@ -256,6 +350,8 @@ async fn debug(ctx: &Context, msg: &Message) -> CommandResult { "embed" => debug::dbg_embed(ctx, msg).await?, "parse-qingque-atopwl" => debug::dbg_parse_qingque_atopwl(ctx, msg).await?, "parse-katana-kc_ow" => debug::dbg_parse_katana_kc_ow(ctx, msg).await?, + "parse-katana-klu_lookup" => debug::dbg_parse_katana_klu_lookup(ctx, msg).await?, + "parse-katana-klu_results" => debug::dbg_parse_katana_klu_results(ctx, msg).await?, _ => { helper::error_message( ctx,