diff --git a/backend/Cargo.lock b/backend/Cargo.lock index f9c461f..ac1ff76 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1,26 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "abnf" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47feb9fbcef700639ef28e04ca2a87eab8161a01a075ee227b15c90143805462" -dependencies = [ - "nom", -] - -[[package]] -name = "abnf_to_pest" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372baaa5d3a422d8816b513bcdb2c120078c8614f7ecbcc3baf34a1634bbbe2e" -dependencies = [ - "abnf", - "indexmap", - "itertools", - "pretty", -] - [[package]] name = "addr2line" version = "0.13.0" @@ -106,12 +85,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "annotate-snippets" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba2d96b8c8b5e656ad7ffb0d09f57772f10a1db74c8d23fca0ec695b38a4047" - [[package]] name = "ansi_term" version = "0.11.0" @@ -130,12 +103,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - [[package]] name = "atty" version = "0.2.14" @@ -407,7 +374,7 @@ dependencies = [ "hmac 0.7.1", "percent-encoding 2.1.0", "rand 0.7.3", - "sha2 0.8.2", + "sha2", "time 0.1.44", ] @@ -614,43 +581,6 @@ dependencies = [ "syn 0.15.44", ] -[[package]] -name = "dhall" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e2aa2abb16c2ef064fbc45f5163be5c5ff990e8584e54fb1c8f6e318107289" -dependencies = [ - "abnf_to_pest", - "annotate-snippets", - "hex", - "itertools", - "lazy_static", - "once_cell", - "percent-encoding 2.1.0", - "pest", - "pest_consume", - "pest_generator", - "quote 1.0.7", - "reqwest 0.10.8", - "serde", - "serde_cbor", - "sha2 0.9.1", - "url 2.1.1", - "walkdir", -] - -[[package]] -name = "dhall_proc_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf6cff1e2ddd03851652e0cde982b01dc877c9fc9da9ba25ad4241a151945f09" -dependencies = [ - "itertools", - "proc-macro2 1.0.21", - "quote 1.0.7", - "syn 1.0.40", -] - [[package]] name = "diesel" version = "1.4.5" @@ -756,7 +686,7 @@ dependencies = [ "hyper-old-types", "isolang", "log 0.4.11", - "reqwest 0.9.24", + "reqwest", "serde", "serde_derive", "serde_json", @@ -1181,12 +1111,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "half" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" - [[package]] name = "hashbrown" version = "0.9.0" @@ -1486,12 +1410,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ipnet" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" - [[package]] name = "isolang" version = "1.0.0" @@ -1503,15 +1421,6 @@ dependencies = [ "serde", ] -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "0.4.6" @@ -1572,19 +1481,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lexical-core" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.77" @@ -1666,12 +1562,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matchers" version = "0.0.1" @@ -1717,6 +1607,7 @@ dependencies = [ "diesel", "egg-mode", "elefren", + "futures-io", "jsonfeed", "kankyo", "log 0.4.11", @@ -1730,7 +1621,6 @@ dependencies = [ "rocket_prometheus", "rusty_ulid", "serde", - "serde_dhall", "serde_json", "thiserror", "tracing", @@ -1846,17 +1736,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "nom" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "lexical-core", - "memchr", - "version_check 0.9.2", -] - [[package]] name = "notify" version = "4.0.15" @@ -2069,73 +1948,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "pest_consume" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f219b98d6adeb806008406459357c7692f413e2dd862219e262858d70a4108" -dependencies = [ - "pest", - "pest_consume_macros", - "pest_derive", - "proc-macro-hack", -] - -[[package]] -name = "pest_consume_macros" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4211c86227964037a5e04d55650bfd4392e7072539fa8cbc5f9ff47e77c22b4e" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.21", - "quote 1.0.7", - "syn 1.0.40", -] - -[[package]] -name = "pest_derive" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2 1.0.21", - "quote 1.0.7", - "syn 1.0.40", -] - -[[package]] -name = "pest_meta" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" -dependencies = [ - "maplit", - "pest", - "sha-1 0.8.2", -] - [[package]] name = "phf" version = "0.7.24" @@ -2228,15 +2040,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" -[[package]] -name = "pretty" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60c0d9f6fc88ecdd245d90c1920ff76a430ab34303fc778d33b1d0a4c3bf6d3" -dependencies = [ - "typed-arena", -] - [[package]] name = "proc-macro-hack" version = "0.5.18" @@ -2600,42 +2403,7 @@ dependencies = [ "tokio-timer", "url 1.7.2", "uuid", - "winreg 0.6.2", -] - -[[package]] -name = "reqwest" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" -dependencies = [ - "base64 0.12.3", - "bytes 0.5.6", - "encoding_rs", - "futures-core", - "futures-util", - "http 0.2.1", - "http-body 0.3.1", - "hyper 0.13.7", - "hyper-tls 0.4.3", - "ipnet", - "js-sys", - "lazy_static", - "log 0.4.11", - "mime 0.3.16", - "mime_guess", - "native-tls", - "percent-encoding 2.1.0", - "pin-project-lite", - "serde", - "serde_urlencoded 0.6.1", - "tokio 0.2.22", - "tokio-tls", - "url 2.1.1", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.7.0", + "winreg", ] [[package]] @@ -2896,17 +2664,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_cbor" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45cd6d95391b16cd57e88b68be41d504183b7faae22030c0cc3b3f73dd57b2fd" -dependencies = [ - "byteorder", - "half", - "serde", -] - [[package]] name = "serde_derive" version = "1.0.116" @@ -2918,19 +2675,6 @@ dependencies = [ "syn 1.0.40", ] -[[package]] -name = "serde_dhall" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "313ac1225c35cd2760b4124d39fa4df19b4a5e29edd55a3eb3fc0b01940f8707" -dependencies = [ - "dhall", - "dhall_proc_macros", - "doc-comment", - "serde", - "url 2.1.1", -] - [[package]] name = "serde_json" version = "1.0.57" @@ -3021,19 +2765,6 @@ dependencies = [ "opaque-debug 0.2.3", ] -[[package]] -name = "sha2" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpuid-bool", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - [[package]] name = "sharded-slab" version = "0.0.9" @@ -3130,12 +2861,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdweb" version = "0.4.20" @@ -3386,7 +3111,6 @@ dependencies = [ "lazy_static", "memchr", "mio", - "num_cpus", "pin-project-lite", "slab", "tokio-macros", @@ -3687,24 +3411,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -[[package]] -name = "typed-arena" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" - [[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - [[package]] name = "unicase" version = "1.4.2" @@ -3898,8 +3610,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ "cfg-if", - "serde", - "serde_json", "wasm-bindgen-macro", ] @@ -3918,18 +3628,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.68" @@ -4040,15 +3738,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "winreg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index e05dad1..7f745dd 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -18,7 +18,6 @@ paseto = { version = "1.0", features = ["easy_tokens", "v2"] } ring = { version = "^0.16", features = ["std"] } rand = "0" rusty_ulid = "0.10" -serde_dhall = "0.8" serde_json = "^1" serde = { version = "1", features = ["derive"] } thiserror = "1" @@ -30,6 +29,7 @@ ureq = { version = "1", features = ["json", "charset"] } uuid = { version = "0.7", features = ["serde", "v4"] } rocket_prometheus = "0.7.0" prometheus = { version = "0.10", default-features = false, features = ["process"] } +futures-io = "0.3" jsonfeed = { git = "https://github.com/Xe/site" } diff --git a/backend/src/api.rs b/backend/src/api.rs index d96b876..5d10602 100644 --- a/backend/src/api.rs +++ b/backend/src/api.rs @@ -1,4 +1,4 @@ -use crate::{models, schema, MainDatabase}; +use crate::{models, schema, web, MainDatabase}; use chrono::prelude::*; use diesel::prelude::*; use rocket::{ @@ -8,7 +8,7 @@ use rocket::{ response::Responder, Data, Outcome::*, - Response, + Response, State, }; use rocket_contrib::json::Json; use rusty_ulid::generate_ulid_string; @@ -96,8 +96,13 @@ pub fn get_current_front(conn: MainDatabase) -> Result> { } #[post("/switches/switch", data = "")] -#[instrument(skip(conn), err)] -pub fn make_switch(conn: MainDatabase, who: StringBody) -> Result { +#[instrument(skip(conn, sc, pk), err)] +pub fn make_switch( + conn: MainDatabase, + who: StringBody, + sc: State, + pk: State, +) -> Result { use schema::{members, switches}; let who = who.unwrap(); @@ -153,6 +158,9 @@ pub fn make_switch(conn: MainDatabase, who: StringBody) -> Result { info!(from = &member.cmene[..], to = &to.cmene[..], "switched"); + sc.switch(to.cmene.clone())?; + pk.switch(to.cmene.clone())?; + Ok(to.cmene) } @@ -206,6 +214,9 @@ pub enum Error { #[error("not found")] NotFound, + + #[error("web API interop error: {0}")] + Web(#[from] web::Error), } pub type Result = std::result::Result; diff --git a/backend/src/main.rs b/backend/src/main.rs index ec12939..6c0fd30 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -36,6 +36,7 @@ fn main() -> Result<()> { .attach(prometheus.clone()) .attach(MainDatabase::fairing()) .attach(SpaceHelmet::default()) + .attach(web::pluralkit::Client::fairing()) .attach(web::switchcounter::Client::fairing()) .mount("/metrics", prometheus) .mount( diff --git a/backend/src/web/mod.rs b/backend/src/web/mod.rs index 0ec293d..273c218 100644 --- a/backend/src/web/mod.rs +++ b/backend/src/web/mod.rs @@ -1 +1,22 @@ +pub mod pluralkit; pub mod switchcounter; + +pub type Result = std::result::Result; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("serde error: {0}")] + Serde(#[from] serde_json::Error), + + #[error("ureq error: {0}")] + UReq(String), + + #[error("http unsuccessful: {0}")] + HttpStatus(u16), + + #[error("futures io error: {0}")] + FuturesIO(#[from] futures_io::Error), + + #[error("systemmate mapping not found")] + SystemmateMappingNotFound(String), +} diff --git a/backend/src/web/pluralkit.rs b/backend/src/web/pluralkit.rs new file mode 100644 index 0000000..77e2944 --- /dev/null +++ b/backend/src/web/pluralkit.rs @@ -0,0 +1,82 @@ +use super::{Error, Result}; +use chrono::NaiveDateTime; +use rocket::fairing::AdHoc; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +#[derive(Deserialize, Debug)] +pub struct ProxyTag { + pub prefix: String, + pub suffix: String, +} + +#[derive(Deserialize, Debug)] +pub struct Member { + pub id: String, + pub name: Option, + pub display_name: Option, + pub description: Option, + pub color: Option, + pub avatar_url: Option, + pub birthday: Option, + pub proxy_tags: Option>, + pub keep_proxy: bool, + pub created: NaiveDateTime, +} + +#[derive(Serialize, Debug)] +pub struct SwitchRequest { + pub members: Vec, +} + +pub struct Client { + api_token: String, + member_mappings: BTreeMap, +} + +impl Client { + pub fn fairing() -> AdHoc { + AdHoc::on_attach("PluralKit client", |rocket| { + let cfg = rocket.config(); + let table = cfg.get_table("pluralkit").unwrap(); + let api_token = table["token"].as_str().unwrap().to_string(); + + let mut member_mappings = BTreeMap::new(); + + for (key, value) in table["mappings"].as_table().unwrap().iter() { + member_mappings.insert(key.clone(), value.as_str().unwrap().to_string()); + } + + let cli = Client { + api_token: api_token, + member_mappings: member_mappings, + }; + Ok(rocket.manage(cli)) + }) + } + + #[instrument(err, skip(self))] + pub fn switch(&self, member_name: String) -> Result { + let member = self + .member_mappings + .get(&member_name) + .ok_or_else(|| Error::SystemmateMappingNotFound(member_name.clone()))? + .clone(); + + let resp = ureq::post("https://api.pluralkit.me/v1/s/switches") + .set("Authorization", &self.api_token) + .set("User-Agent", crate::APPLICATION_NAME) + .send_json(serde_json::to_value(SwitchRequest { + members: vec![member], + })?); + + if resp.ok() { + Ok(()) + } else { + Err(match resp.synthetic_error() { + Some(why) => Error::UReq(why.to_string()), + None => Error::HttpStatus(resp.status()), + }) + } + } +} diff --git a/backend/src/web/switchcounter.rs b/backend/src/web/switchcounter.rs index 51451f8..2b9e970 100644 --- a/backend/src/web/switchcounter.rs +++ b/backend/src/web/switchcounter.rs @@ -1,4 +1,4 @@ -use color_eyre::eyre::{eyre, Result}; +use super::{Error, Result}; use rocket::fairing::AdHoc; use serde::{Deserialize, Serialize}; @@ -52,7 +52,10 @@ impl Client { if resp.ok() { Ok(resp.into_json_deserialize()?) } else { - Err(eyre!("{}", resp.status_line())) + Err(match resp.synthetic_error() { + Some(why) => Error::UReq(why.to_string()), + None => Error::HttpStatus(resp.status()), + }) } } @@ -66,7 +69,10 @@ impl Client { if resp.ok() { Ok(resp.into_json_deserialize()?) } else { - Err(eyre!("{}", resp.status_line())) + Err(match resp.synthetic_error() { + Some(why) => Error::UReq(why.to_string()), + None => Error::HttpStatus(resp.status()), + }) } } }