feat: swordfish-user
Also move tesseract implementation to swordfish cuz only the bot uses it.
This commit is contained in:
parent
ebafd93110
commit
8eb622f479
71
Cargo.lock
generated
71
Cargo.lock
generated
@ -289,9 +289,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
|
||||
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
@ -315,6 +315,16 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "command_attr"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/nshout/serenity-self#6b62ca61aa592d4fd22dc42848388c5fb3889161"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
@ -1141,12 +1151,12 @@ checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1974,7 +1984,42 @@ dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"command_attr",
|
||||
"command_attr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dashmap",
|
||||
"flate2",
|
||||
"futures",
|
||||
"fxhash",
|
||||
"levenshtein",
|
||||
"mime_guess",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"reqwest",
|
||||
"secrecy",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"static_assertions",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tracing",
|
||||
"typemap_rev",
|
||||
"typesize",
|
||||
"url",
|
||||
"uwl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serenity"
|
||||
version = "0.13.0-alpha2"
|
||||
source = "git+https://github.com/nshout/serenity-self#6b62ca61aa592d4fd22dc42848388c5fb3889161"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"async-trait",
|
||||
"base64 0.21.5",
|
||||
"bitflags 2.4.1",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"command_attr 0.5.1 (git+https://github.com/nshout/serenity-self)",
|
||||
"dashmap",
|
||||
"flate2",
|
||||
"futures",
|
||||
@ -2174,9 +2219,11 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenvy",
|
||||
"image",
|
||||
"leptess",
|
||||
"regex",
|
||||
"rusty-tesseract",
|
||||
"serde",
|
||||
"serenity",
|
||||
"serenity 0.12.0",
|
||||
"swordfish-common",
|
||||
"tokio",
|
||||
"toml",
|
||||
@ -2186,16 +2233,22 @@ dependencies = [
|
||||
name = "swordfish-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"leptess",
|
||||
"log",
|
||||
"mongodb",
|
||||
"rusty-tesseract",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swordfish-user"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serenity 0.13.0-alpha2",
|
||||
"swordfish-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
@ -3,5 +3,5 @@ resolver = "1"
|
||||
members = [
|
||||
"swordfish-common",
|
||||
"swordfish"
|
||||
]
|
||||
, "swordfish-user"]
|
||||
default-members = ["swordfish"]
|
||||
|
@ -6,9 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
leptess = "0.14.0"
|
||||
log = "0.4.20"
|
||||
rusty-tesseract = "1.1.9"
|
||||
serde = "1.0.195"
|
||||
tokio = "1.35.1"
|
||||
tracing = "0.1.40"
|
||||
|
@ -1,12 +1,12 @@
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(string_remove_matches)]
|
||||
pub use log;
|
||||
pub use tokio;
|
||||
pub use tracing::{debug, error, info, trace, warn};
|
||||
use tracing_subscriber::{self, fmt, EnvFilter};
|
||||
pub mod constants;
|
||||
pub mod database;
|
||||
pub mod structs;
|
||||
pub mod tesseract;
|
||||
pub mod utils;
|
||||
|
||||
pub fn setup_logger(level: &str) -> Result<(), ()> {
|
||||
|
13
swordfish-user/Cargo.toml
Normal file
13
swordfish-user/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "swordfish-user"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serenity = { git = "https://github.com/nshout/serenity-self", version = "0.13.0-alpha2" }
|
||||
|
||||
|
||||
[dependencies.swordfish-common]
|
||||
path = "../swordfish-common"
|
202
swordfish-user/src/main.rs
Normal file
202
swordfish-user/src/main.rs
Normal file
@ -0,0 +1,202 @@
|
||||
use std::env;
|
||||
|
||||
use serenity::all::{Embed, MessageUpdateEvent};
|
||||
use serenity::async_trait;
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::prelude::*;
|
||||
use swordfish_common::setup_logger;
|
||||
use swordfish_common::{constants, database, utils};
|
||||
use swordfish_common::{debug, tokio};
|
||||
use swordfish_common::{error, info, trace};
|
||||
|
||||
const GITHUB_URL: &str = "https://github.com/teppyboy/swordfish";
|
||||
|
||||
async fn parse_katana(ctx: &Context, msg: &Message) -> Result<(), String> {
|
||||
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;
|
||||
}
|
||||
debug!("Importing cards from Katana 'Card Collection'");
|
||||
match database::katana::write_cards(cards).await {
|
||||
Ok(_) => {
|
||||
debug!("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;
|
||||
}
|
||||
};
|
||||
debug!("Importing a card from Katana 'Character Lookup'");
|
||||
match database::katana::write_card(card).await {
|
||||
Ok(_) => {
|
||||
debug!("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;
|
||||
}
|
||||
debug!("Importing cards from Katana 'Character Results'");
|
||||
match database::katana::write_cards(cards).await {
|
||||
Ok(_) => {
|
||||
debug!("Imported successully");
|
||||
}
|
||||
Err(why) => {
|
||||
error!("Failed to import card: {:?}", why);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
None => {}
|
||||
};
|
||||
}
|
||||
|
||||
async fn parse_qingque_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];
|
||||
let embed_title = match embed.title {
|
||||
Some(ref title) => title,
|
||||
None => {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
match embed_title.as_str() {
|
||||
"Top Wishlist" => {
|
||||
let cards = utils::katana::parse_cards_from_qingque_atopwl(
|
||||
&embed.description.as_ref().unwrap(),
|
||||
);
|
||||
debug!("Importing cards from Qingque 'Top Wishlist'");
|
||||
match database::katana::write_cards(cards).await {
|
||||
Ok(_) => {
|
||||
debug!("Imported successully");
|
||||
}
|
||||
Err(why) => {
|
||||
error!("Failed to import card: {:?}", why);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
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(())
|
||||
}
|
||||
|
||||
struct Handler;
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn message(&self, ctx: Context, msg: Message) {
|
||||
if msg.author.id.get() == constants::KATANA_ID {
|
||||
parse_katana(&ctx, &msg).await.unwrap();
|
||||
}
|
||||
}
|
||||
async fn message_update(
|
||||
&self,
|
||||
ctx: Context,
|
||||
old_if_available: Option<Message>,
|
||||
new: Option<Message>,
|
||||
event: MessageUpdateEvent,
|
||||
) {
|
||||
let author = match event.author {
|
||||
Some(ref v) => v,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
if author.id == ctx.cache.current_user().id {
|
||||
return;
|
||||
}
|
||||
let content = match event.content {
|
||||
Some(ref v) => v,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
trace!("Message update: {}, sender: {}", content, author.id);
|
||||
match author.id.get() {
|
||||
constants::KATANA_ID => {
|
||||
parse_katana_event(&ctx, event).await.unwrap();
|
||||
}
|
||||
constants::QINGQUE_ID => {
|
||||
parse_qingque_event(&ctx, event).await.unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Login with a user token from the environment
|
||||
let log_level = env::var("LOG_LEVEL").unwrap_or("info".to_string());
|
||||
setup_logger(log_level.as_str()).expect("Failed to setup logger");
|
||||
let token = env::var("DISCORD_TOKEN").expect("Token not found");
|
||||
info!("Swordfish v{} - {}", env!("CARGO_PKG_VERSION"), GITHUB_URL);
|
||||
info!("Log level: {}", log_level);
|
||||
info!("Initializing database...");
|
||||
swordfish_common::database::init().await;
|
||||
info!("Initializing Discord client...");
|
||||
let mut client = Client::builder(token)
|
||||
.event_handler(Handler)
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
|
||||
// start listening for events by starting a single shard
|
||||
if let Err(why) = client.start().await {
|
||||
error!("An error occurred while running the client: {:?}", why);
|
||||
}
|
||||
}
|
@ -8,7 +8,9 @@ edition = "2021"
|
||||
[dependencies]
|
||||
dotenvy = "0.15.7"
|
||||
image = "0.24.7"
|
||||
leptess = "0.14.0"
|
||||
regex = "1.10.2"
|
||||
rusty-tesseract = "1.1.9"
|
||||
serde = "1.0.193"
|
||||
serenity = { version = "0.12.0", features = ["builder"] }
|
||||
tokio = { version = "1.35.1", features = ["full"] }
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::tesseract::{libtesseract, subprocess};
|
||||
use crate::CONFIG;
|
||||
use image::imageops::colorops::contrast_in_place;
|
||||
use image::io::Reader as ImageReader;
|
||||
@ -8,7 +9,6 @@ use std::io::Cursor;
|
||||
use std::sync::LazyLock;
|
||||
use swordfish_common::database::katana as db;
|
||||
use swordfish_common::structs::Card;
|
||||
use swordfish_common::tesseract::{libtesseract, subprocess};
|
||||
use swordfish_common::{trace, warn};
|
||||
use tokio::task;
|
||||
|
||||
|
@ -19,6 +19,7 @@ mod debug;
|
||||
mod helper;
|
||||
mod katana;
|
||||
mod template;
|
||||
mod tesseract;
|
||||
|
||||
const GITHUB_URL: &str = "https://github.com/teppyboy/swordfish";
|
||||
static CONFIG: OnceLock<Config> = OnceLock::new();
|
||||
@ -95,10 +96,10 @@ async fn parse_qingque_event(ctx: &Context, event: MessageUpdateEvent) -> Result
|
||||
let cards = utils::katana::parse_cards_from_qingque_atopwl(
|
||||
&embed.description.as_ref().unwrap(),
|
||||
);
|
||||
trace!("Begin importing cards");
|
||||
debug!("Importing cards from Qingque 'Top Wishlist'");
|
||||
match database::katana::write_cards(cards).await {
|
||||
Ok(_) => {
|
||||
trace!("Imported successully");
|
||||
debug!("Imported successully");
|
||||
}
|
||||
Err(why) => {
|
||||
error!("Failed to import card: {:?}", why);
|
||||
@ -206,10 +207,10 @@ async fn parse_katana_embed(embed: &Embed) {
|
||||
if cards.len() == 0 {
|
||||
return;
|
||||
}
|
||||
trace!("Begin importing cards");
|
||||
debug!("Importing cards from Katana 'Card Collection'");
|
||||
match database::katana::write_cards(cards).await {
|
||||
Ok(_) => {
|
||||
trace!("Imported successully");
|
||||
debug!("Imported successully");
|
||||
}
|
||||
Err(why) => {
|
||||
error!("Failed to import card: {:?}", why);
|
||||
@ -231,10 +232,10 @@ async fn parse_katana_embed(embed: &Embed) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
trace!("Begin importing a card");
|
||||
debug!("Importing a card from Katana 'Character Lookup'");
|
||||
match database::katana::write_card(card).await {
|
||||
Ok(_) => {
|
||||
trace!("Imported successully");
|
||||
debug!("Imported successully");
|
||||
}
|
||||
Err(why) => {
|
||||
error!("Failed to import card: {:?}", why);
|
||||
@ -253,10 +254,10 @@ async fn parse_katana_embed(embed: &Embed) {
|
||||
if cards.len() == 0 {
|
||||
return;
|
||||
}
|
||||
trace!("Begin importing cards");
|
||||
debug!("Importing cards from Katana 'Character Results'");
|
||||
match database::katana::write_cards(cards).await {
|
||||
Ok(_) => {
|
||||
trace!("Imported successully");
|
||||
debug!("Imported successully");
|
||||
}
|
||||
Err(why) => {
|
||||
error!("Failed to import card: {:?}", why);
|
||||
|
Loading…
Reference in New Issue
Block a user