From f11fdb4dde603b0d39aacf2f6015ce0bc96557da Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 25 Sep 2023 18:50:33 +0100 Subject: [PATCH] feat: conversion script --- Cargo.toml | 3 + src/bin/update_id.rs | 144 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 38 ++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 src/bin/update_id.rs diff --git a/Cargo.toml b/Cargo.toml index 0732349..54043e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,9 @@ name = "update_data" [[bin]] name = "update_users" +[[bin]] +name = "update_id" + [dependencies] serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] } diff --git a/src/bin/update_id.rs b/src/bin/update_id.rs new file mode 100644 index 0000000..4923801 --- /dev/null +++ b/src/bin/update_id.rs @@ -0,0 +1,144 @@ +use serenity::{ + async_trait, + client::{Context, EventHandler}, + model::{ + gateway::{GatewayIntents, Ready}, + }, + Client, +}; +use skynet_discord_bot::{db_init, get_config, Config, DataBase, ServerMembersWolves, Wolves2}; +use sqlx::{Pool, Sqlite}; +use std::{process, sync::Arc}; +use tokio::sync::RwLock; + +#[tokio::main] +async fn main() { + let config = get_config(); + let db = match db_init(&config).await { + Ok(x) => x, + Err(_) => return, + }; + + // Intents are a bitflag, bitwise operations can be used to dictate which intents to use + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; + // Build our client. + let mut client = Client::builder(&config.discord_token, intents) + .event_handler(Handler {}) + .await + .expect("Error creating client"); + + { + let mut data = client.data.write().await; + + data.insert::(Arc::new(RwLock::new(config))); + data.insert::(Arc::new(RwLock::new(db))); + } + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +struct Handler; +#[async_trait] +impl EventHandler for Handler { + async fn ready(&self, ctx: Context, ready: Ready) { + let ctx = Arc::new(ctx); + println!("{} is connected!", ready.user.name); + + bulk_check(Arc::clone(&ctx)).await; + + // finish up + process::exit(0); + } +} + +async fn bulk_check(ctx: Arc) { + let db_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + + let db = db_lock.read().await; + + // get sk + let mut wolves2 = vec![]; + + // get wolves users + for user in get_server_member_bulk(&db).await{ + let discord = match user.discord{ + None => { + wolves2.push(Wolves2{ + id_wolves: user.id_wolves, + email: user.email, + discord: None, + minecraft: user.minecraft, + }); + + continue; + } + Some(x) => {x} + }; + + if let Ok(x) = user.server.search_members(&ctx.http, &discord, None).await { + for user_tmp in x { + if &user_tmp.user.name == &discord { + wolves2.push(Wolves2{ + id_wolves: user.id_wolves.to_owned(), + email: user.email.to_owned(), + discord: Some(user_tmp.user.id), + minecraft: user.minecraft.to_owned(), + }); + + break; + } + } + } + } + + for user in wolves2 { + + set_member_info(&db, &user).await; + } +} + +async fn get_server_member_bulk(db: &Pool) -> Vec { + sqlx::query_as::<_, ServerMembersWolves>( + r#" + SELECT * + FROM server_members + JOIN wolves USING (id_wolves) + "#, + ) + .fetch_all(db) + .await + .unwrap_or_default() +} + +async fn set_member_info(db: &Pool, user: &Wolves2){ + + let discord = user.discord.map(|x| *x.as_u64() as i64); + + + // save + match sqlx::query_as::<_, Wolves2>( + " + INSERT INTO wolves2 (id_wolves, email, discord) + VALUES ($1, $2, $3) + ON CONFLICT(id_wolves) DO UPDATE SET email = $2, discord = $3 + ", + ) + .bind(&user.id_wolves) + .bind(&user.email) + .bind(discord) + .fetch_optional(db) + .await + { + Ok(_) => {} + Err(e) => { + println!("Failure to insert into {:?}", &user); + println!("{:?}", e); + } + } + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index cd5ee35..f148b4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ use sqlx::{ Error, FromRow, Pool, Row, Sqlite, }; use std::{env, str::FromStr, sync::Arc}; +use serenity::model::id::UserId; use tokio::sync::RwLock; pub struct Config { @@ -152,6 +153,32 @@ pub struct Wolves { pub minecraft: Option, } +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct Wolves2 { + pub id_wolves: String, + pub email: String, + pub discord: Option, + pub minecraft: Option, +} +impl<'r> FromRow<'r, SqliteRow> for Wolves2 { + fn from_row(row: &'r SqliteRow) -> Result { + let discord = match row.try_get("discord") { + Ok(x) => { + let tmp: i64 = x; + Some(UserId::from(tmp as u64)) + } + _ => None, + }; + + Ok(Self { + id_wolves: row.try_get("id_wolves")?, + email: row.try_get("email")?, + discord, + minecraft: row.try_get("minecraft")?, + }) + } +} + #[derive(Debug, Clone, Deserialize, Serialize, sqlx::FromRow)] pub struct WolvesVerify { pub email: String, @@ -222,6 +249,17 @@ pub async fn db_init(config: &Config) -> Result, Error> { .execute(&pool) .await?; + sqlx::query( + "CREATE TABLE IF NOT EXISTS wolves2 ( + id_wolves text PRIMARY KEY, + email text not null, + discord integer, + minecraft text + )", + ) + .execute(&pool) + .await?; + sqlx::query("CREATE INDEX IF NOT EXISTS index_discord ON wolves (discord)").execute(&pool).await?; sqlx::query(