Merge pull request 'added lock commands' (#3) from feature/vibecoded-command into main
Reviewed-on: https://codeberg.org/RythonDev/portfolio-roast-bot/pulls/3
This commit is contained in:
commit
7a71fca30d
7 changed files with 331 additions and 23 deletions
|
|
@ -1,3 +1,4 @@
|
|||
pub mod faq;
|
||||
pub mod forum;
|
||||
pub mod info;
|
||||
pub mod lock;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::utils::format::format_embed_description;
|
||||
use crate::{Context, Error};
|
||||
use futures::{Stream, StreamExt};
|
||||
use poise::CreateReply;
|
||||
|
|
@ -10,11 +11,6 @@ struct Faq {
|
|||
description: String,
|
||||
}
|
||||
|
||||
fn format_embed_description<S: Into<String>>(description: S) -> Result<String, Error> {
|
||||
let string_val = description.into();
|
||||
Ok(str::replace(&string_val, "\\n", "\n"))
|
||||
}
|
||||
|
||||
fn faq_exists(conn: &Connection, faq: &str, guild_id: &u64) -> Result<bool, Error> {
|
||||
let guild_id = guild_id.to_string();
|
||||
let exists: bool = conn.query_row(
|
||||
|
|
@ -93,26 +89,33 @@ pub async fn view(
|
|||
let guild_id = server_guild_id.to_string();
|
||||
|
||||
move |conn| {
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, guild_id, title, description FROM faqs WHERE title = ?1 AND guild_id = ?2"
|
||||
)?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT title, description FROM faqs WHERE title = ?1 AND guild_id = ?2",
|
||||
)?;
|
||||
|
||||
let faqs: Vec<Faq> = stmt
|
||||
.query_map([&faq_title, &guild_id], |row| {
|
||||
Ok(Faq {
|
||||
// id: row.get(0)?,
|
||||
// guild_id: row.get(1)?,
|
||||
title: row.get(2)?,
|
||||
description: row.get(3)?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let faqs: Vec<Faq> = stmt
|
||||
.query_map([&faq_title, &guild_id], |row| {
|
||||
Ok(Faq {
|
||||
title: row.get(0)?,
|
||||
description: row.get(1)?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(faqs)
|
||||
}})
|
||||
Ok(faqs)
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
let faq = faqs.first().unwrap();
|
||||
let Some(faq) = faqs.first() else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Error 404")
|
||||
.description("FAQ not found");
|
||||
|
||||
ctx.send(CreateReply::default().ephemeral(true).embed(embed))
|
||||
.await?;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let embed_description = format_embed_description(&faq.description).expect("Format error");
|
||||
let embed = CreateEmbed::new()
|
||||
|
|
@ -143,6 +146,7 @@ pub async fn preview(
|
|||
let server_guild_id = ctx.guild_id().expect("Guild ID not found");
|
||||
let guild_id = server_guild_id.to_string();
|
||||
|
||||
|
||||
move |conn| {
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, guild_id, title, description FROM faqs WHERE title = ?1 AND guild_id = ?2"
|
||||
|
|
@ -163,9 +167,8 @@ pub async fn preview(
|
|||
}})
|
||||
.await?;
|
||||
|
||||
let faq = faqs.first().unwrap();
|
||||
let faq = faqs.first().expect("FAQ not found");
|
||||
|
||||
// let embed_description = format_embed_description(&faq.description).expect("Format error");
|
||||
let embed = CreateEmbed::new().title(&faq.title).description(format!(
|
||||
"```
|
||||
{}
|
||||
|
|
|
|||
281
src/commands/lock.rs
Normal file
281
src/commands/lock.rs
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
use crate::utils::format::format_embed_description;
|
||||
use crate::{Context, Error};
|
||||
use poise::CreateReply;
|
||||
use rusqlite::Connection;
|
||||
use serenity::all::CreateEmbed;
|
||||
use serenity::builder::EditThread;
|
||||
|
||||
struct LockEmbed {
|
||||
title: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
fn lock_message_exists(conn: &Connection, guild_id: &u64) -> Result<bool, Error> {
|
||||
let guild_id = guild_id.to_string();
|
||||
let exists: bool = conn.query_row(
|
||||
"SELECT EXISTS(SELECT 1 FROM lock WHERE guild_id = ?1)",
|
||||
[&guild_id],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
|
||||
Ok(exists)
|
||||
}
|
||||
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
subcommands("vibecoded", "preview", "add", "edit", "delete"),
|
||||
guild_only
|
||||
)]
|
||||
pub async fn lock(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Post the vibe coded slop embed message
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
required_permissions = "MANAGE_MESSAGES" // mod only
|
||||
)]
|
||||
pub async fn vibecoded(
|
||||
ctx: Context<'_>,
|
||||
#[description = "additional comment"] comment_option: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let data = ctx.data();
|
||||
|
||||
// lock thread, if it's a thread in a forum
|
||||
|
||||
// let thread_lock = EditThread::new().locked(true);
|
||||
let mut channel = ctx.guild_channel().await.expect("Not a thread");
|
||||
channel
|
||||
.edit_thread(ctx, EditThread::new().locked(true))
|
||||
.await
|
||||
.expect("Failed to lock thread, check permissions");
|
||||
|
||||
let lock_messages = data
|
||||
.execute_db({
|
||||
let server_guild_id = ctx.guild_id().expect("Guild ID not found");
|
||||
let guild_id = server_guild_id.to_string();
|
||||
|
||||
move |conn| {
|
||||
let mut stmt =
|
||||
conn.prepare("SELECT title, description FROM lock WHERE guild_id = ?1")?;
|
||||
|
||||
let lock_messages: Vec<LockEmbed> = stmt
|
||||
.query_map([&guild_id], |row| {
|
||||
Ok(LockEmbed {
|
||||
title: row.get(0)?,
|
||||
description: row.get(1)?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(lock_messages)
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
let Some(lock_message) = lock_messages.first() else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Error 404")
|
||||
.description("Lock message not found");
|
||||
|
||||
ctx.send(CreateReply::default().embed(embed).ephemeral(true))
|
||||
.await?;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let mut embed_description =
|
||||
format_embed_description(&lock_message.description).expect("Format error");
|
||||
if !comment_option.is_none() {
|
||||
let comment = comment_option.expect("Comment error");
|
||||
let new_description = format!(
|
||||
"{}\n\n**Additional Comment(s)**\n{}",
|
||||
&lock_message.description, comment
|
||||
);
|
||||
embed_description = format_embed_description(new_description).expect("Format error");
|
||||
}
|
||||
let embed = CreateEmbed::new()
|
||||
.title(&lock_message.title)
|
||||
.description(embed_description)
|
||||
.color(0xff0000);
|
||||
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add vibe coded slop embed message
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
required_permissions = "MANAGE_MESSAGES" // mod only
|
||||
)]
|
||||
pub async fn add(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Lock message title"] title: String,
|
||||
#[description = "Lock message description"] description: String,
|
||||
) -> Result<(), Error> {
|
||||
let data: &crate::Data = ctx.data();
|
||||
|
||||
let result = data
|
||||
.execute_db({
|
||||
let title = title.clone();
|
||||
let description = description.clone();
|
||||
|
||||
let server_guild_id = ctx.guild_id().expect("Guild ID not found");
|
||||
let guild_id = server_guild_id.get();
|
||||
move |conn| {
|
||||
let exists = lock_message_exists(conn, &guild_id).unwrap_or(false);
|
||||
|
||||
if !exists {
|
||||
conn.execute(
|
||||
"INSERT INTO lock (guild_id, title, description) VALUES (?1, ?2, ?3)",
|
||||
[guild_id.to_string(), title, description],
|
||||
)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
if result == 1 {
|
||||
let embed_description = format_embed_description(description).expect("Format error");
|
||||
let embed = CreateEmbed::new()
|
||||
.title(format!("Added Lock Message: {}", &title))
|
||||
.description(embed_description);
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
} else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title(format!("Error adding lock message: {}", &title))
|
||||
.description("Lock message already exists!");
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Preview lock message
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
required_permissions = "MANAGE_MESSAGES" // mod only
|
||||
)]
|
||||
pub async fn preview(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let data = ctx.data();
|
||||
|
||||
let lock_messages = data
|
||||
.execute_db({
|
||||
let server_guild_id = ctx.guild_id().expect("Guild ID not found");
|
||||
let guild_id = server_guild_id.to_string();
|
||||
|
||||
move |conn| {
|
||||
let mut stmt =
|
||||
conn.prepare("SELECT title, description FROM lock WHERE guild_id = ?1")?;
|
||||
|
||||
let lock_messages: Vec<LockEmbed> = stmt
|
||||
.query_map([&guild_id], |row| {
|
||||
Ok(LockEmbed {
|
||||
title: row.get(0)?,
|
||||
description: row.get(1)?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(lock_messages)
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
let lock_message = lock_messages.first().expect("Lock message not found");
|
||||
|
||||
let embed = CreateEmbed::new()
|
||||
.title(&lock_message.title)
|
||||
.description(format!(
|
||||
"```
|
||||
{}
|
||||
```",
|
||||
&lock_message.description
|
||||
));
|
||||
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Edit lock message
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
required_permissions = "MANAGE_MESSAGES"
|
||||
)]
|
||||
pub async fn edit(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Title"] title: String,
|
||||
#[description = "Description"] description: String,
|
||||
) -> Result<(), Error> {
|
||||
let data = ctx.data();
|
||||
|
||||
let result = data
|
||||
.execute_db({
|
||||
let title = title.clone();
|
||||
let description = description.clone();
|
||||
|
||||
let server_guild_id = ctx.guild_id().expect("Guild ID not found");
|
||||
let guild_id = server_guild_id.get();
|
||||
|
||||
move |conn| {
|
||||
conn.execute(
|
||||
"UPDATE lock SET description = ?3, title = ?2 WHERE guild_id = ?1",
|
||||
[guild_id.to_string(), title, description],
|
||||
)
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
let embed_description = format_embed_description(description).expect("Format error");
|
||||
|
||||
if result == 1 {
|
||||
let embed = CreateEmbed::new()
|
||||
.title(format!("Edited lock message: {}", &title))
|
||||
.description(&embed_description);
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
} else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title(format!("Error editing lock message: {}", &title))
|
||||
.description(format!("{} rows were affected", result));
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Delete lock message
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
required_permissions = "MANAGE_MESSAGES"
|
||||
)]
|
||||
pub async fn delete(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let data = ctx.data();
|
||||
let server_guild_id = ctx.guild_id().expect("Guild ID not found");
|
||||
let guild_id = server_guild_id.to_string();
|
||||
|
||||
let result = data
|
||||
.execute_db({
|
||||
move |conn| conn.execute("DELETE FROM lock WHERE guild_id = ?1", [guild_id])
|
||||
})
|
||||
.await?;
|
||||
|
||||
if result == 1 {
|
||||
let embed = CreateEmbed::new().title(format!("Deleted lock message for this server"));
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
} else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title(format!("Error deleting lock message, ask Ryan"))
|
||||
.description(format!("{} rows were affected", result));
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -62,6 +62,20 @@ pub fn init_tables(conn: &Connection) -> Result<()> {
|
|||
.expect("Forum Channels Table Creation error");
|
||||
}
|
||||
|
||||
let lock_table_exists = table_exists(conn, "lock").expect("Lock table exists error");
|
||||
if !lock_table_exists {
|
||||
conn.execute(
|
||||
"CREATE TABLE lock (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
guild_id TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL
|
||||
)",
|
||||
(),
|
||||
)
|
||||
.expect("Lock Table Creation error");
|
||||
}
|
||||
|
||||
// if we need to create more tables we'll use this function
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use tokio::sync::Mutex;
|
|||
mod commands;
|
||||
mod database;
|
||||
mod events;
|
||||
mod utils;
|
||||
use crate::database::database::{init_db, init_tables};
|
||||
|
||||
// Types used by all command functions
|
||||
|
|
@ -89,6 +90,7 @@ async fn main() {
|
|||
commands::info::help(),
|
||||
commands::faq::faq(),
|
||||
commands::forum::forum(),
|
||||
commands::lock::lock(),
|
||||
],
|
||||
event_handler: |ctx, event, framework, data| {
|
||||
Box::pin(event_handler(ctx, event, framework, data))
|
||||
|
|
|
|||
1
src/utils.rs
Normal file
1
src/utils.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod format;
|
||||
6
src/utils/format.rs
Normal file
6
src/utils/format.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
use crate::Error;
|
||||
|
||||
pub fn format_embed_description<S: Into<String>>(description: S) -> Result<String, Error> {
|
||||
let string_val = description.into();
|
||||
Ok(str::replace(&string_val, "\\n", "\n"))
|
||||
}
|
||||
Loading…
Reference in a new issue