added FAQ
This commit is contained in:
parent
1673087e07
commit
17fa355ecb
7 changed files with 128 additions and 14 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
/target
|
||||
.env
|
||||
*.sqlite
|
||||
13
Cargo.lock
generated
13
Cargo.lock
generated
|
|
@ -453,6 +453,7 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
|||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
|
|
@ -475,6 +476,17 @@ version = "0.3.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.31"
|
||||
|
|
@ -1185,6 +1197,7 @@ name = "portfolio-roast-bot"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"futures",
|
||||
"poise",
|
||||
"reqwest",
|
||||
"rusqlite",
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@ serenity = "0.12.5"
|
|||
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
||||
serde = "1.0.228"
|
||||
rusqlite = { version = "0.37.0", features = ["bundled"] }
|
||||
futures = "0.3.31"
|
||||
|
|
|
|||
|
|
@ -7,3 +7,8 @@ To do:
|
|||
- [ ] FAQs
|
||||
- [ ] Slash commands
|
||||
- [ ] Portfolio Roast Forum: One tag only
|
||||
|
||||
FAQ table
|
||||
- ID: Primary Key
|
||||
- title: string
|
||||
- description: string
|
||||
BIN
bot_data.sqlite
BIN
bot_data.sqlite
Binary file not shown.
|
|
@ -1,24 +1,118 @@
|
|||
use crate::{Context, Error};
|
||||
use futures::{Stream, StreamExt};
|
||||
use poise::CreateReply;
|
||||
use serenity::all::{CreateEmbed};
|
||||
|
||||
#[poise::command(slash_command, subcommands("add", "child2"))]
|
||||
// Define your FAQ struct
|
||||
struct Faq {
|
||||
// id: i64,
|
||||
title: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
async fn autocomplete_faq_titles<'a>(
|
||||
ctx: Context<'_>,
|
||||
partial: &'a str,
|
||||
) -> impl Stream<Item = String> + 'a {
|
||||
let data = ctx.data();
|
||||
|
||||
let fetch_faqs = data
|
||||
.execute_db(|conn| {
|
||||
let mut stmt = conn.prepare("SELECT ID, title, description FROM faqs")?;
|
||||
|
||||
let faqs: Vec<Faq> = stmt
|
||||
.query_map([], |row| {
|
||||
Ok(Faq {
|
||||
title: row.get(1)?,
|
||||
description: row.get(2)?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(faqs)
|
||||
})
|
||||
.await;
|
||||
|
||||
let faqs: Vec<Faq> = fetch_faqs.unwrap_or(vec![]);
|
||||
|
||||
// Now you can use the faqs Vec
|
||||
// ctx.say(format!("Found {} FAQs", faqs.len())).await?;
|
||||
|
||||
futures::stream::iter(faqs)
|
||||
.filter(move |faq| futures::future::ready(faq.title.starts_with(partial)))
|
||||
.map(|faq| faq.title)
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, subcommands("view", "add"))]
|
||||
pub async fn faq(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// View messages
|
||||
#[poise::command(prefix_command, slash_command)]
|
||||
pub async fn view(
|
||||
ctx: Context<'_>,
|
||||
#[description = "FAQ Title"]
|
||||
#[autocomplete = "autocomplete_faq_titles"]
|
||||
faq_title: String,
|
||||
) -> Result<(), Error> {
|
||||
let data = ctx.data();
|
||||
|
||||
let faqs = data
|
||||
.execute_db(move |conn| {
|
||||
let mut stmt = conn.prepare(&format!("SELECT ID, title, description FROM faqs WHERE title='{}'", &faq_title))?;
|
||||
|
||||
let faqs: Vec<Faq> = stmt
|
||||
.query_map([], |row| {
|
||||
Ok(Faq {
|
||||
// id: row.get(0)?,
|
||||
title: row.get(1)?,
|
||||
description: row.get(2)?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(faqs)
|
||||
})
|
||||
.await?;
|
||||
|
||||
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);
|
||||
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A subcommand of `parent`
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
required_permissions = "MANAGE_MESSAGES" // mod only
|
||||
)]
|
||||
pub async fn add(ctx: Context<'_>) -> Result<(), Error> {
|
||||
ctx.say("You invoked the first child command!").await?;
|
||||
Ok(())
|
||||
}
|
||||
pub async fn add(
|
||||
ctx: Context<'_>,
|
||||
#[description = "FAQ title"] title: String,
|
||||
#[description = "FAQ description"] description: String,
|
||||
) -> Result<(), Error> {
|
||||
let data = ctx.data();
|
||||
|
||||
let result = data
|
||||
.execute_db(|conn| {
|
||||
conn.execute(
|
||||
"INSERT INTO faqs (title, description) VALUES (?1, ?2)",
|
||||
[title, description],
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Now you can use the faqs Vec
|
||||
ctx.say(format!("{} rows affected", result)).await?;
|
||||
|
||||
/// Another subcommand of `parent`
|
||||
#[poise::command(prefix_command, slash_command)]
|
||||
pub async fn child2(ctx: Context<'_>) -> Result<(), Error> {
|
||||
ctx.say("You invoked the second child command!").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub struct Data {
|
|||
}
|
||||
|
||||
impl Data {
|
||||
// Helper method to safely execute database operations
|
||||
// helper method to safely execute database operations
|
||||
pub async fn execute_db<F, R>(&self, f: F) -> Result<R, Error>
|
||||
where
|
||||
F: FnOnce(&Connection) -> Result<R, rusqlite::Error> + Send + 'static,
|
||||
|
|
@ -80,7 +80,7 @@ async fn main() {
|
|||
|
||||
let framework = poise::Framework::builder()
|
||||
.options(poise::FrameworkOptions {
|
||||
commands: vec![commands::info::help()],
|
||||
commands: vec![commands::info::help(), commands::faq::faq()],
|
||||
event_handler: |ctx, event, framework, data| {
|
||||
Box::pin(event_handler(ctx, event, framework, data))
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue