added FAQ
This commit is contained in:
parent
1673087e07
commit
17fa355ecb
7 changed files with 128 additions and 14 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
.env
|
.env
|
||||||
|
*.sqlite
|
||||||
13
Cargo.lock
generated
13
Cargo.lock
generated
|
|
@ -453,6 +453,7 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
|
@ -475,6 +476,17 @@ version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
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]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
|
@ -1185,6 +1197,7 @@ name = "portfolio-roast-bot"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"futures",
|
||||||
"poise",
|
"poise",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,5 @@ serde_json = "1.0.145"
|
||||||
serenity = "0.12.5"
|
serenity = "0.12.5"
|
||||||
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
||||||
serde = "1.0.228"
|
serde = "1.0.228"
|
||||||
rusqlite = { version = "0.37.0", features = ["bundled"] }
|
rusqlite = { version = "0.37.0", features = ["bundled"] }
|
||||||
|
futures = "0.3.31"
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,9 @@ To do:
|
||||||
- [ ] Database
|
- [ ] Database
|
||||||
- [ ] FAQs
|
- [ ] FAQs
|
||||||
- [ ] Slash commands
|
- [ ] Slash commands
|
||||||
- [ ] Portfolio Roast Forum: One tag only
|
- [ ] 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 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> {
|
pub async fn faq(_ctx: Context<'_>) -> Result<(), Error> {
|
||||||
Ok(())
|
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`
|
/// A subcommand of `parent`
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
prefix_command,
|
prefix_command,
|
||||||
slash_command,
|
slash_command,
|
||||||
required_permissions = "MANAGE_MESSAGES" // mod only
|
required_permissions = "MANAGE_MESSAGES" // mod only
|
||||||
)]
|
)]
|
||||||
pub async fn add(ctx: Context<'_>) -> Result<(), Error> {
|
pub async fn add(
|
||||||
ctx.say("You invoked the first child command!").await?;
|
ctx: Context<'_>,
|
||||||
Ok(())
|
#[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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ pub struct Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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>
|
pub async fn execute_db<F, R>(&self, f: F) -> Result<R, Error>
|
||||||
where
|
where
|
||||||
F: FnOnce(&Connection) -> Result<R, rusqlite::Error> + Send + 'static,
|
F: FnOnce(&Connection) -> Result<R, rusqlite::Error> + Send + 'static,
|
||||||
|
|
@ -80,7 +80,7 @@ async fn main() {
|
||||||
|
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
commands: vec![commands::info::help()],
|
commands: vec![commands::info::help(), commands::faq::faq()],
|
||||||
event_handler: |ctx, event, framework, data| {
|
event_handler: |ctx, event, framework, data| {
|
||||||
Box::pin(event_handler(ctx, event, framework, data))
|
Box::pin(event_handler(ctx, event, framework, data))
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue