WIP late submissions
This commit is contained in:
parent
b90ef09836
commit
1db0d0da0c
2 changed files with 44 additions and 23 deletions
|
@ -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,
|
||||||
|
|
20
src/utils.rs
20
src/utils.rs
|
@ -38,18 +38,14 @@ pub fn get_hugo_path() -> String {
|
||||||
env::var("HUGO").unwrap()
|
env::var("HUGO").unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_submission_images_dir() -> String {
|
pub fn get_submission_images_dir(challenge: i32) -> String {
|
||||||
format!("{}/assets/{}", get_hugo_path(), get_challenge_number())
|
format!("{}/assets/{challenge}", get_hugo_path())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_submission_data_path(challenge: i32) -> String {
|
pub fn get_submission_data_path(challenge: i32) -> String {
|
||||||
format!("{}/data/challenges/{}.json", get_hugo_path(), challenge)
|
format!("{}/data/challenges/{}.json", get_hugo_path(), challenge)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_current_submission_data_path() -> String {
|
|
||||||
get_submission_data_path(get_challenge_number())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_current_submission_data() -> Vec<Value> {
|
pub fn get_current_submission_data() -> Vec<Value> {
|
||||||
get_submission_data(get_challenge_number())
|
get_submission_data(get_challenge_number())
|
||||||
}
|
}
|
||||||
|
@ -74,12 +70,12 @@ pub fn get_submission_data(challenge: i32) -> Vec<Value> {
|
||||||
submission_data.as_array_mut().unwrap().clone()
|
submission_data.as_array_mut().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_submission_data(submission_data: Vec<Value>) {
|
pub fn set_submission_data(challenge: i32, submission_data: Vec<Value>) {
|
||||||
let submission_data: Value = submission_data.into();
|
let submission_data: Value = submission_data.into();
|
||||||
let mut submission_data_file = OpenOptions::new()
|
let mut submission_data_file = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(get_current_submission_data_path())
|
.open(get_submission_data_path(challenge))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
submission_data_file
|
submission_data_file
|
||||||
.write_all(
|
.write_all(
|
||||||
|
@ -359,9 +355,14 @@ pub async fn leaderboard(ctx: &Context<'_>) -> Result<(), Error> {
|
||||||
for challenge in 1..get_challenge_number() + 1 {
|
for challenge in 1..get_challenge_number() + 1 {
|
||||||
let submission_data = get_submission_data(challenge);
|
let submission_data = get_submission_data(challenge);
|
||||||
for submission in submission_data.iter() {
|
for submission in submission_data.iter() {
|
||||||
|
let submission = submission.as_object().unwrap();
|
||||||
|
if submission.contains_key("late") && submission["late"].as_bool().unwrap() {
|
||||||
|
// Don't count late submissions toward leaderboard
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let user = submission_counts
|
let user = submission_counts
|
||||||
.entry(String::from(
|
.entry(String::from(
|
||||||
submission.as_object().unwrap()["id"].as_str().unwrap(),
|
submission["id"].as_str().unwrap(),
|
||||||
))
|
))
|
||||||
.or_insert(0);
|
.or_insert(0);
|
||||||
*user += 1;
|
*user += 1;
|
||||||
|
@ -384,6 +385,7 @@ pub async fn leaderboard(ctx: &Context<'_>) -> Result<(), Error> {
|
||||||
leaderboard_html.push_str("</table>");
|
leaderboard_html.push_str("</table>");
|
||||||
let mut file = std::fs::OpenOptions::new()
|
let mut file = std::fs::OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
|
.truncate(true) // potential fix for trailing >table> after leaderboard
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(env::var("LEADERBOARD").unwrap())
|
.open(env::var("LEADERBOARD").unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Add table
Reference in a new issue