Move to poise, add slash commands
This commit is contained in:
parent
d397bb7117
commit
9e9eb48025
8 changed files with 385 additions and 404 deletions
|
@ -1,20 +1,20 @@
|
|||
use crate::utils::*;
|
||||
use serde_json::Map;
|
||||
use serenity::framework::standard::{macros::command, Args, CommandResult};
|
||||
use serenity::http::typing::Typing;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::serenity;
|
||||
use crate::Error;
|
||||
use crate::{Context, PrefixContext};
|
||||
use poise::command;
|
||||
|
||||
use slug::slugify;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
#[command]
|
||||
async fn challenge(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
#[command(prefix_command, slash_command, description_localized("en-US", "View the latest handwriting challenge info."))]
|
||||
pub async fn challenge(ctx: Context<'_>) -> Result<(), Error> {
|
||||
ctx.say(
|
||||
format!(
|
||||
"Tegaki Tuesday #{n}: <https://tegakituesday.com/{n}>",
|
||||
n = get_challenge_number()
|
||||
|
@ -24,27 +24,26 @@ async fn challenge(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
#[command(prefix_command, broadcast_typing, description_localized("en-US", "Submit to the latest handwriting challenge."))]
|
||||
pub async fn submit(ctx: PrefixContext<'_>) -> Result<(), Error> {
|
||||
// TODO: The code for this command needs to be refactored,
|
||||
// there are large duplicated sections that need to be merged somehow.
|
||||
let guild_data = get_guild_data();
|
||||
let guild = msg.guild_id.unwrap().as_u64().to_string();
|
||||
let guild = ctx.msg.guild_id.unwrap().as_u64().to_string();
|
||||
if !guild_data.contains_key(&guild)
|
||||
|| !&guild_data[&guild]
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.contains_key("submissionChannel")
|
||||
{
|
||||
msg.reply(&ctx.http, "Submissions aren't enabled for this server yet.")
|
||||
.await?;
|
||||
ctx.msg.reply(&ctx.discord.http, "Submissions aren't enabled for this server yet.").await?;
|
||||
return Ok(());
|
||||
}
|
||||
let current_guild_data = &guild_data[&guild].as_object().unwrap();
|
||||
let submission_channel = current_guild_data["submissionChannel"].as_str().unwrap();
|
||||
if submission_channel != &msg.channel_id.as_u64().to_string() {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
if submission_channel != ctx.msg.channel_id.as_u64().to_string() {
|
||||
ctx.msg.reply(
|
||||
&ctx.discord.http,
|
||||
format!(
|
||||
"Sorry, submissions aren't permitted here. Please go to <#{}>. Thanks!",
|
||||
guild
|
||||
|
@ -53,12 +52,10 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
if msg.attachments.len() == 0 {
|
||||
msg.reply(&ctx.http, "Please attach at least one image.")
|
||||
.await?;
|
||||
if ctx.msg.attachments.len() == 0 {
|
||||
ctx.msg.reply(&ctx.discord.http, "Please attach at least one image.").await?;
|
||||
return Ok(());
|
||||
}
|
||||
let typing = Typing::start(ctx.http.clone(), *msg.channel_id.as_u64()).unwrap();
|
||||
let challenge_number = get_challenge_number();
|
||||
let submission_images_dir = get_submission_images_dir();
|
||||
|
||||
|
@ -71,10 +68,10 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
let mut invalid_types = false;
|
||||
let mut requires_rebuild = false;
|
||||
for (i, submission) in submission_data.iter_mut().enumerate() {
|
||||
if is_matching_submission(&submission, &msg) {
|
||||
if is_matching_submission(&submission, &ctx.msg.author) {
|
||||
existing_submitter = true;
|
||||
let mut images = submission["images"].as_array_mut().unwrap().clone();
|
||||
for attachment in msg.attachments.iter() {
|
||||
for attachment in ctx.msg.attachments.iter() {
|
||||
let extension;
|
||||
if let Some(content_type) = &attachment.content_type {
|
||||
if content_type == "image/png" {
|
||||
|
@ -93,8 +90,8 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
let file_name = format!(
|
||||
"{}-{}-{}-{}.{}",
|
||||
i + 1,
|
||||
slugify(&msg.author.name),
|
||||
msg.author.discriminator,
|
||||
slugify(&ctx.msg.author.name),
|
||||
ctx.msg.author.discriminator,
|
||||
images.len() + 1,
|
||||
extension
|
||||
);
|
||||
|
@ -113,10 +110,10 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
let mut submitter_data = Map::new();
|
||||
submitter_data.insert(
|
||||
String::from("username"),
|
||||
format!("{}#{}", msg.author.name, msg.author.discriminator).into(),
|
||||
format!("{}#{}", ctx.msg.author.name, ctx.msg.author.discriminator).into(),
|
||||
);
|
||||
let mut images: Vec<String> = Vec::new();
|
||||
for attachment in msg.attachments.iter() {
|
||||
for attachment in ctx.msg.attachments.iter() {
|
||||
let extension;
|
||||
if let Some(content_type) = &attachment.content_type {
|
||||
if content_type == "image/png" {
|
||||
|
@ -135,8 +132,8 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
let file_name = format!(
|
||||
"{}-{}-{}{}.{}",
|
||||
submission_data.len() + 1,
|
||||
slugify(&msg.author.name),
|
||||
msg.author.discriminator,
|
||||
slugify(&ctx.msg.author.name),
|
||||
ctx.msg.author.discriminator,
|
||||
if images.len() == 0 {
|
||||
String::from("")
|
||||
} else {
|
||||
|
@ -153,7 +150,7 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
submitter_data.insert(String::from("images"), images.into());
|
||||
submitter_data.insert(
|
||||
String::from("id"),
|
||||
msg.author.id.as_u64().to_string().into(),
|
||||
ctx.msg.author.id.as_u64().to_string().into(),
|
||||
);
|
||||
submission_data.push(submitter_data.into());
|
||||
}
|
||||
|
@ -169,18 +166,17 @@ async fn submit(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
} else if invalid_types {
|
||||
message.push_str("Sorry, your submission could not be uploaded; only **.png**, **.jpg**, and **.jpeg** files are permitted.");
|
||||
}
|
||||
let _ = typing.stop();
|
||||
msg.reply(&ctx.http, message).await?;
|
||||
ctx.msg.reply(&ctx.discord.http, message).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn images(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
#[command(prefix_command, slash_command, description_localized("en-US", "List images in your current submission, if available."))]
|
||||
pub async fn images(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let submission_data = get_current_submission_data();
|
||||
let images: Vec<String> = {
|
||||
let mut images = Vec::new();
|
||||
for submission in submission_data.iter() {
|
||||
if is_matching_submission(&submission, &msg) {
|
||||
if is_matching_submission(&submission, &ctx.author()) {
|
||||
for image in submission["images"].as_array().unwrap().iter() {
|
||||
images.push(String::from(image.as_str().unwrap()));
|
||||
}
|
||||
|
@ -191,8 +187,7 @@ async fn images(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
};
|
||||
let challenge_number = get_challenge_number();
|
||||
if images.len() == 0 {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
ctx.say(
|
||||
format!(
|
||||
"You haven't submitted anything for Tegaki Tuesday #{}.",
|
||||
challenge_number
|
||||
|
@ -213,41 +208,29 @@ async fn images(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
image
|
||||
));
|
||||
}
|
||||
msg.reply(&ctx.http, message).await?;
|
||||
ctx.say(message).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
// imageDelete instead of image_delete to keep command naming from Python version
|
||||
#[allow(non_snake_case)]
|
||||
async fn imageDelete(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
let number;
|
||||
match args.single::<i32>() {
|
||||
Ok(value) => number = value,
|
||||
Err(_) => {
|
||||
msg.reply(&ctx.http, format!("Please provide the image number you want to delete. You can get a list of your submitted images using `{}images`.", env::var("PREFIX").unwrap())).await?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
#[command(prefix_command, slash_command, description_localized("en-US", "Delete images from your current submission using image numbers from the images command."))]
|
||||
pub async fn imagedelete(
|
||||
ctx: Context<'_>,
|
||||
number: i32,
|
||||
) -> Result<(), Error> {
|
||||
if number < 1 {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
"That isn't a valid image number. Image numbers start at 1.",
|
||||
)
|
||||
.await?;
|
||||
ctx.say("That isn't a valid image number. Image numbers start at 1.").await?;
|
||||
return Ok(());
|
||||
}
|
||||
let challenge_number = get_challenge_number();
|
||||
let mut submission_data = get_current_submission_data();
|
||||
for (i, submission) in submission_data.iter_mut().enumerate() {
|
||||
if !is_matching_submission(&submission, &msg) {
|
||||
if !is_matching_submission(&submission, &ctx.author()) {
|
||||
continue;
|
||||
}
|
||||
let mut images = submission["images"].as_array().unwrap().clone();
|
||||
let image_count = images.len();
|
||||
if image_count < number.try_into().unwrap() {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
ctx.say(
|
||||
if image_count == 0 {
|
||||
// This is an edge case that should never happen.
|
||||
// In this scenario, there is submission data with an empty image list.
|
||||
|
@ -296,11 +279,12 @@ async fn imageDelete(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes
|
|||
for (j, image) in images.iter_mut().enumerate() {
|
||||
let old = image.as_str().unwrap();
|
||||
let from = format!("{}/{}", submission_images_dir, old);
|
||||
let author = ctx.author();
|
||||
let new = format!(
|
||||
"{}-{}-{}{}.{}",
|
||||
i + 1,
|
||||
slugify(&msg.author.name),
|
||||
msg.author.discriminator,
|
||||
slugify(&author.name),
|
||||
author.discriminator,
|
||||
if j == 0 {
|
||||
String::from("")
|
||||
} else {
|
||||
|
@ -317,11 +301,10 @@ async fn imageDelete(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes
|
|||
}
|
||||
set_submission_data(submission_data);
|
||||
rebuild_site();
|
||||
msg.reply(&ctx.http, message).await?;
|
||||
ctx.say(message).await?;
|
||||
return Ok(());
|
||||
}
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
ctx.say(
|
||||
format!(
|
||||
"You haven't submitted anything for Tegaki Tuesday #{}.",
|
||||
challenge_number
|
||||
|
@ -331,11 +314,15 @@ async fn imageDelete(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[allow(non_snake_case)]
|
||||
async fn suggest(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
// TODO: make also slash command
|
||||
#[command(prefix_command, description_localized("en-US", "Make a suggestion for future challenge prompts!"))]
|
||||
pub async fn suggest(
|
||||
ctx: PrefixContext<'_>,
|
||||
#[description = "Suggestion text. Please include passage and source."]
|
||||
suggestion: String,
|
||||
) -> Result<(), Error> {
|
||||
let guild_data = get_guild_data();
|
||||
let channel = ChannelId(
|
||||
let channel = serenity::ChannelId(
|
||||
guild_data["suggestionChannel"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
|
@ -344,33 +331,32 @@ async fn suggest(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||
);
|
||||
// User::accent_colour is only available via the REST API
|
||||
// If we just do msg.author.accent_colour here, we will get None
|
||||
let accent_color = ctx
|
||||
.http
|
||||
.get_user(*msg.author.id.as_u64())
|
||||
let author = &ctx.msg.author;
|
||||
let accent_color = ctx.discord.http
|
||||
.get_user(*author.id.as_u64())
|
||||
.await
|
||||
.unwrap()
|
||||
.accent_colour;
|
||||
channel
|
||||
.send_message(&ctx.http, |m| {
|
||||
.send_message(&ctx.discord.http, |m| {
|
||||
m.allowed_mentions(|am| {
|
||||
am.empty_parse();
|
||||
am
|
||||
});
|
||||
m.embed(|e| {
|
||||
let username = format!("{}#{}", msg.author.name, msg.author.discriminator);
|
||||
let username = format!("{}#{}", author.name, author.discriminator);
|
||||
e.title("New suggestion");
|
||||
e.description(format!(
|
||||
"{}\n\n[See original message]({}) ({})",
|
||||
args.rest(),
|
||||
msg.link(),
|
||||
msg.guild(&ctx).unwrap().name
|
||||
"{}\n\n[See original message]({})",
|
||||
suggestion,
|
||||
ctx.msg.link(),
|
||||
));
|
||||
let mut author = serenity::builder::CreateEmbedAuthor::default();
|
||||
author
|
||||
.icon_url(get_avatar(&msg.author))
|
||||
let mut embed_author = serenity::builder::CreateEmbedAuthor::default();
|
||||
embed_author
|
||||
.icon_url(get_avatar(&author))
|
||||
.name(username)
|
||||
.url(format!("https://discord.com/users/{}", msg.author.id));
|
||||
e.set_author(author);
|
||||
.url(format!("https://discord.com/users/{}", author.id));
|
||||
e.set_author(embed_author);
|
||||
if let Some(accent_color) = accent_color {
|
||||
e.color(accent_color);
|
||||
}
|
||||
|
@ -380,6 +366,6 @@ async fn suggest(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||
})
|
||||
.await
|
||||
.unwrap();
|
||||
msg.reply(&ctx.http, "Suggestion sent! Thank you for making a suggestion. If it is chosen to be used in a future challenge, you will be mentioned in the challenge description!").await?;
|
||||
ctx.msg.reply(&ctx.discord.http, "Suggestion sent! Thank you for making a suggestion. If it is chosen to be used in a future challenge, you will be mentioned in the challenge description!").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use crate::utils::*;
|
||||
use serenity::framework::standard::{macros::command, Args, CommandResult};
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
#[command]
|
||||
async fn i(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
let input = args.rest();
|
||||
use crate::serenity;
|
||||
use crate::Error;
|
||||
use crate::Context;
|
||||
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<char> = Vec::new();
|
||||
|
@ -40,9 +45,7 @@ async fn i(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||
if skipped_chars == 1 { "" } else { "s" }
|
||||
));
|
||||
}
|
||||
msg.channel_id
|
||||
.send_message(&ctx.http, |m| {
|
||||
m.reference_message(msg);
|
||||
ctx.send(|m| {
|
||||
m.allowed_mentions(|am| {
|
||||
am.empty_parse();
|
||||
am
|
||||
|
@ -69,50 +72,61 @@ async fn i(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn joyo(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
random_kanji("JOYO", ctx, msg, args).await
|
||||
#[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]
|
||||
async fn jinmeiyo(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
random_kanji("JINMEIYO", ctx, msg, args).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]
|
||||
async fn kyoiku(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
random_kanji("KYOIKU", ctx, msg, args).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<String>,
|
||||
) -> Result<(), Error> {
|
||||
random_kanji("KYOIKU", ctx, subcategory).await
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn jlpt(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
random_kanji("JLPT", ctx, msg, args).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<String>
|
||||
) -> Result<(), Error> {
|
||||
random_kanji("JLPT", ctx, subcategory).await
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn hyogai(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
random_kanji("HYOGAI", ctx, msg, args).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<String>,
|
||||
) -> Result<(), Error> {
|
||||
random_kanji("HYOGAI", ctx, subcategory).await
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn so(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
#[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 text = args.rest();
|
||||
if text.is_empty() {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
"Please provide some text you want the stroke order for.",
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
let mut displayed_characters: Vec<char> = Vec::new();
|
||||
let mut displayed_character_count = 0;
|
||||
for character in text.chars() {
|
||||
if displayed_character_count >= MAX_CHARS {
|
||||
msg.channel_id
|
||||
ctx.channel_id()
|
||||
.say(
|
||||
&ctx.http,
|
||||
&ctx.discord().http,
|
||||
":warning: Maximum number of stroke order diagrams per command reached.",
|
||||
)
|
||||
.await?;
|
||||
|
@ -124,7 +138,7 @@ async fn so(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||
// Don't show same character twice
|
||||
displayed_characters.push(character);
|
||||
displayed_character_count += 1;
|
||||
display_kanji(&ctx, &msg, character, "").await?;
|
||||
display_kanji(ctx, character, "").await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use serenity::framework::standard::macros::hook;
|
||||
use serenity::framework::standard::{macros::command, CommandResult};
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
use crate::Error;
|
||||
use crate::Context;
|
||||
use poise::command;
|
||||
|
||||
use std::env;
|
||||
|
||||
#[command]
|
||||
async fn help(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let prefix = env::var("PREFIX").unwrap();
|
||||
// TODO: Implement proper help text for command-specific help,
|
||||
// see https://github.com/kangalioo/poise/blob/90ac24a8ef621ec6dc3fc452762dc9cfa144f693/examples/framework_usage/main.rs#L18-L38
|
||||
#[command(prefix_command, slash_command, description_localized("en-US", "Get help for the 字ちゃん Tegaki Tuesday bot"))]
|
||||
pub async fn help(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let p = env::var("PREFIX").unwrap();
|
||||
let message = format!(
|
||||
"<:jichan:943336845637480478> Hello! I'm 字【じ】ちゃん (Ji-chan), the Tegaki Tuesday bot (and mascot!).
|
||||
For more information about the challenge, check out the website at <https://tegakituesday.com>
|
||||
|
@ -26,18 +27,8 @@ __**Kanji 漢字**__
|
|||
:game_die: `{p}joyo` Random Jōyō kanji
|
||||
:game_die: `{p}kyoiku <grade|all>` Random Kyōiku kanji
|
||||
:game_die: `{p}jlpt <level|all>` Random JLPT kanji
|
||||
:game_die: `{p}hyogai <group|all>` Random Hyōgai kanji",
|
||||
p = prefix
|
||||
:game_die: `{p}hyogai <group|all>` Random Hyōgai kanji"
|
||||
);
|
||||
msg.reply(&ctx.http, message).await?;
|
||||
ctx.say(message).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[hook]
|
||||
pub async fn unrecognised_command_hook(
|
||||
ctx: &Context,
|
||||
msg: &Message,
|
||||
unrecognised_command_name: &str,
|
||||
) {
|
||||
msg.reply(&ctx.http, &format!("I don't understand the command '{}'. For a list of commands, see `{}help`. Commands are case-sensitive.", unrecognised_command_name, env::var("PREFIX").unwrap())).await.unwrap();
|
||||
}
|
||||
|
|
|
@ -1,38 +1,26 @@
|
|||
use serenity::framework::standard::{macros::command, Args, CommandResult};
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::Context;
|
||||
use crate::Error;
|
||||
use poise::command;
|
||||
|
||||
use serde_json::json;
|
||||
use std::env;
|
||||
|
||||
use crate::utils::*;
|
||||
use crate::ShardManagerContainer;
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
async fn sleep(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let data = ctx.data.read().await;
|
||||
|
||||
if let Some(manager) = data.get::<ShardManagerContainer>() {
|
||||
msg.reply(ctx, "Good night!").await?;
|
||||
manager.lock().await.shutdown_all().await;
|
||||
} else {
|
||||
msg.reply(ctx, "There was a problem getting the shard manager")
|
||||
.await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
pub async fn sleep(ctx: Context<'_>) -> Result<(), crate::Error> {
|
||||
ctx.say("Good night!").await?;
|
||||
ctx.framework().shard_manager.lock().await.shutdown_all().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
#[allow(non_snake_case)]
|
||||
async fn setSubmissionChannel(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
pub async fn setsubmissionchannel(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let mut guild_data = get_guild_data();
|
||||
let guild = msg.guild_id.unwrap().as_u64().to_string();
|
||||
let channel = msg.channel_id.as_u64().to_string();
|
||||
let guild = ctx.guild_id().unwrap().as_u64().to_string();
|
||||
let channel = ctx.channel_id().as_u64().to_string();
|
||||
if guild_data.contains_key(&guild) {
|
||||
let mut current_guild_data = guild_data[&guild].as_object().unwrap().clone();
|
||||
if current_guild_data.contains_key("submissionChannel") {
|
||||
|
@ -45,23 +33,21 @@ async fn setSubmissionChannel(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
guild_data.insert(guild, json!({ "submissionChannel": channel }));
|
||||
}
|
||||
set_guild_data(guild_data);
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
ctx.say(
|
||||
format!(
|
||||
"Submission channel for **{}** set to <#{}>.",
|
||||
msg.guild(&ctx).unwrap().name,
|
||||
msg.channel_id
|
||||
ctx.guild().unwrap().name,
|
||||
ctx.channel_id()
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
#[allow(non_snake_case)]
|
||||
async fn setSuggestionChannel(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let channel = msg.channel_id.as_u64().to_string();
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
pub async fn setsuggestionchannel(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let channel = ctx.channel_id().as_u64().to_string();
|
||||
let message = format!("Submission channel set to <#{}>.", channel);
|
||||
let mut guild_data = get_guild_data();
|
||||
if guild_data.contains_key("submissionChannel") {
|
||||
guild_data["suggestionChannel"] = channel.into();
|
||||
|
@ -69,29 +55,19 @@ async fn setSuggestionChannel(ctx: &Context, msg: &Message) -> CommandResult {
|
|||
guild_data.insert(String::from("suggestionChannel"), channel.into());
|
||||
}
|
||||
set_guild_data(guild_data);
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
format!("Submission channel set to <#{}>.", msg.channel_id),
|
||||
)
|
||||
.await?;
|
||||
ctx.say(message).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
#[allow(non_snake_case)]
|
||||
async fn setAnnouncementRole(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
let role;
|
||||
match args.single::<u64>() {
|
||||
Ok(id) => role = id.to_string(),
|
||||
Err(_) => {
|
||||
msg.reply(&ctx.http, "Please provide an announcement role ID.")
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
pub async fn setannouncementrole(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Announcement role ID"]
|
||||
role: u64,
|
||||
) -> Result<(), Error> {
|
||||
let mut guild_data = get_guild_data();
|
||||
let guild = msg.guild_id.unwrap().as_u64().to_string();
|
||||
let guild = ctx.guild_id().unwrap().as_u64().to_string();
|
||||
if guild_data.contains_key(&guild) {
|
||||
let mut current_guild_data = guild_data[&guild].as_object().unwrap().clone();
|
||||
if current_guild_data.contains_key("announcementRole") {
|
||||
|
@ -104,20 +80,21 @@ async fn setAnnouncementRole(ctx: &Context, msg: &Message, mut args: Args) -> Co
|
|||
guild_data.insert(guild, json!({ "announcementRole": role }));
|
||||
}
|
||||
set_guild_data(guild_data);
|
||||
msg.reply(&ctx.http, "Announcement role set.").await?;
|
||||
ctx.say("Announcement role set.").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
async fn announce(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
send(ctx, msg, args.rest(), true, false).await
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
pub async fn announce(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Announcement text"]
|
||||
announcement: String,
|
||||
) -> Result<(), Error> {
|
||||
send(ctx, &announcement, true, false).await
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
#[allow(non_snake_case)]
|
||||
async fn announceChallenge(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
pub async fn announcechallenge(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let challenge_number = get_challenge_number();
|
||||
let message = format!("Welcome to the **{n}{th}** weekly **Tegaki Tuesday** (手書きの火曜日) handwriting challenge! :pen_fountain: The prompt is available in both Japanese and English on the website at <https://tegakituesday.com/{n}>.
|
||||
|
||||
|
@ -131,15 +108,14 @@ You can make submissions in both languages, but please submit in your target lan
|
|||
},
|
||||
p = env::var("PREFIX").unwrap()
|
||||
);
|
||||
send(ctx, msg, &message, true, false).await
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[owners_only]
|
||||
#[allow(non_snake_case)]
|
||||
async fn rebuildSite(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
rebuild_site();
|
||||
msg.reply(&ctx.http, "Started site rebuild process!")
|
||||
.await?;
|
||||
send(ctx, &message, true, false).await?;
|
||||
ctx.say("Announced!").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command(prefix_command, hide_in_help, owners_only)]
|
||||
pub async fn rebuildsite(ctx: Context<'_>) -> Result<(), Error> {
|
||||
rebuild_site();
|
||||
ctx.say("Started site rebuild process!").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue