use crate::utils::*; use crate::serenity; use crate::Context; use crate::Error; use poise::command; #[command(slash_command, prefix_command, description_localized("en-US", "Get category info and links to Jisho for character(s), with stroke order for single characters."))] pub async fn i( ctx: Context<'_>, #[description = "Input kanji to get info for"] input: String, ) -> Result<(), Error> { let chars = input.chars(); let mut message = String::from(""); let mut covered_chars: Vec = Vec::new(); let mut skipped_chars = 0; let mut found_chars: Vec = Vec::new(); for character in chars { if covered_chars.contains(&character) { continue; } let kanji_info = get_kanji_info(character); covered_chars.push(character); if kanji_info.len() == 0 { skipped_chars += 1; continue; } found_chars.push(character); message.push_str(&format!( "[{}](https://jisho.org/search/{}%23kanji): {}\n", character, character, kanji_info )); } message = format!( "Found {} kanji{}\n{}", found_chars.len(), if found_chars.len() == 0 { "." } else { ":" }, message ); if skipped_chars > 0 { message.push_str(&format!( "Skipped {} character{}.", skipped_chars, if skipped_chars == 1 { "" } else { "s" } )); } ctx.send(|m| { m.allowed_mentions(|am| { am.empty_parse(); am }); m.embed(|e| { e.title(input); e.description(message); let mut author = serenity::builder::CreateEmbedAuthor::default(); author .icon_url("https://raw.githubusercontent.com/ElnuDev/ji-chan/main/ji-chan.png") .name("字ちゃん") .url("https://github.com/ElnuDev/ji-chan"); e.set_author(author); e.color(serenity::utils::Colour::from_rgb(251, 73, 52)); if found_chars.len() == 1 { e.thumbnail(get_so_diagram(found_chars[0])); } e }); m }) .await .unwrap(); Ok(()) } #[command( slash_command, prefix_command, description_localized("en-US", "Random Jōyō kanji") )] pub async fn joyo(ctx: Context<'_>) -> Result<(), Error> { random_kanji("JOYO", ctx, None).await } #[command( slash_command, prefix_command, description_localized("en-US", "Random Jinmeiyō kanji") )] pub async fn jinmeiyo(ctx: Context<'_>) -> Result<(), Error> { random_kanji("JINMEIYO", ctx, None).await } #[command( slash_command, prefix_command, description_localized("en-US", "Random Kyōiku kanji") )] pub async fn kyoiku( ctx: Context<'_>, #[description = "Kyōiku subcategory. GRADE1, GRADE2, GRADE3, GRADE4, GRADE5, GRADE6, or ALL."] subcategory: Option, ) -> Result<(), Error> { random_kanji("KYOIKU", ctx, subcategory).await } #[command( slash_command, prefix_command, description_localized("en-US", "Random JLPT kanji") )] pub async fn jlpt( ctx: Context<'_>, #[description = "JLPT subcategory. N1, N2, N3, N4, N5, or ALL"] subcategory: Option, ) -> Result<(), Error> { random_kanji("JLPT", ctx, subcategory).await } #[command( slash_command, prefix_command, description_localized("en-US", "Random Hyōgai kanji") )] pub async fn hyogai( ctx: Context<'_>, #[description = "Hyōgai subcategory. ELEMENTS, MAIN, or ALL."] subcategory: Option, ) -> Result<(), Error> { random_kanji("HYOGAI", ctx, subcategory).await } #[command( slash_command, prefix_command, description_localized("en-US", "Get stroke order diagrams for character(s), maximum 4") )] pub async fn so( ctx: Context<'_>, #[description = "Input characters to get stroke order for"] text: String, ) -> Result<(), Error> { const MAX_CHARS: i32 = 4; let mut displayed_characters: Vec = Vec::new(); let mut displayed_character_count = 0; for character in text.chars() { if displayed_character_count >= MAX_CHARS { ctx.channel_id() .say( &ctx.serenity_context().http, ":warning: Maximum number of stroke order diagrams per command reached.", ) .await?; break; } if character.is_whitespace() || displayed_characters.contains(&character) { continue; } // Don't show same character twice displayed_characters.push(character); displayed_character_count += 1; display_kanji(ctx, character, "").await?; } Ok(()) }