diff --git a/Cargo.lock b/Cargo.lock index 62fb5bc..ea2ecb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -889,6 +889,7 @@ dependencies = [ "rusttype", "serde", "serde_json", + "tokio", ] [[package]] diff --git a/assets/clock/electric.png b/assets/clock/electric.png new file mode 100644 index 0000000..a95e00b Binary files /dev/null and b/assets/clock/electric.png differ diff --git a/assets/clock/electric_locked.png b/assets/clock/electric_locked.png new file mode 100644 index 0000000..95f29d3 Binary files /dev/null and b/assets/clock/electric_locked.png differ diff --git a/assets/clock/fire.png b/assets/clock/fire.png new file mode 100644 index 0000000..cc8ea4a Binary files /dev/null and b/assets/clock/fire.png differ diff --git a/assets/clock/fire_locked.png b/assets/clock/fire_locked.png new file mode 100644 index 0000000..71635bd Binary files /dev/null and b/assets/clock/fire_locked.png differ diff --git a/assets/clock/grass.png b/assets/clock/grass.png new file mode 100644 index 0000000..afb9e89 Binary files /dev/null and b/assets/clock/grass.png differ diff --git a/assets/clock/grass_locked.png b/assets/clock/grass_locked.png new file mode 100644 index 0000000..8bd4802 Binary files /dev/null and b/assets/clock/grass_locked.png differ diff --git a/assets/clock/ice.png b/assets/clock/ice.png new file mode 100644 index 0000000..f3b12c5 Binary files /dev/null and b/assets/clock/ice.png differ diff --git a/assets/clock/ice_locked.png b/assets/clock/ice_locked.png new file mode 100644 index 0000000..0d54b86 Binary files /dev/null and b/assets/clock/ice_locked.png differ diff --git a/assets/clock/rock.png b/assets/clock/rock.png new file mode 100644 index 0000000..44e6fe0 Binary files /dev/null and b/assets/clock/rock.png differ diff --git a/assets/clock/rock_locked.png b/assets/clock/rock_locked.png new file mode 100644 index 0000000..86b57dd Binary files /dev/null and b/assets/clock/rock_locked.png differ diff --git a/assets/clock/water.png b/assets/clock/water.png new file mode 100644 index 0000000..bc70f3b Binary files /dev/null and b/assets/clock/water.png differ diff --git a/assets/clock/water_locked.png b/assets/clock/water_locked.png new file mode 100644 index 0000000..2e57080 Binary files /dev/null and b/assets/clock/water_locked.png differ diff --git a/assets/clock/wind.png b/assets/clock/wind.png new file mode 100644 index 0000000..3957dd4 Binary files /dev/null and b/assets/clock/wind.png differ diff --git a/assets/clock/wind_locked.png b/assets/clock/wind_locked.png new file mode 100644 index 0000000..fea2ada Binary files /dev/null and b/assets/clock/wind_locked.png differ diff --git a/bin/bot/src/component.rs b/bin/bot/src/component.rs index 1790888..56d4be3 100644 --- a/bin/bot/src/component.rs +++ b/bin/bot/src/component.rs @@ -173,9 +173,11 @@ pub fn create_components( let format = CreateActionRow::SelectMenu(format); let button = CreateActionRow::Buttons(vec![ CreateButton::new_link(format!("https://enka.network/u/{}", uid)).label("Enka Network"), + CreateButton::new_link(format!("https://ag.neody.land/generate?uid={}", uid)) + .label(t!(locale, "main:general.webapp")), /*CreateButton::new("end") .style(ButtonStyle::Danger) - .label("終了"),*/ + .label(t!(locale, "main:general.close")),*/ ]); vec![chara, score, format, button] } diff --git a/bin/bot/src/events/interaction.rs b/bin/bot/src/events/interaction.rs index 7d934f6..498934a 100644 --- a/bin/bot/src/events/interaction.rs +++ b/bin/bot/src/events/interaction.rs @@ -128,19 +128,17 @@ pub async fn handler( } select_menu.edit_response(&ctx.http, builder).await?; } - /* if custom_id == "end" { - let e = select_menu.message.embeds.first(); - if e.is_none() { - return Ok(()); + /*if custom_id == "end" { + let msg = &select_menu.message; + if let Some(e) = msg.embeds.first() { + let e = CreateEmbed::from(e.to_owned()); + let res = CreateInteractionResponseMessage::new() + .embed(e) + .components(vec![]) + .files(vec![]); + let res = CreateInteractionResponse::UpdateMessage(res); + select_menu.create_response(&ctx.http, res).await?; } - let e = e.unwrap(); - let e = CreateEmbed::from(e.to_owned()); - let res = CreateInteractionResponseMessage::new() - .embed(e) - .components(vec![]) - .files(vec![]); - let res = CreateInteractionResponse::UpdateMessage(res); - select_menu.create_response(&ctx.http, res).await?; }*/ } _ => {} diff --git a/lib/gen/Cargo.toml b/lib/gen/Cargo.toml index 4ab3740..fdba1ed 100644 --- a/lib/gen/Cargo.toml +++ b/lib/gen/Cargo.toml @@ -9,4 +9,5 @@ serde_json = { workspace = true } serde = { workspace = true } image = "0.24.7" rusttype = "0.9.3" -imageproc = "0.23.0" \ No newline at end of file +imageproc = "0.23.0" +tokio = { version = "1.33.0", features = ["rt", "macros", "fs"] } \ No newline at end of file diff --git a/lib/gen/src/constants.rs b/lib/gen/src/constants.rs index 7c92502..f7b9d53 100644 --- a/lib/gen/src/constants.rs +++ b/lib/gen/src/constants.rs @@ -108,3 +108,38 @@ pub fn get_scores_for_part(part: Option) -> Scores { }, } } +const ELECTRIC: &[u8; 6968] = include_bytes!("../../../assets/clock/electric.png"); +const ELECTRIC_LOCKED: &[u8; 7797] = include_bytes!("../../../assets/clock/electric_locked.png"); +const FIRE: &[u8; 6599] = include_bytes!("../../../assets/clock/fire.png"); +const FIRE_LOCKED: &[u8; 7447] = include_bytes!("../../../assets/clock/fire_locked.png"); +const GRASS: &[u8; 6941] = include_bytes!("../../../assets/clock/grass.png"); +const GRASS_LOCKED: &[u8; 7591] = include_bytes!("../../../assets/clock/grass_locked.png"); +const ICE: &[u8; 6953] = include_bytes!("../../../assets/clock/ice.png"); +const ICE_LOCKED: &[u8; 7761] = include_bytes!("../../../assets/clock/ice_locked.png"); +const ROCK: &[u8; 6898] = include_bytes!("../../../assets/clock/rock.png"); +const ROCK_LOCKED: &[u8; 7627] = include_bytes!("../../../assets/clock/rock_locked.png"); +const WATER: &[u8; 6726] = include_bytes!("../../../assets/clock/water.png"); +const WATER_LOCKED: &[u8; 7544] = include_bytes!("../../../assets/clock/water_locked.png"); +const WIND: &[u8; 6071] = include_bytes!("../../../assets/clock/wind.png"); +const WIND_LOCKED: &[u8; 7737] = include_bytes!("../../../assets/clock/wind_locked.png"); + +pub fn get_clock_image(f: impl AsRef, locked: bool) -> Option { + image::load_from_memory(match (f.as_ref().to_lowercase(), locked) { + (f, true) if f == "electric" || f == "elec" => ELECTRIC_LOCKED, + (f, true) if f == "fire" => FIRE_LOCKED, + (f, true) if f == "grass" => GRASS_LOCKED, + (f, true) if f == "ice" => ICE_LOCKED, + (f, true) if f == "rock" => ROCK_LOCKED, + (f, true) if f == "water" => WATER_LOCKED, + (f, true) if f == "wind" => WIND_LOCKED, + (f, false) if f == "electric" || f == "elec" => ELECTRIC, + (f, false) if f == "fire" => FIRE, + (f, false) if f == "grass" => GRASS, + (f, false) if f == "ice" => ICE, + (f, false) if f == "rock" => ROCK, + (f, false) if f == "water" => WATER, + (f, false) if f == "wind" => WIND, + _ => return None, + }) + .ok() +} diff --git a/lib/gen/src/gen.rs b/lib/gen/src/gen.rs index a6ab49c..3d5c072 100644 --- a/lib/gen/src/gen.rs +++ b/lib/gen/src/gen.rs @@ -24,7 +24,7 @@ pub use crate::default::get_default; use serde::Deserialize; use crate::{ - constants::{self, FONT}, + constants::{self, get_clock_image, FONT}, dupe, locale, }; @@ -242,30 +242,15 @@ pub async fn generate( let clocks = data.talents(); let mut clock_y = 100; for clock in clocks { - let img = clock.image(api).await.ok()?; - let mut img = img.into_rgba8(); - let mut base_img = DynamicImage::new_rgba8(60, 60).into_rgba8(); - if let Some(c) = icons.image("Const.svg", 5.0) { - image::imageops::overlay(&mut base_img, &c, 0, 0); + let locked_image = get_clock_image(data.element.fight_prop_name(), !clock.is_unlock())?; + let mut locked_image = resize(&locked_image, 70, 70, image::imageops::Triangle); + if clock.is_unlock() { + let img = clock.image(api).await.ok()?; + let img = img.into_rgba8(); + let img = resize(&img, 35, 35, image::imageops::Triangle); + image::imageops::overlay(&mut locked_image, &img, 16, 15); } - let unique_color = data.element.color_rgb(); - if !clock.is_unlock() { - for p in img.pixels_mut() { - p.0 = [100, 100, 100, p.0[3]]; - } - } else { - for p in img.pixels_mut() { - if p.0[0] == 255 && p.0[1] == 255 && p.0[2] == 255 { - p.0 = [255, 255, 255, p.0[3]]; - p[0] = unique_color[0]; - p[1] = unique_color[1]; - p[2] = unique_color[2]; - } - } - } - let img = resize(&img, 40, 40, image::imageops::Triangle); - image::imageops::overlay(&mut base_img, &img, 15, 15); - image::imageops::overlay(&mut image, &base_img, 680, clock_y as i64); + image::imageops::overlay(&mut image, &locked_image, 680, clock_y as i64); clock_y += 80; } diff --git a/lib/gen/src/main.rs b/lib/gen/src/main.rs new file mode 100644 index 0000000..253ed70 --- /dev/null +++ b/lib/gen/src/main.rs @@ -0,0 +1,20 @@ +use enka_api::{api::Api, character::CharacterId}; +use gen::gen::{generate, ImageFormat, Lang, ScoreCounter}; +use tokio::fs::write; + +const UID: i32 = 827106332; + +#[tokio::main(flavor = "current_thread")] +async fn main() { + let api = Api::new(); + let icons = api.icon_data(); + let (user, _cached) = api.simple(UID).await.unwrap(); + let character = user.character(CharacterId(10000031)).unwrap(); + let format = ImageFormat::Png; + let counter = ScoreCounter::Hp; + let raw_lang = Lang::Ja; + let res = generate(character.clone(), &api, &raw_lang, &icons, counter, format) + .await + .unwrap(); + write("test.png", res).await.unwrap(); +} diff --git a/localization/en-US/main.json b/localization/en-US/main.json index f8cd67d..baa90bd 100644 --- a/localization/en-US/main.json +++ b/localization/en-US/main.json @@ -19,6 +19,8 @@ "general.linked": "Successfully linked your UID.", "general.parseFailed": "Failed to parse data.", "general.generated": "Stats of {{name}}", + "general.webapp": "Web Version", + "general.close": "Close", "calculationMethod.attack": "ATK Calculation", "calculationMethod.defense": "DEF Calculation", "calculationMethod.hp": "HP Calculation", diff --git a/localization/ja/main.json b/localization/ja/main.json index 00a6806..ccb50c5 100644 --- a/localization/ja/main.json +++ b/localization/ja/main.json @@ -19,6 +19,8 @@ "general.linked": "ユーザーidをリンクしました。", "general.parseFailed": "解析に失敗しました。", "general.generated": "{{name}}のステータス", + "general.webapp": "Web版", + "general.close": "閉じる", "calculationMethod.attack": "攻撃型", "calculationMethod.defense": "防御型", "calculationMethod.hp": "HP型",