feat: starting db abstractions
parent
303e3ffd4e
commit
0b10885015
|
@ -1,7 +1,11 @@
|
||||||
-- Your SQL goes here
|
-- Your SQL goes here
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
discord_id UNSIGNED BIG INT PRIMARY KEY NOT NULL,
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
discord_id UNSIGNED BIG INT NOT NULL,
|
||||||
|
guild_id UNSIGNED BIG INT NOT NULL,
|
||||||
email TEXT UNIQUE NOT NULL,
|
email TEXT UNIQUE NOT NULL,
|
||||||
first_name TEXT NOT NULL,
|
first_name TEXT NOT NULL,
|
||||||
last_name TEXT NOT NULL
|
last_name TEXT NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE(discord_id, guild_id)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::db::users::{user_all, user_insert, User};
|
use crate::db::users::{User, NewUser};
|
||||||
use crate::{Context, Error};
|
use crate::{Context, Error};
|
||||||
|
use diesel::RunQueryDsl;
|
||||||
|
|
||||||
#[poise::command(prefix_command, slash_command)]
|
#[poise::command(prefix_command, slash_command)]
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
|
@ -8,8 +9,10 @@ pub async fn register(
|
||||||
last_name: String,
|
last_name: String,
|
||||||
email: String,
|
email: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let user = User {
|
if let Some(guild_id) = ctx.guild_id() {
|
||||||
|
let new_user = NewUser {
|
||||||
discord_id: ctx.author().id.0 as i64,
|
discord_id: ctx.author().id.0 as i64,
|
||||||
|
guild_id: guild_id.into(),
|
||||||
first_name,
|
first_name,
|
||||||
last_name,
|
last_name,
|
||||||
email,
|
email,
|
||||||
|
@ -17,7 +20,10 @@ pub async fn register(
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut conn = ctx.data().pool.get()?;
|
let mut conn = ctx.data().pool.get()?;
|
||||||
user_insert(&mut conn, &user);
|
new_user.insert(&mut conn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx.say("You have to send this message from a guild.").await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -25,9 +31,10 @@ pub async fn register(
|
||||||
|
|
||||||
#[poise::command(prefix_command, slash_command)]
|
#[poise::command(prefix_command, slash_command)]
|
||||||
pub async fn registered(ctx: Context<'_>) -> Result<(), Error> {
|
pub async fn registered(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
if let Some(guild_id) = ctx.guild_id() {
|
||||||
let users = {
|
let users = {
|
||||||
let mut conn = ctx.data().pool.get()?;
|
let mut conn = ctx.data().pool.get()?;
|
||||||
user_all(&mut conn)
|
User::by_guild_id(guild_id.into()).load(&mut conn)?
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.send(|f| {
|
ctx.send(|f| {
|
||||||
|
@ -40,6 +47,9 @@ pub async fn registered(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
} else {
|
||||||
|
ctx.say("You are not in a guild.").await?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,23 @@
|
||||||
mod schema;
|
mod schema;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
|
|
||||||
|
use diesel::sqlite::SqliteConnection;
|
||||||
|
use diesel::connection::SimpleConnection;
|
||||||
|
use diesel::QueryResult;
|
||||||
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
|
|
||||||
|
fn initialize_db(conn: &mut SqliteConnection) -> QueryResult<()> {
|
||||||
|
// Enable WAL mode and enforce foreign keys
|
||||||
|
conn.batch_execute("PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA foreign_keys = ON;")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initialize_pool(url: &str) -> Pool<ConnectionManager<SqliteConnection>> {
|
||||||
|
let manager = ConnectionManager::new(url);
|
||||||
|
|
||||||
|
let pool = Pool::builder().test_on_check_out(true).build(manager).expect("oops");
|
||||||
|
|
||||||
|
let mut conn = pool.get().unwrap();
|
||||||
|
initialize_db(&mut conn).unwrap();
|
||||||
|
|
||||||
|
pool
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
// @generated automatically by Diesel CLI.
|
// @generated automatically by Diesel CLI.
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
users (discord_id) {
|
users (id) {
|
||||||
|
id -> Integer,
|
||||||
discord_id -> BigInt,
|
discord_id -> BigInt,
|
||||||
|
guild_id -> BigInt,
|
||||||
email -> Text,
|
email -> Text,
|
||||||
first_name -> Text,
|
first_name -> Text,
|
||||||
last_name -> Text,
|
last_name -> Text,
|
||||||
|
|
|
@ -1,22 +1,68 @@
|
||||||
use super::schema::users;
|
use super::schema::users::{self, dsl::*};
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use diesel::sqlite::SqliteConnection;
|
use diesel::sqlite::SqliteConnection;
|
||||||
|
use diesel::dsl::{AsSelect, Select};
|
||||||
|
use diesel::sqlite::Sqlite;
|
||||||
|
use diesel::dsl::Eq;
|
||||||
|
use diesel::helper_types::Filter;
|
||||||
|
use diesel::sql_types::BigInt;
|
||||||
|
use diesel::expression::AsExpression;
|
||||||
|
|
||||||
#[derive(Queryable, Insertable)]
|
#[derive(Queryable, Selectable)]
|
||||||
|
#[diesel(table_name = users)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
|
pub id: i32,
|
||||||
pub discord_id: i64,
|
pub discord_id: i64,
|
||||||
|
pub guild_id: i64,
|
||||||
pub email: String,
|
pub email: String,
|
||||||
pub first_name: String,
|
pub first_name: String,
|
||||||
pub last_name: String,
|
pub last_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_insert(conn: &mut SqliteConnection, user: &User) -> User {
|
#[derive(Insertable)]
|
||||||
diesel::insert_into(users::table)
|
#[diesel(table_name = users)]
|
||||||
.values(user)
|
pub struct NewUser {
|
||||||
.get_result(conn)
|
pub discord_id: i64,
|
||||||
.expect("fuck")
|
pub guild_id: i64,
|
||||||
|
pub email: String,
|
||||||
|
pub first_name: String,
|
||||||
|
pub last_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_all(conn: &mut SqliteConnection) -> Vec<User> {
|
type All = Select<users::table, AsSelect<User, Sqlite>>;
|
||||||
users::table.load::<User>(conn).expect("nou")
|
type WithGuild<T> = Eq<guild_id, T>;
|
||||||
|
type ByGuild<T> = Filter<All, WithGuild<T>>;
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
pub fn all() -> All {
|
||||||
|
users::table.select(User::as_select())
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn by_guild<T>(guild_id_: T) -> ByGuild<T>
|
||||||
|
// where T: AsExpression<BigInt>
|
||||||
|
// {
|
||||||
|
// Self::all().filter(guild_id.eq(guild_id_))
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn by_guild_id(guild_id_: i64) -> ByGuild<i64>
|
||||||
|
{
|
||||||
|
Self::all().filter(guild_id.eq(guild_id_))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(conn: &mut SqliteConnection, guild_id_: i64, discord_id_: i64) -> Result<User, diesel::result::Error> {
|
||||||
|
Self::all().filter(guild_id.eq(guild_id_)).filter(discord_id.eq(discord_id_)).first(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_by_id(conn: &mut SqliteConnection, id_: i32) -> Result<User, diesel::result::Error> {
|
||||||
|
Self::all().filter(id.eq(id_)).first(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NewUser {
|
||||||
|
pub fn insert(&self, conn: &mut SqliteConnection) -> User {
|
||||||
|
diesel::insert_into(users::table)
|
||||||
|
.values(self)
|
||||||
|
.get_result(conn)
|
||||||
|
.expect("fuck")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -2,9 +2,7 @@ mod commands;
|
||||||
mod db;
|
mod db;
|
||||||
|
|
||||||
use affluences_api::AffluencesClient;
|
use affluences_api::AffluencesClient;
|
||||||
use diesel::Connection;
|
|
||||||
use poise::serenity_prelude as serenity;
|
use poise::serenity_prelude as serenity;
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::{env::var, time::Duration};
|
use std::{env::var, time::Duration};
|
||||||
use diesel::r2d2::{ConnectionManager, Pool};
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
use diesel::sqlite::SqliteConnection;
|
use diesel::sqlite::SqliteConnection;
|
||||||
|
@ -36,12 +34,6 @@ async fn on_error(error: poise::FrameworkError<'_, Data, Error>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn db_connection_pool(url: &str) -> Pool<ConnectionManager<SqliteConnection>> {
|
|
||||||
let manager = ConnectionManager::new(url);
|
|
||||||
|
|
||||||
Pool::builder().test_on_check_out(true).build(manager).expect("oops")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// FrameworkOptions contains all of poise's configuration option in one struct
|
// FrameworkOptions contains all of poise's configuration option in one struct
|
||||||
|
@ -103,7 +95,7 @@ async fn main() {
|
||||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
||||||
Ok(Data {
|
Ok(Data {
|
||||||
client: AffluencesClient::new(),
|
client: AffluencesClient::new(),
|
||||||
pool: db_connection_pool("affy.db")
|
pool: db::initialize_pool("affy.db")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue