From 3cd3bc54af1889815a3193826d43529ce593f589 Mon Sep 17 00:00:00 2001
From: Paul <paulmakles@gmail.com>
Date: Wed, 26 May 2021 13:02:40 +0100
Subject: [PATCH] New Feature: Settings sync to server.

---
 set_version.sh                  |  2 +-
 src/notifications/events.rs     |  6 ++++
 src/routes/mod.rs               |  2 ++
 src/routes/sync/get_settings.rs | 40 +++++++++++++++++++++++++
 src/routes/sync/mod.rs          | 11 +++++++
 src/routes/sync/set_settings.rs | 52 +++++++++++++++++++++++++++++++++
 src/version.rs                  |  2 +-
 7 files changed, 113 insertions(+), 2 deletions(-)
 create mode 100644 src/routes/sync/get_settings.rs
 create mode 100644 src/routes/sync/mod.rs
 create mode 100644 src/routes/sync/set_settings.rs

diff --git a/set_version.sh b/set_version.sh
index 866f747..0fe4c09 100755
--- a/set_version.sh
+++ b/set_version.sh
@@ -1,3 +1,3 @@
 #!/bin/bash
-export version=0.4.2-alpha.0
+export version=0.4.2-alpha.1
 echo "pub const VERSION: &str = \"${version}\";" > src/version.rs
diff --git a/src/notifications/events.rs b/src/notifications/events.rs
index a798a81..fa8c438 100644
--- a/src/notifications/events.rs
+++ b/src/notifications/events.rs
@@ -1,3 +1,5 @@
+use std::collections::HashMap;
+
 use hive_pubsub::PubSub;
 use rauth::auth::Session;
 use rocket_contrib::json::JsonValue;
@@ -100,6 +102,10 @@ pub enum ClientboundNotification {
         id: String,
         online: bool,
     },
+    UserSettingsUpdate {
+        id: String,
+        update: HashMap<String, String>
+    }
 }
 
 impl ClientboundNotification {
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 6d8229b..4a038d9 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -8,6 +8,7 @@ mod onboard;
 mod push;
 mod root;
 mod users;
+mod sync;
 
 pub fn mount(rocket: Rocket) -> Rocket {
     rocket
@@ -17,4 +18,5 @@ pub fn mount(rocket: Rocket) -> Rocket {
         .mount("/channels", channels::routes())
         .mount("/guild", guild::routes())
         .mount("/push", push::routes())
+        .mount("/sync", sync::routes())
 }
diff --git a/src/routes/sync/get_settings.rs b/src/routes/sync/get_settings.rs
new file mode 100644
index 0000000..b912637
--- /dev/null
+++ b/src/routes/sync/get_settings.rs
@@ -0,0 +1,40 @@
+use crate::database::*;
+use crate::util::result::{Error, Result};
+
+use mongodb::bson::doc;
+use serde::{Deserialize, Serialize};
+use mongodb::options::FindOneOptions;
+use rocket_contrib::json::{Json, JsonValue};
+
+#[derive(Serialize, Deserialize)]
+pub struct Options {
+    keys: Vec<String>
+}
+
+#[post("/settings/fetch", data = "<options>")]
+pub async fn req(user: User, options: Json<Options>) -> Result<JsonValue> {
+    let options = options.into_inner();
+    let mut projection = doc! {
+        "_id": 0,
+    };
+
+    for key in options.keys {
+        projection.insert(key, 1);
+    }
+
+    if let Some(doc) = get_collection("user_settings")
+        .find_one(
+            doc! {
+                "_id": user.id
+            },
+            FindOneOptions::builder()
+                .projection(projection)
+                .build()
+        )
+        .await
+        .map_err(|_| Error::DatabaseError { operation: "find_one", with: "user_settings" })? {
+        Ok(json!(doc))
+    } else {
+        Ok(json!({ }))
+    }
+}
diff --git a/src/routes/sync/mod.rs b/src/routes/sync/mod.rs
new file mode 100644
index 0000000..0b1ecf6
--- /dev/null
+++ b/src/routes/sync/mod.rs
@@ -0,0 +1,11 @@
+use rocket::Route;
+
+mod get_settings;
+mod set_settings;
+
+pub fn routes() -> Vec<Route> {
+    routes![
+        get_settings::req,
+        set_settings::req
+    ]
+}
diff --git a/src/routes/sync/set_settings.rs b/src/routes/sync/set_settings.rs
new file mode 100644
index 0000000..65c6f52
--- /dev/null
+++ b/src/routes/sync/set_settings.rs
@@ -0,0 +1,52 @@
+use crate::database::*;
+use crate::notifications::events::ClientboundNotification;
+use crate::util::result::{Error, Result};
+
+use chrono::prelude::*;
+use std::collections::HashMap;
+use rocket_contrib::json::Json;
+use mongodb::bson::{doc, to_bson};
+use mongodb::options::UpdateOptions;
+
+type Data = HashMap<String, String>;
+
+#[post("/settings/set", data = "<data>")]
+pub async fn req(user: User, data: Json<Data>) -> Result<()> {
+    let data = data.into_inner();
+
+    let mut set = doc! {};
+    for (key, data) in &data {
+        set.insert(
+            key.clone(),
+            vec! [
+                to_bson(&Utc::now().timestamp_millis()).unwrap(),
+                to_bson(&data.clone()).unwrap()
+            ]
+        );
+    }
+
+    if set.len() > 0 {
+        get_collection("user_settings")
+            .update_one(
+                doc! {
+                    "_id": &user.id
+                },
+                doc! {
+                    "$set": set
+                },
+                UpdateOptions::builder()
+                    .upsert(true)
+                    .build()
+            )
+            .await
+            .map_err(|_| Error::DatabaseError { operation: "update_one", with: "user_settings" })?;
+    }
+
+    ClientboundNotification::UserSettingsUpdate {
+        id: user.id.clone(),
+        update: data
+    }
+    .publish(user.id);
+    
+    Ok(())
+}
diff --git a/src/version.rs b/src/version.rs
index cc9aa59..45f4f47 100644
--- a/src/version.rs
+++ b/src/version.rs
@@ -1 +1 @@
-pub const VERSION: &str = "0.4.2-alpha.0";
+pub const VERSION: &str = "0.4.2-alpha.1";
-- 
GitLab