kv, quotes, some other stuff
This commit is contained in:
parent
008ff5b7cf
commit
7276f5922f
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -1263,6 +1263,16 @@ version = "0.2.164"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@ -2284,6 +2294,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"chrono-tz",
|
"chrono-tz",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"libloading",
|
||||||
"poise",
|
"poise",
|
||||||
"reqwest 0.12.9",
|
"reqwest 0.12.9",
|
||||||
"serde",
|
"serde",
|
||||||
@ -2422,6 +2433,7 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlformat",
|
"sqlformat",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -2506,6 +2518,7 @@ dependencies = [
|
|||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
@ -2544,6 +2557,7 @@ dependencies = [
|
|||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
@ -2567,6 +2581,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
poise = "0.6.1"
|
poise = "0.6.1"
|
||||||
serenity = "0.12.4"
|
serenity = "0.12.4"
|
||||||
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-ring", "mysql" ] }
|
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-ring", "mysql", "time" ] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
@ -17,3 +17,4 @@ chrono = "0.4.38"
|
|||||||
chrono-tz = "0.10.0"
|
chrono-tz = "0.10.0"
|
||||||
reqwest = "0.12.9"
|
reqwest = "0.12.9"
|
||||||
serde_json = "1.0.133"
|
serde_json = "1.0.133"
|
||||||
|
libloading = "0.8.5"
|
||||||
|
5
migrations/20241125173833_add_kv_table.sql
Normal file
5
migrations/20241125173833_add_kv_table.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
CREATE TABLE kv_store (
|
||||||
|
`key` VARCHAR(255) NOT NULL PRIMARY KEY,
|
||||||
|
`value` TEXT
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
11
migrations/20241125180340_add_quotes_table.sql
Normal file
11
migrations/20241125180340_add_quotes_table.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
CREATE TABLE quotes (
|
||||||
|
quote_id INT AUTO_INCREMENT PRIMARY KEY, -- Unique ID for each quote
|
||||||
|
user_id BIGINT NOT NULL, -- Discord user ID (64-bit)
|
||||||
|
username VARCHAR(255) NOT NULL, -- Username of the person who said the quote
|
||||||
|
quote TEXT NOT NULL, -- The quote itself
|
||||||
|
added_by BIGINT NOT NULL, -- Discord user ID of the person who added the quote
|
||||||
|
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the quote was added
|
||||||
|
INDEX (user_id), -- Index for efficient lookup by user_id
|
||||||
|
INDEX (added_by) -- Index for efficient lookup by added_by
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{utils, Context, Error};
|
use crate::{utils, Context, Error};
|
||||||
use poise::CreateReply;
|
use poise::CreateReply;
|
||||||
use serenity::all::{CreateAllowedMentions, CreateAttachment, Message};
|
use serenity::all::{CreateAllowedMentions, CreateAttachment, Message};
|
||||||
use serenity::builder::CreateMessage;
|
|
||||||
use serenity::model::prelude::UserId;
|
use serenity::model::prelude::UserId;
|
||||||
use serenity::prelude::Mentionable;
|
use serenity::prelude::Mentionable;
|
||||||
|
|
||||||
|
112
src/commands/eval.rs
Normal file
112
src/commands/eval.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use std::{
|
||||||
|
env, fs,
|
||||||
|
process::{Command, Output, Stdio},
|
||||||
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{Context, Error};
|
||||||
|
|
||||||
|
/// Evaluate rust code
|
||||||
|
#[poise::command(prefix_command)]
|
||||||
|
pub async fn eval(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "The code to run"] code: poise::CodeBlock,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let authed_users = ctx.data().owners.clone();
|
||||||
|
|
||||||
|
// Check if the user is an owner
|
||||||
|
if !authed_users.contains(&ctx.author().id.into()) {
|
||||||
|
ctx.say(":x: You are not authorized to run this command")
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.say(":gear: Processing...").await?;
|
||||||
|
|
||||||
|
// Create a temporary directory for the file
|
||||||
|
let temp_dir = env::temp_dir();
|
||||||
|
let unique_id = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.expect("Time went backwards")
|
||||||
|
.as_secs();
|
||||||
|
let file_path = temp_dir.join(format!("eval_{}.rs", unique_id));
|
||||||
|
let executable_path = temp_dir.join(format!("eval_{}.out", unique_id));
|
||||||
|
|
||||||
|
// Write the code to a temporary file
|
||||||
|
if let Err(err) = fs::write(&file_path, code.code) {
|
||||||
|
ctx.say(format!("Error writing to temporary file: {}", err))
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile the Rust file and capture stderr
|
||||||
|
let compile_output: Result<Output, _> = Command::new("rustc")
|
||||||
|
.arg(&file_path)
|
||||||
|
.arg("-o")
|
||||||
|
.arg(&executable_path)
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.output();
|
||||||
|
|
||||||
|
match compile_output {
|
||||||
|
Ok(output) if output.status.success() => {
|
||||||
|
ctx.say(
|
||||||
|
"<:success:1310650176037453834> Compilation successful. Running the executable...",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Run the compiled executable
|
||||||
|
let output = Command::new(&executable_path).output();
|
||||||
|
|
||||||
|
match output {
|
||||||
|
Ok(output) => {
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
ctx.say(format!(
|
||||||
|
"**Output:**\n```\n{}\n```\n**Errors:**\n```\n{}\n```",
|
||||||
|
if stdout.trim().is_empty() {
|
||||||
|
"<no output>"
|
||||||
|
} else {
|
||||||
|
stdout.trim()
|
||||||
|
},
|
||||||
|
if stderr.trim().is_empty() {
|
||||||
|
"<no errors>"
|
||||||
|
} else {
|
||||||
|
stderr.trim()
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
ctx.say(format!(
|
||||||
|
"<:error:1310650177056538655> Error running the executable: {}",
|
||||||
|
err
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(output) => {
|
||||||
|
// If compilation failed, display the compiler error output
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
ctx.say(format!(
|
||||||
|
"<:error:1310650177056538655> Compilation failed:\n```\n{}\n```",
|
||||||
|
stderr
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
ctx.say(format!(
|
||||||
|
"<:error:1310650177056538655> Error invoking rustc: {}",
|
||||||
|
err
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
let _ = fs::remove_file(&file_path);
|
||||||
|
let _ = fs::remove_file(&executable_path);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -3,4 +3,6 @@ pub mod vouch;
|
|||||||
pub mod cta;
|
pub mod cta;
|
||||||
pub mod dog;
|
pub mod dog;
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
pub mod action;
|
pub mod action;
|
||||||
|
pub mod eval;
|
||||||
|
pub mod quote;
|
91
src/commands/quote.rs
Normal file
91
src/commands/quote.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use crate::{Context, Error};
|
||||||
|
use poise::CreateReply;
|
||||||
|
use serenity::all::{CreateAllowedMentions, Message, User};
|
||||||
|
use sqlx::types::time::OffsetDateTime;
|
||||||
|
|
||||||
|
#[poise::command(context_menu_command = "Quote User")]
|
||||||
|
pub async fn quote_action(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "The target message to quote"] message: Message,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let quote = crate::structs::quote::Quote {
|
||||||
|
quote_id: 0,
|
||||||
|
user_id: message.author.id.into(),
|
||||||
|
username: message.author.name.clone(),
|
||||||
|
quote: message.content.clone(),
|
||||||
|
added_by: ctx.author().id.into(),
|
||||||
|
added_at: OffsetDateTime::now_utc(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if quote.user_id == quote.added_by {
|
||||||
|
ctx.say(":x: You can't quote yourself").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.data().database_controller.quote_create(quote).await?;
|
||||||
|
ctx.say(":white_check_mark: Okay, I've immortalized that message for you :)")
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a random quote
|
||||||
|
#[poise::command(slash_command)]
|
||||||
|
pub async fn random_quote(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
let quote = ctx.data().database_controller.quote_get_random().await?;
|
||||||
|
|
||||||
|
if let Some(quote) = quote {
|
||||||
|
ctx.send(
|
||||||
|
CreateReply::default()
|
||||||
|
.content(format!(
|
||||||
|
"{}: {}\nQuoted at: <t:{}:f> by <@{}>",
|
||||||
|
quote.username,
|
||||||
|
quote.quote,
|
||||||
|
quote.added_at.unix_timestamp(),
|
||||||
|
quote.added_by
|
||||||
|
))
|
||||||
|
.allowed_mentions(CreateAllowedMentions::new().empty_users()),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
ctx.say("No quotes found").await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get quotes for a user, showing latest 10
|
||||||
|
#[poise::command(slash_command)]
|
||||||
|
pub async fn user_quotes(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "The user to get quotes for"] user: User,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let quotes = ctx
|
||||||
|
.data()
|
||||||
|
.database_controller
|
||||||
|
.quote_get_by_user_id(user.id.into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if quotes.is_empty() {
|
||||||
|
ctx.say("No quotes found").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut response = String::new();
|
||||||
|
for quote in quotes {
|
||||||
|
response.push_str(&format!(
|
||||||
|
"{}: {}\nQuoted at: <t:{}:f> by <@{}>\n",
|
||||||
|
quote.username,
|
||||||
|
quote.quote,
|
||||||
|
quote.added_at.unix_timestamp(),
|
||||||
|
quote.added_by
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.send(
|
||||||
|
CreateReply::default()
|
||||||
|
.content(response)
|
||||||
|
.allowed_mentions(CreateAllowedMentions::new().empty_users()),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::structs::quote::Quote;
|
||||||
use crate::structs::user::User;
|
use crate::structs::user::User;
|
||||||
use sqlx::MySqlPool;
|
use sqlx::MySqlPool;
|
||||||
|
|
||||||
@ -99,4 +100,80 @@ impl DatabaseController {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn kv_set(&self, key: &str, value: &str) -> Result<(), sqlx::Error> {
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO kv_store (`key`, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?",
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
.execute(&self.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn kv_get(&self, key: &str) -> Result<Option<String>, sqlx::Error> {
|
||||||
|
let kv = sqlx::query!("SELECT * FROM kv_store WHERE `key` = ?", key)
|
||||||
|
.fetch_optional(&self.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match kv {
|
||||||
|
Some(kv) => Ok(kv.value),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn quote_create(&self, quote: Quote) -> Result<(), sqlx::Error> {
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO quotes (user_id, username, quote, added_by) VALUES (?, ?, ?, ?)",
|
||||||
|
quote.user_id,
|
||||||
|
quote.username,
|
||||||
|
quote.quote,
|
||||||
|
quote.added_by
|
||||||
|
)
|
||||||
|
.execute(&self.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn quote_get_random(&self) -> Result<Option<Quote>, sqlx::Error> {
|
||||||
|
let quote = sqlx::query!("SELECT * FROM quotes ORDER BY RAND() LIMIT 1")
|
||||||
|
.fetch_optional(&self.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match quote {
|
||||||
|
Some(quote) => Ok(Some(Quote {
|
||||||
|
quote_id: quote.quote_id,
|
||||||
|
user_id: quote.user_id,
|
||||||
|
username: quote.username,
|
||||||
|
quote: quote.quote,
|
||||||
|
added_by: quote.added_by,
|
||||||
|
added_at: quote.added_at.unwrap(),
|
||||||
|
})),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn quote_get_by_user_id(&self, user_id: u64) -> Result<Vec<Quote>, sqlx::Error> {
|
||||||
|
let quote = sqlx::query!("SELECT * FROM quotes WHERE user_id = ?", user_id)
|
||||||
|
.fetch_all(&self.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut quotes = Vec::new();
|
||||||
|
for q in quote {
|
||||||
|
quotes.push(Quote {
|
||||||
|
quote_id: q.quote_id,
|
||||||
|
user_id: q.user_id,
|
||||||
|
username: q.username,
|
||||||
|
quote: q.quote,
|
||||||
|
added_by: q.added_by,
|
||||||
|
added_at: q.added_at.unwrap(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(quotes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
|
pub mod db;
|
||||||
pub mod join;
|
pub mod join;
|
||||||
pub mod db;
|
|
23
src/main.rs
23
src/main.rs
@ -4,6 +4,8 @@ mod handlers;
|
|||||||
mod structs;
|
mod structs;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use events::event_handler;
|
use events::event_handler;
|
||||||
use handlers::db::DatabaseController;
|
use handlers::db::DatabaseController;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -78,6 +80,7 @@ async fn init_sqlx() -> MySqlPool {
|
|||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
database_controller: DatabaseController,
|
database_controller: DatabaseController,
|
||||||
|
owners: Vec<u64>,
|
||||||
uptime: std::time::Instant,
|
uptime: std::time::Instant,
|
||||||
config: Config,
|
config: Config,
|
||||||
vouch_store: Mutex<Vec<Vouch>>,
|
vouch_store: Mutex<Vec<Vouch>>,
|
||||||
@ -99,6 +102,7 @@ struct Channels {
|
|||||||
main: u64,
|
main: u64,
|
||||||
logs_public: u64,
|
logs_public: u64,
|
||||||
logs_mod: u64,
|
logs_mod: u64,
|
||||||
|
starboard: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
@ -136,6 +140,7 @@ async fn main() {
|
|||||||
main: 0,
|
main: 0,
|
||||||
logs_public: 0,
|
logs_public: 0,
|
||||||
logs_mod: 0,
|
logs_mod: 0,
|
||||||
|
starboard: 0,
|
||||||
},
|
},
|
||||||
roles: Roles {
|
roles: Roles {
|
||||||
admin: 0,
|
admin: 0,
|
||||||
@ -160,7 +165,9 @@ async fn main() {
|
|||||||
let pool = init_sqlx().await;
|
let pool = init_sqlx().await;
|
||||||
|
|
||||||
info!("initializing bot");
|
info!("initializing bot");
|
||||||
let intents = GatewayIntents::privileged();
|
let intents = GatewayIntents::privileged()
|
||||||
|
| GatewayIntents::GUILD_MEMBERS
|
||||||
|
| GatewayIntents::GUILD_MESSAGES;
|
||||||
|
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions::<Data, Error> {
|
.options(poise::FrameworkOptions::<Data, Error> {
|
||||||
@ -173,10 +180,22 @@ async fn main() {
|
|||||||
commands::action::use_action_hug(),
|
commands::action::use_action_hug(),
|
||||||
commands::action::use_action_kiss(),
|
commands::action::use_action_kiss(),
|
||||||
commands::action::use_action_pat(),
|
commands::action::use_action_pat(),
|
||||||
|
commands::eval::eval(),
|
||||||
|
commands::quote::quote_action(),
|
||||||
|
commands::quote::random_quote(),
|
||||||
|
commands::quote::user_quotes(),
|
||||||
],
|
],
|
||||||
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))
|
||||||
},
|
},
|
||||||
|
prefix_options: poise::PrefixFrameworkOptions {
|
||||||
|
prefix: Some("~".into()),
|
||||||
|
edit_tracker: Some(Arc::new(poise::EditTracker::for_timespan(
|
||||||
|
std::time::Duration::from_secs(3600),
|
||||||
|
))),
|
||||||
|
case_insensitive_commands: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.setup(|ctx, _ready, framework| {
|
.setup(|ctx, _ready, framework| {
|
||||||
@ -188,6 +207,8 @@ async fn main() {
|
|||||||
uptime: std::time::Instant::now(),
|
uptime: std::time::Instant::now(),
|
||||||
config,
|
config,
|
||||||
vouch_store: Mutex::new(Vec::new()),
|
vouch_store: Mutex::new(Vec::new()),
|
||||||
|
// Sticks, Emi, Katie
|
||||||
|
owners: vec![1017196087276220447, 272871217256726531, 1033331958291369984],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
|
pub mod quote;
|
||||||
|
pub mod user;
|
||||||
pub mod vouch;
|
pub mod vouch;
|
||||||
pub mod user;
|
|
11
src/structs/quote.rs
Normal file
11
src/structs/quote.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use sqlx::types::time::OffsetDateTime;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Quote {
|
||||||
|
pub quote_id: i32,
|
||||||
|
pub user_id: i64,
|
||||||
|
pub username: String,
|
||||||
|
pub quote: String,
|
||||||
|
pub added_by: i64,
|
||||||
|
pub added_at: OffsetDateTime,
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user