Added a route for importing templates

This commit is contained in:
jude
2024-11-16 14:15:35 +00:00
parent b8ee99cb45
commit 0a9c390f32
7 changed files with 492 additions and 325 deletions

View File

@@ -0,0 +1,181 @@
use crate::web::routes::dashboard::{create_reminder_template, ReminderTemplate};
use crate::web::{
check_authorization,
guards::transaction::Transaction,
routes::{
dashboard::{
create_reminder, CreateReminder, ImportBody, ReminderCsv, ReminderTemplateCsv, TodoCsv,
},
JsonResult,
},
};
use crate::Database;
use base64::{prelude::BASE64_STANDARD, Engine};
use csv::{QuoteStyle, WriterBuilder};
use log::warn;
use rocket::{
get,
http::CookieJar,
put,
serde::json::{json, Json},
State,
};
use serenity::{
client::Context,
model::id::{ChannelId, GuildId, UserId},
};
use sqlx::{MySql, Pool};
#[get("/api/guild/<id>/export/reminder_templates")]
pub async fn export(
id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
pool: &State<Pool<MySql>>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
let mut csv_writer = WriterBuilder::new().quote_style(QuoteStyle::Always).from_writer(vec![]);
match sqlx::query_as_unchecked!(
ReminderTemplateCsv,
"SELECT
name,
attachment,
attachment_name,
avatar,
content,
embed_author,
embed_author_url,
embed_color,
embed_description,
embed_footer,
embed_footer_url,
embed_image_url,
embed_thumbnail_url,
embed_title,
embed_fields,
interval_seconds,
interval_days,
interval_months,
tts,
username
FROM reminder_template WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)",
id
)
.fetch_all(pool.inner())
.await
{
Ok(templates) => {
templates.iter().for_each(|template| {
csv_writer.serialize(template).unwrap();
});
match csv_writer.into_inner() {
Ok(inner) => match String::from_utf8(inner) {
Ok(encoded) => Ok(json!({ "body": encoded })),
Err(e) => {
warn!("Failed to write UTF-8: {:?}", e);
json_err!("Failed to write UTF-8")
}
},
Err(e) => {
warn!("Failed to extract CSV: {:?}", e);
json_err!("Failed to extract CSV")
}
}
}
Err(e) => {
warn!("Could not fetch templates from {}: {:?}", id, e);
json_err!("Failed to query templates")
}
}
}
#[put("/api/guild/<id>/export/reminder_templates", data = "<body>")]
pub async fn import(
id: u64,
cookies: &CookieJar<'_>,
body: Json<ImportBody>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
match BASE64_STANDARD.decode(&body.body) {
Ok(body) => {
let mut reader = csv::Reader::from_reader(body.as_slice());
let mut count = 0;
for result in reader.deserialize::<ReminderTemplateCsv>() {
match result {
Ok(record) => {
let reminder_template = ReminderTemplate {
id: 0,
guild_id: 0,
name: record.name,
attachment: record.attachment,
attachment_name: record.attachment_name,
avatar: record.avatar,
content: record.content,
embed_author: record.embed_author,
embed_author_url: record.embed_author_url,
embed_color: record.embed_color,
embed_description: record.embed_description,
embed_footer: record.embed_footer,
embed_footer_url: record.embed_footer_url,
embed_image_url: record.embed_image_url,
embed_thumbnail_url: record.embed_thumbnail_url,
embed_title: record.embed_title,
embed_fields: record
.embed_fields
.map(|s| serde_json::from_str(&s).ok())
.flatten(),
interval_seconds: record.interval_seconds,
interval_days: record.interval_days,
interval_months: record.interval_months,
tts: record.tts,
username: record.username,
};
create_reminder_template(
ctx.inner(),
&mut transaction,
GuildId::new(id),
reminder_template,
)
.await?;
count += 1;
}
Err(e) => {
warn!("Couldn't deserialize CSV row: {:?}", e);
return json_err!(format!("Deserialize error: {:?}", e));
}
}
}
match transaction.commit().await {
Ok(_) => Ok(json!({
"message": format!("Imported {} reminder templates", count)
})),
Err(e) => {
warn!("Failed to commit transaction: {:?}", e);
json_err!("Couldn't commit transaction")
}
}
}
Err(_) => {
json_err!("Malformed base64")
}
}
}