added db
This commit is contained in:
parent
b73cb21a94
commit
1673087e07
9 changed files with 202 additions and 4 deletions
62
Cargo.lock
generated
62
Cargo.lock
generated
|
|
@ -375,6 +375,18 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-streaming-iterator"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
|
|
@ -403,6 +415,12 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
|
|
@ -572,12 +590,30 @@ version = "0.14.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.4.0"
|
||||
|
|
@ -884,6 +920,17 @@ version = "0.2.178"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
|
|
@ -1140,6 +1187,7 @@ dependencies = [
|
|||
"dotenv",
|
||||
"poise",
|
||||
"reqwest",
|
||||
"rusqlite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serenity",
|
||||
|
|
@ -1419,6 +1467,20 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
"libsqlite3-sys",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ reqwest = "0.12.24"
|
|||
serde_json = "1.0.145"
|
||||
serenity = "0.12.5"
|
||||
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"] }
|
||||
9
README.md
Normal file
9
README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Portfolio roast bot
|
||||
|
||||
---
|
||||
|
||||
To do:
|
||||
- [ ] Database
|
||||
- [ ] FAQs
|
||||
- [ ] Slash commands
|
||||
- [ ] Portfolio Roast Forum: One tag only
|
||||
BIN
bot_data.sqlite
Normal file
BIN
bot_data.sqlite
Normal file
Binary file not shown.
|
|
@ -1 +1,2 @@
|
|||
pub mod faq;
|
||||
pub mod info;
|
||||
|
|
|
|||
24
src/commands/faq.rs
Normal file
24
src/commands/faq.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use crate::{Context, Error};
|
||||
|
||||
#[poise::command(slash_command, subcommands("add", "child2"))]
|
||||
pub async fn faq(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
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(())
|
||||
}
|
||||
|
||||
/// 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(())
|
||||
}
|
||||
1
src/database.rs
Normal file
1
src/database.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod database;
|
||||
51
src/database/database.rs
Normal file
51
src/database/database.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use std::path::Path;
|
||||
|
||||
// Using SQLite
|
||||
use rusqlite::{Connection, OpenFlags, Result};
|
||||
|
||||
pub fn init_db(filename: &str) -> Result<Connection, rusqlite::Error> {
|
||||
let filepath = Path::new(filename);
|
||||
|
||||
let open_flags = OpenFlags::default();
|
||||
|
||||
let conn = Connection::open_with_flags(filepath, open_flags);
|
||||
|
||||
conn
|
||||
}
|
||||
|
||||
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
|
||||
),
|
||||
[],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
|
||||
Ok(exists)
|
||||
}
|
||||
|
||||
pub fn init_tables(conn: &Connection) -> Result<()> {
|
||||
// FAQ table
|
||||
// ID: Primary Key
|
||||
// FAQ title: string
|
||||
// FAQ description: string
|
||||
let faq_table_exists = table_exists(conn, "faqs").expect("FAQ table exists error");
|
||||
|
||||
if !faq_table_exists {
|
||||
conn.execute(
|
||||
"CREATE TABLE faqs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL
|
||||
)",
|
||||
(),
|
||||
)
|
||||
.expect("FAQ Table Creation error");
|
||||
}
|
||||
|
||||
// if we need to create more tables we'll use this function
|
||||
|
||||
Ok(())
|
||||
}
|
||||
55
src/main.rs
55
src/main.rs
|
|
@ -1,14 +1,38 @@
|
|||
use dotenv;
|
||||
use poise::serenity_prelude as serenity;
|
||||
use rusqlite::Connection;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
mod commands;
|
||||
mod database;
|
||||
mod events;
|
||||
|
||||
struct Data {}
|
||||
use crate::database::database::{init_db, init_tables};
|
||||
|
||||
// Types used by all command functions
|
||||
type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||
type Context<'a> = poise::Context<'a, Data, Error>;
|
||||
|
||||
pub struct Data {
|
||||
conn: Arc<Mutex<Connection>>,
|
||||
}
|
||||
|
||||
impl Data {
|
||||
// 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,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let conn = self.conn.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let conn = conn.blocking_lock();
|
||||
f(&conn)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn event_handler(
|
||||
ctx: &serenity::Context,
|
||||
event: &serenity::FullEvent,
|
||||
|
|
@ -24,9 +48,33 @@ async fn event_handler(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn on_error(error: poise::FrameworkError<'_, Data, Error>) {
|
||||
// This is our custom error handler
|
||||
// They are many errors that can occur, so we only handle the ones we want to customize
|
||||
// and forward the rest to the default handler
|
||||
match error {
|
||||
poise::FrameworkError::Setup { error, .. } => panic!("Failed to start bot: {:?}", error),
|
||||
poise::FrameworkError::Command { error, ctx, .. } => {
|
||||
println!("Error in command `{}`: {:?}", ctx.command().name, error,);
|
||||
}
|
||||
error => {
|
||||
if let Err(e) = poise::builtins::on_error(error).await {
|
||||
println!("Error while handling error: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
// SQLite
|
||||
let conn = init_db("bot_data.sqlite").expect("Failed to start database");
|
||||
init_tables(&conn).expect("Failed to init tables");
|
||||
let conn = Arc::new(Mutex::new(conn));
|
||||
|
||||
// Discord bot
|
||||
let token = std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN");
|
||||
let intents = serenity::GatewayIntents::non_privileged();
|
||||
|
||||
|
|
@ -36,12 +84,13 @@ async fn main() {
|
|||
event_handler: |ctx, event, framework, data| {
|
||||
Box::pin(event_handler(ctx, event, framework, data))
|
||||
},
|
||||
on_error: |error| Box::pin(on_error(error)),
|
||||
..Default::default()
|
||||
})
|
||||
.setup(|ctx, _ready, framework| {
|
||||
Box::pin(async move {
|
||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
||||
Ok(Data {})
|
||||
Ok(Data { conn })
|
||||
})
|
||||
})
|
||||
.build();
|
||||
|
|
|
|||
Loading…
Reference in a new issue