added edit faq command

This commit is contained in:
liyunze 2026-01-06 13:24:40 +08:00
parent 7c3e66f513
commit 56f28d5891
2 changed files with 106 additions and 23 deletions

View file

@ -1,7 +1,10 @@
use std::string;
use crate::{Context, Error};
use futures::{Stream, StreamExt};
use poise::CreateReply;
use serenity::all::{CreateEmbed};
use rusqlite::Connection;
use serenity::all::CreateEmbed;
// Define your FAQ struct
struct Faq {
@ -10,6 +13,21 @@ 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) -> Result<bool, Error> {
let exists: bool = conn.query_row(
"SELECT EXISTS(SELECT 1 FROM faqs WHERE title = ?)",
[faq],
|row| row.get(0),
)?;
Ok(exists)
}
async fn autocomplete_faq_titles<'a>(
ctx: Context<'_>,
partial: &'a str,
@ -43,12 +61,12 @@ async fn autocomplete_faq_titles<'a>(
.map(|faq| faq.title)
}
#[poise::command(slash_command, subcommands("view", "add"))]
#[poise::command(slash_command, subcommands("view", "add", "edit"))]
pub async fn faq(_ctx: Context<'_>) -> Result<(), Error> {
Ok(())
}
/// View messages
/// View FAQ
#[poise::command(prefix_command, slash_command)]
pub async fn view(
ctx: Context<'_>,
@ -60,7 +78,10 @@ pub async fn view(
let faqs = data
.execute_db(move |conn| {
let mut stmt = conn.prepare(&format!("SELECT ID, title, description FROM faqs WHERE title='{}'", &faq_title))?;
let mut stmt = conn.prepare(&format!(
"SELECT ID, title, description FROM faqs WHERE title='{}'",
&faq_title
))?;
let faqs: Vec<Faq> = stmt
.query_map([], |row| {
@ -78,18 +99,17 @@ pub async fn view(
let faq = faqs.first().unwrap();
// Now you can use the faqs Vec
// ctx.say(format!("# {}\n{}", faqs[0].title, faqs[0].description )).await?;
// #131416 19,20,22
let embed = CreateEmbed::new().title(&faq.title).description(&faq.description);
let embed_description = format_embed_description(&faq.description).expect("Format error");
let embed = CreateEmbed::new()
.title(&faq.title)
.description(embed_description);
ctx.send(CreateReply::default().embed(embed)).await?;
Ok(())
}
/// A subcommand of `parent`
/// Add FAQ
#[poise::command(
prefix_command,
slash_command,
@ -100,19 +120,85 @@ pub async fn add(
#[description = "FAQ title"] title: String,
#[description = "FAQ description"] description: String,
) -> Result<(), Error> {
let data = ctx.data();
let data: &crate::Data = ctx.data();
let result = data
.execute_db(|conn| {
conn.execute(
"INSERT INTO faqs (title, description) VALUES (?1, ?2)",
[title, description],
)
.execute_db({
let title = title.clone();
let description = description.clone();
|conn| {
let exists = faq_exists(conn, &title).unwrap_or(false);
if !exists {
conn.execute(
"INSERT INTO faqs (title, description) VALUES (?1, ?2)",
[title, description],
)
} else {
Ok(0)
}
}
})
.await?;
// Now you can use the faqs Vec
ctx.say(format!("{} rows affected", result)).await?;
let embed_description = format_embed_description(description).expect("Format error");
if result == 1 {
let embed = CreateEmbed::new()
.title(format!("Added FAQ: {}", &title))
.description(embed_description);
ctx.send(CreateReply::default().embed(embed)).await?;
} else {
let embed = CreateEmbed::new()
.title(format!("Error adding FAQ: {}", &title))
.description("Title already exists!");
ctx.send(CreateReply::default().embed(embed)).await?;
}
Ok(())
}
/// Edit FAQ
#[poise::command(
prefix_command,
slash_command,
required_permissions = "MANAGE_MESSAGES"
)]
pub async fn edit(
ctx: Context<'_>,
#[description = "FAQ Title"]
#[autocomplete = "autocomplete_faq_titles"]
title: String,
#[description = "FAQ description"] description: String,
) -> Result<(), Error> {
let data = ctx.data();
let result = data
.execute_db({
let title = title.clone();
let description = description.clone();
move |conn| {
conn.execute(
"UPDATE faqs SET description = ?2 WHERE title = ?1",
[title, description],
)
}
})
.await?;
let embed_description = format_embed_description(description).expect("Format error");
if result == 1 {
let embed = CreateEmbed::new()
.title(format!("Edited FAQ: {}", &title))
.description(&embed_description);
ctx.send(CreateReply::default().embed(embed)).await?;
} else {
let embed = CreateEmbed::new()
.title(format!("Error editing FAQ: {}", &title))
.description(format!("{} rows were affected", result));
ctx.send(CreateReply::default().embed(embed)).await?;
}
Ok(())
}

View file

@ -15,11 +15,8 @@ pub fn init_db(filename: &str) -> Result<Connection, rusqlite::Error> {
fn table_exists(conn: &Connection, table_name: &str) -> Result<bool> {
let exists: bool = conn.query_row(
&format!(
"SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='table' AND name='{}')",
table_name
),
[],
"SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='table' AND name=?1)",
[table_name],
|row| row.get(0),
)?;