|
|
@ -34,7 +34,11 @@ pub async fn challenge(ctx: Context<'_>) -> Result<(), Error> {
|
|
|
|
broadcast_typing,
|
|
|
|
broadcast_typing,
|
|
|
|
description_localized("en-US", "Submit to the latest handwriting challenge.")
|
|
|
|
description_localized("en-US", "Submit to the latest handwriting challenge.")
|
|
|
|
)]
|
|
|
|
)]
|
|
|
|
pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Result<(), Error> {
|
|
|
|
pub async fn submit(
|
|
|
|
|
|
|
|
ctx: Context<'_>,
|
|
|
|
|
|
|
|
challenge: Option<i32>,
|
|
|
|
|
|
|
|
submission: serenity::Attachment
|
|
|
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
// TODO: The code for this command needs to be refactored,
|
|
|
|
// TODO: The code for this command needs to be refactored,
|
|
|
|
// there are large duplicated sections that need to be merged somehow.
|
|
|
|
// there are large duplicated sections that need to be merged somehow.
|
|
|
|
match ctx {
|
|
|
|
match ctx {
|
|
|
@ -71,16 +75,30 @@ pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Resul
|
|
|
|
.await?;
|
|
|
|
.await?;
|
|
|
|
return Ok(());
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let latest_challenge = get_challenge_number();
|
|
|
|
let challenge_number = get_challenge_number();
|
|
|
|
let late;
|
|
|
|
let submission_images_dir = get_submission_images_dir();
|
|
|
|
let challenge_number = match challenge {
|
|
|
|
|
|
|
|
Some(challenge) => {
|
|
|
|
|
|
|
|
if challenge > latest_challenge {
|
|
|
|
|
|
|
|
ctx.say(format!("That challenge doesn't exist, the latest challenge is #{latest_challenge}.")).await?;
|
|
|
|
|
|
|
|
return Ok(());
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
late = challenge < latest_challenge;
|
|
|
|
|
|
|
|
challenge
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
None => {
|
|
|
|
|
|
|
|
late = false;
|
|
|
|
|
|
|
|
get_challenge_number()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
let submission_images_dir = get_submission_images_dir(challenge_number);
|
|
|
|
let timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis();
|
|
|
|
let timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis();
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure that submission_images_dir exists
|
|
|
|
// Ensure that submission_images_dir exists
|
|
|
|
let path = Path::new(&submission_images_dir);
|
|
|
|
let path = Path::new(&submission_images_dir);
|
|
|
|
std::fs::create_dir_all(path)?;
|
|
|
|
std::fs::create_dir_all(path)?;
|
|
|
|
|
|
|
|
|
|
|
|
let mut submission_data = get_current_submission_data();
|
|
|
|
let mut submission_data = get_submission_data(challenge_number);
|
|
|
|
let mut existing_submitter = false;
|
|
|
|
let mut existing_submitter = false;
|
|
|
|
let mut invalid_types = false;
|
|
|
|
let mut invalid_types = false;
|
|
|
|
let mut requires_rebuild = false;
|
|
|
|
let mut requires_rebuild = false;
|
|
|
@ -92,7 +110,7 @@ pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Resul
|
|
|
|
let author = ctx.author();
|
|
|
|
let author = ctx.author();
|
|
|
|
let mut submitted_images = Vec::new();
|
|
|
|
let mut submitted_images = Vec::new();
|
|
|
|
for submission in submission_data.iter_mut() {
|
|
|
|
for submission in submission_data.iter_mut() {
|
|
|
|
if is_matching_submission(&submission, author) {
|
|
|
|
if is_matching_submission(&submission, author) && late == (submission.as_object().unwrap().contains_key("late") && submission["late"].as_bool().unwrap()) {
|
|
|
|
existing_submitter = true;
|
|
|
|
existing_submitter = true;
|
|
|
|
let mut images: Vec<String> = submission["images"].as_array_mut().unwrap().clone().iter().map(|value| value.as_str().unwrap().to_owned()).collect();
|
|
|
|
let mut images: Vec<String> = submission["images"].as_array_mut().unwrap().clone().iter().map(|value| value.as_str().unwrap().to_owned()).collect();
|
|
|
|
for (i, attachment) in attachments.iter().enumerate() {
|
|
|
|
for (i, attachment) in attachments.iter().enumerate() {
|
|
|
@ -173,9 +191,12 @@ pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Resul
|
|
|
|
}
|
|
|
|
}
|
|
|
|
submitter_data.insert(String::from("images"), images.into());
|
|
|
|
submitter_data.insert(String::from("images"), images.into());
|
|
|
|
submitter_data.insert(String::from("id"), author.id.as_u64().to_string().into());
|
|
|
|
submitter_data.insert(String::from("id"), author.id.as_u64().to_string().into());
|
|
|
|
|
|
|
|
if late {
|
|
|
|
|
|
|
|
submitter_data.insert(String::from("late"), true.into());
|
|
|
|
|
|
|
|
}
|
|
|
|
submission_data.push(submitter_data.into());
|
|
|
|
submission_data.push(submitter_data.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
set_submission_data(submission_data);
|
|
|
|
set_submission_data(challenge_number, submission_data);
|
|
|
|
let mut message = String::new();
|
|
|
|
let mut message = String::new();
|
|
|
|
if requires_rebuild {
|
|
|
|
if requires_rebuild {
|
|
|
|
let thank_you = &format!("Thank you for submitting! You can view your submission at <https://tegakituesday.com/{}>", challenge_number);
|
|
|
|
let thank_you = &format!("Thank you for submitting! You can view your submission at <https://tegakituesday.com/{}>", challenge_number);
|
|
|
@ -206,7 +227,7 @@ pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Resul
|
|
|
|
for image in submitted_images.iter() {
|
|
|
|
for image in submitted_images.iter() {
|
|
|
|
for (other_guild_id, data) in guild_data.iter() {
|
|
|
|
for (other_guild_id, data) in guild_data.iter() {
|
|
|
|
let here = other_guild_id.eq(&ctx.guild_id().unwrap().as_u64().to_string());
|
|
|
|
let here = other_guild_id.eq(&ctx.guild_id().unwrap().as_u64().to_string());
|
|
|
|
if !repost_here && here {
|
|
|
|
if (late && !here) || (!repost_here && here) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let data = data.as_object().unwrap();
|
|
|
|
let data = data.as_object().unwrap();
|
|
|
@ -230,8 +251,7 @@ pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Resul
|
|
|
|
channel.send_message(&ctx.discord().http, |m| {
|
|
|
|
channel.send_message(&ctx.discord().http, |m| {
|
|
|
|
m.embed(|e| {
|
|
|
|
m.embed(|e| {
|
|
|
|
let username = format!("{}#{}", author.name, author.discriminator);
|
|
|
|
let username = format!("{}#{}", author.name, author.discriminator);
|
|
|
|
let n = get_challenge_number();
|
|
|
|
let mut description = format!("New {}submission to [Tegaki Tuesday #{n}](https://tegakituesday.com/{n})!", if late { "late " } else { "" }, n = challenge_number);
|
|
|
|
let mut description = format!("New submission to [Tegaki Tuesday #{n}](https://tegakituesday.com/{n})!");
|
|
|
|
|
|
|
|
if !here {
|
|
|
|
if !here {
|
|
|
|
description.push_str(&if let Some(invite) = invite {
|
|
|
|
description.push_str(&if let Some(invite) = invite {
|
|
|
|
format!("\nCrossposted from [{}](https://discord.gg/{invite})", guild.name)
|
|
|
|
format!("\nCrossposted from [{}](https://discord.gg/{invite})", guild.name)
|
|
|
@ -246,7 +266,7 @@ pub async fn submit(ctx: Context<'_>, submission: serenity::Attachment) -> Resul
|
|
|
|
.name(username)
|
|
|
|
.name(username)
|
|
|
|
.url(format!("https://discord.com/users/{}", author.id));
|
|
|
|
.url(format!("https://discord.com/users/{}", author.id));
|
|
|
|
e.set_author(embed_author);
|
|
|
|
e.set_author(embed_author);
|
|
|
|
e.image(format!("https://tegakituesday.com/{n}/{image}#{timestamp}"));
|
|
|
|
e.image(format!("https://tegakituesday.com/{challenge_number}/{image}#{timestamp}"));
|
|
|
|
if let Some(accent_color) = accent_color {
|
|
|
|
if let Some(accent_color) = accent_color {
|
|
|
|
e.color(accent_color);
|
|
|
|
e.color(accent_color);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -358,7 +378,7 @@ pub async fn imagedelete(ctx: Context<'_>, number: i32) -> Result<(), Error> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let index = number as usize - 1;
|
|
|
|
let index = number as usize - 1;
|
|
|
|
let image = images[index].as_str().unwrap().to_owned();
|
|
|
|
let image = images[index].as_str().unwrap().to_owned();
|
|
|
|
let submission_images_dir = get_submission_images_dir();
|
|
|
|
let submission_images_dir = get_submission_images_dir(challenge_number);
|
|
|
|
let image_path = format!("{}/{}", submission_images_dir, image);
|
|
|
|
let image_path = format!("{}/{}", submission_images_dir, image);
|
|
|
|
match fs::remove_file(image_path) {
|
|
|
|
match fs::remove_file(image_path) {
|
|
|
|
Ok(_) => (),
|
|
|
|
Ok(_) => (),
|
|
|
@ -374,7 +394,7 @@ pub async fn imagedelete(ctx: Context<'_>, number: i32) -> Result<(), Error> {
|
|
|
|
images.remove(index);
|
|
|
|
images.remove(index);
|
|
|
|
submission["images"] = images.into();
|
|
|
|
submission["images"] = images.into();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
set_submission_data(submission_data);
|
|
|
|
set_submission_data(challenge_number, submission_data);
|
|
|
|
rebuild_site();
|
|
|
|
rebuild_site();
|
|
|
|
ctx.say(message).await?;
|
|
|
|
ctx.say(message).await?;
|
|
|
|
return Ok(());
|
|
|
|
return Ok(());
|
|
|
@ -387,7 +407,6 @@ pub async fn imagedelete(ctx: Context<'_>, number: i32) -> Result<(), Error> {
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: make also slash command
|
|
|
|
|
|
|
|
#[command(
|
|
|
|
#[command(
|
|
|
|
prefix_command,
|
|
|
|
prefix_command,
|
|
|
|
slash_command,
|
|
|
|
slash_command,
|
|
|
|