about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2025-04-20 06:52:12 -0500
committergennyble <gen@nyble.dev>2025-04-20 06:52:12 -0500
commit2d667d4c3d63a44c4cc01f7fb7133e5714d60584 (patch)
tree61c7dbc795998644f1546b4104e1eff86629cda8 /src
parent85a319730a9d3290a0b75c8460279a2649b10443 (diff)
downloadleaberblord-2d667d4c3d63a44c4cc01f7fb7133e5714d60584.tar.gz
leaberblord-2d667d4c3d63a44c4cc01f7fb7133e5714d60584.zip
add quick-n-easy import cli command
Diffstat (limited to 'src')
-rw-r--r--src/import.rs54
-rw-r--r--src/main.rs29
2 files changed, 80 insertions, 3 deletions
diff --git a/src/import.rs b/src/import.rs
new file mode 100644
index 0000000..f7d9873
--- /dev/null
+++ b/src/import.rs
@@ -0,0 +1,54 @@
+use serde::Deserialize;
+
+use crate::database::{BoardRow, Database, Error};
+
+#[derive(Debug, Deserialize)]
+pub struct Emboard {
+	guildName: String,
+	leaderboard: Vec<EmboardRow>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct EmboardRow {
+	guildId: String,
+	discordId: String,
+	points: String,
+	username: String,
+}
+
+pub fn import(db: &Database, json: String) {
+	let embaord: Emboard = match serde_json::from_str(&json) {
+		Ok(e) => e,
+		Err(e) => {
+			panic!("{e}");
+		}
+	};
+
+	let Some(first) = embaord.leaderboard.first() else {
+		return;
+	};
+
+	let guild_id = u64::from_str_radix(&first.guildId, 10).unwrap();
+	if db.get_leaderboard(guild_id).is_err() {
+		db.create_leaderboard(guild_id).unwrap();
+	}
+
+	for user in embaord.leaderboard {
+		let user_id = u64::from_str_radix(&user.discordId, 10).unwrap();
+		let points = i64::from_str_radix(&user.points, 10).unwrap();
+
+		let res = db.give_user_points(guild_id, user_id, points);
+		if let Err(Error::UserNotExist) = res {
+			db.add_user_to_leaderboard(
+				guild_id,
+				BoardRow {
+					user_id,
+					user_handle: user.username,
+					user_nickname: None,
+					points,
+				},
+			)
+			.unwrap();
+		}
+	}
+}
diff --git a/src/main.rs b/src/main.rs
index 680c944..af238dc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,4 @@
-use std::{env, error::Error, sync::Arc};
+use std::{env, error::Error, path::PathBuf, sync::Arc};
 
 use confindent::Confindent;
 use database::{BoardRow, Database, Error as DbError, PermissionSetting};
@@ -31,6 +31,7 @@ use twilight_util::builder::{
 };
 
 mod database;
+mod import;
 
 const APP_ID: u64 = 1363055126264283136;
 
@@ -62,7 +63,13 @@ macro_rules! success {
 async fn main() -> anyhow::Result<()> {
 	dotenv::dotenv().ok();
 
-	let conf = Confindent::from_file("/etc/leaberblord.conf").unwrap();
+	let conf_path = if !PathBuf::from("/etc/leaberblord.conf").exists() {
+		"leaberblord.conf"
+	} else {
+		"/etc/leaberblord.conf"
+	};
+
+	let conf = Confindent::from_file(conf_path).unwrap();
 	let db_dir = conf
 		.child_owned("Database")
 		.unwrap_or("/var/leaberblord/leaberblord.sqlite".to_string());
@@ -73,6 +80,22 @@ async fn main() -> anyhow::Result<()> {
 	let db = Arc::new(Database::new(db_dir));
 	db.create_tables();
 
+	let arg = std::env::args().nth(1);
+	match arg.as_deref() {
+		Some("import") => {
+			let Some(file) = std::env::args().nth(2) else {
+				eprintln!("import subcommand requires a file path argument to read data from.");
+				return Ok(());
+			};
+
+			let data = std::fs::read_to_string(file).unwrap();
+			import::import(&db, data);
+			println!("Import finished!");
+			return Ok(());
+		}
+		_ => (),
+	}
+
 	let mut shard = Shard::new(ShardId::ONE, token.clone(), Intents::GUILD_MESSAGES);
 	let http = Arc::new(HttpClient::new(token));
 	let mut cache = DefaultInMemoryCache::builder()
@@ -300,7 +323,7 @@ async fn add_points(
 		Some(p) if p > 0 => (p, p, "added to"),
 		Some(p) if p < 0 => (p, -p, "removed from"),
 		Some(0) => {
-			return success!("adding 0 points is a no-operation, so I won't doing anything");
+			return success!("adding 0 points is a no-operation! I won't do anything :)");
 		}
 		Some(_) | None => unreachable!(),
 	};