From 2c26200867ea6a16edbb006dff71babb3fad4bf8 Mon Sep 17 00:00:00 2001 From: notplants Date: Sun, 8 Sep 2024 14:45:40 -0400 Subject: [PATCH] remove golgi dependency --- Cargo.lock | 452 +++++++++--- peach-lib/Cargo.toml | 5 +- peach-lib/src/config_manager.rs | 4 +- peach-lib/src/error.rs | 36 +- peach-lib/src/lib.rs | 1 + peach-lib/src/password_utils.rs | 27 +- peach-lib/src/sbot.rs | 75 +- peach-lib/src/ssb_messages.rs | 104 +++ peach-web/Cargo.toml | 2 +- peach-web/src/error.rs | 14 +- .../routes/settings/scuttlebutt/configure.rs | 2 +- peach-web/src/utils/sbot.rs | 690 +++++++++--------- 12 files changed, 890 insertions(+), 522 deletions(-) create mode 100644 peach-lib/src/ssb_messages.rs diff --git a/Cargo.lock b/Cargo.lock index 5fb2432..083ab10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + [[package]] name = "ascii" version = "1.0.0" @@ -47,7 +53,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ - "quote 1.0.20", + "quote 1.0.37", "syn 1.0.98", ] @@ -191,8 +197,8 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -202,8 +208,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -213,6 +219,17 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" +[[package]] +name = "async-trait" +version = "0.1.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "atomic-waker" version = "1.0.0" @@ -293,6 +310,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bitflags" version = "0.3.3" @@ -614,7 +637,7 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.20", + "quote 1.0.37", "syn 1.0.98", ] @@ -635,8 +658,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "rustc_version 0.4.0", "syn 1.0.98", ] @@ -722,6 +745,15 @@ dependencies = [ "void", ] +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "env_logger" version = "0.6.2" @@ -761,6 +793,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "error-chain" version = "0.12.4" @@ -801,7 +839,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.13", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -938,8 +976,8 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -1090,7 +1128,7 @@ dependencies = [ "kuska-sodiumoxide", "kuska-ssb", "log 0.4.17", - "serde 1.0.139", + "serde 1.0.209", "serde_json", "sha2", ] @@ -1106,19 +1144,44 @@ dependencies = [ "fnv", "futures 0.1.31", "http 0.1.21", - "indexmap", + "indexmap 1.9.1", "log 0.4.17", "slab 0.4.6", "string", "tokio-io", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes 1.1.0", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.8", + "indexmap 2.5.0", + "slab 0.4.6", + "tokio 1.26.0", + "tokio-util 0.7.8", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "heck" version = "0.3.3" @@ -1251,7 +1314,7 @@ dependencies = [ "bytes 0.4.12", "futures 0.1.31", "futures-cpupool", - "h2", + "h2 0.1.26", "http 0.1.21", "http-body 0.1.0", "httparse", @@ -1282,6 +1345,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2 0.3.26", "http 0.2.8", "http-body 0.4.5", "httparse", @@ -1289,7 +1353,7 @@ dependencies = [ "itoa 1.0.2", "pin-project-lite", "socket2", - "tokio 1.19.2", + "tokio 1.26.0", "tower-service", "tracing", "want 0.3.0", @@ -1336,7 +1400,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg 1.1.0", - "hashbrown", + "hashbrown 0.12.2", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", ] [[package]] @@ -1357,6 +1431,12 @@ dependencies = [ "libc", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "itoa" version = "0.4.8" @@ -1388,7 +1468,7 @@ dependencies = [ "futures 0.1.31", "jsonrpc-core 8.0.1", "log 0.4.17", - "serde 1.0.139", + "serde 1.0.209", "serde_json", ] @@ -1417,7 +1497,7 @@ dependencies = [ "jsonrpc-core 18.0.0", "jsonrpc-pubsub", "log 0.4.17", - "serde 1.0.139", + "serde 1.0.209", "serde_json", "url 1.7.2", ] @@ -1430,7 +1510,7 @@ checksum = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" dependencies = [ "futures 0.1.31", "log 0.3.9", - "serde 1.0.139", + "serde 1.0.209", "serde_derive", "serde_json", ] @@ -1443,7 +1523,7 @@ checksum = "97b83fdc5e0218128d0d270f2f2e7a5ea716f3240c8518a58bc89e6716ba8581" dependencies = [ "futures 0.1.31", "log 0.4.17", - "serde 1.0.139", + "serde 1.0.209", "serde_derive", "serde_json", ] @@ -1458,7 +1538,7 @@ dependencies = [ "futures-executor", "futures-util", "log 0.4.17", - "serde 1.0.139", + "serde 1.0.209", "serde_derive", "serde_json", ] @@ -1515,7 +1595,7 @@ dependencies = [ "log 0.4.17", "parking_lot 0.11.2", "rand 0.7.3", - "serde 1.0.139", + "serde 1.0.209", ] [[package]] @@ -1547,9 +1627,9 @@ dependencies = [ "jsonrpc-core 18.0.0", "lazy_static", "log 0.4.17", - "tokio 1.19.2", + "tokio 1.26.0", "tokio-stream", - "tokio-util", + "tokio-util 0.6.10", "unicase", ] @@ -1563,10 +1643,34 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-pubsub", "log 0.4.17", - "serde 1.0.139", + "serde 1.0.209", "serde_json", ] +[[package]] +name = "jsonrpc_client" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c1ec33c537dc1d5a8b597313db6d213fee54320f81ea0d19b0c3869b282e1a" +dependencies = [ + "async-trait", + "jsonrpc_client_macro", + "reqwest", + "serde 1.0.209", + "serde_json", + "url 2.3.0", +] + +[[package]] +name = "jsonrpc_client_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97c11e429f0eaa41fe659013680b459d2368d8f0a3e69dccfb7a35800b0dc27b" +dependencies = [ + "quote 1.0.37", + "syn 1.0.98", +] + [[package]] name = "keccak" version = "0.1.2" @@ -1604,7 +1708,7 @@ checksum = "ae0f8eafdd240b722243787b51fdaf8df6693fb8621d0f7061cdba574214cf88" dependencies = [ "libc", "libsodium-sys", - "serde 1.0.139", + "serde 1.0.209", ] [[package]] @@ -1624,7 +1728,7 @@ dependencies = [ "log 0.4.17", "once_cell", "regex", - "serde 1.0.139", + "serde 1.0.209", "serde_json", "thiserror", ] @@ -1763,8 +1867,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "423430ac467408136d7de93f2929debd8a7bc3e795c92476f45e259b158e3355" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -1811,8 +1915,8 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60bbf2d78a45808eba478a0660f050bbce70dafc011e275cf00f6f8500a8be88" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -1870,7 +1974,7 @@ dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -1963,7 +2067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6cb122918e2e32ae9ee84b7b489dd20fec746cdad3e734095687fc2700da788a" dependencies = [ "atomicwrites", - "indexmap", + "indexmap 1.9.1", "lazy_static", "log 0.4.17", "mkdirp", @@ -2131,9 +2235,9 @@ checksum = "2069a3ae3dad97a4ae47754e8f47e5d2f1fd32ab7ad8a84bb31d051faa59cc3c" [[package]] name = "once_cell" -version = "1.13.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -2211,7 +2315,7 @@ dependencies = [ "peach-lib", "regex", "rpassword", - "serde 1.0.139", + "serde 1.0.209", "serde_json", "snafu 0.6.10", "structopt", @@ -2243,22 +2347,25 @@ dependencies = [ name = "peach-lib" version = "1.3.4" dependencies = [ + "anyhow", "async-std", "chrono", "dirs 4.0.0", "fslock", - "golgi", "jsonrpc-client-core", "jsonrpc-client-http", "jsonrpc-core 8.0.1", + "jsonrpc_client", + "kuska-ssb", "lazy_static", "log 0.4.17", "nanorand", "regex", - "serde 1.0.139", + "serde 1.0.209", "serde_json", "serde_yaml", "sha3", + "solar_client", "toml", ] @@ -2274,7 +2381,7 @@ dependencies = [ "jsonrpc-http-server 11.0.0", "log 0.4.17", "peach-lib", - "serde 1.0.139", + "serde 1.0.209", "serde_json", "ws", ] @@ -2299,7 +2406,7 @@ dependencies = [ "miniserde", "probes 0.4.1", "regex", - "serde 1.0.139", + "serde 1.0.209", "wpactrl", ] @@ -2315,7 +2422,7 @@ dependencies = [ "linux-embedded-hal", "log 0.4.17", "nix 0.11.1", - "serde 1.0.139", + "serde 1.0.209", "ssd1306", "tinybmp", ] @@ -2327,7 +2434,7 @@ dependencies = [ "log 0.4.17", "miniserde", "probes 0.4.1", - "serde 1.0.139", + "serde 1.0.209", "systemstat", ] @@ -2341,7 +2448,6 @@ dependencies = [ "dirs 4.0.0", "env_logger 0.8.4", "futures 0.3.21", - "golgi", "lazy_static", "log 0.4.17", "maud", @@ -2349,6 +2455,7 @@ dependencies = [ "peach-network", "peach-stats", "rouille", + "solar_client", "temporary", "vnstat_parse", "xdg", @@ -2430,8 +2537,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", "version_check 0.9.4", ] @@ -2442,8 +2549,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "version_check 0.9.4", ] @@ -2458,9 +2565,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2482,11 +2589,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2 1.0.40", + "proc-macro2 1.0.86", ] [[package]] @@ -2765,6 +2872,40 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64 0.21.7", + "bytes 1.1.0", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.8", + "http-body 0.4.5", + "hyper 0.14.20", + "ipnet", + "js-sys", + "log 0.4.17", + "mime", + "once_cell", + "percent-encoding 2.1.0", + "pin-project-lite", + "serde 1.0.209", + "serde_json", + "serde_urlencoded", + "tokio 1.26.0", + "tower-service", + "url 2.3.0", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rouille" version = "3.5.0" @@ -2778,14 +2919,14 @@ dependencies = [ "num_cpus", "percent-encoding 2.1.0", "rand 0.8.5", - "serde 1.0.139", + "serde 1.0.209", "serde_derive", "serde_json", "sha1", "threadpool", "time 0.3.11", "tiny_http", - "url 2.2.2", + "url 2.3.0", ] [[package]] @@ -2899,9 +3040,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.139" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -2921,13 +3062,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.139" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -2936,10 +3077,10 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ - "indexmap", + "indexmap 1.9.1", "itoa 1.0.2", "ryu", - "serde 1.0.139", + "serde 1.0.209", ] [[package]] @@ -2951,15 +3092,27 @@ dependencies = [ "serde 0.8.23", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.2", + "ryu", + "serde 1.0.209", +] + [[package]] name = "serde_yaml" version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec0091e1f5aa338283ce049bd9dfefd55e1f168ac233e85c1ffe0038fb48cbe" dependencies = [ - "indexmap", + "indexmap 1.9.1", "ryu", - "serde 1.0.139", + "serde 1.0.209", "yaml-rust", ] @@ -3100,8 +3253,8 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -3115,6 +3268,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "solar_client" +version = "0.1.0" +dependencies = [ + "anyhow", + "jsonrpc_client", + "reqwest", + "serde_json", +] + [[package]] name = "spidev" version = "0.3.0" @@ -3170,8 +3333,8 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -3192,8 +3355,19 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", "unicode-ident", ] @@ -3292,8 +3466,8 @@ version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", ] @@ -3337,7 +3511,7 @@ dependencies = [ "chrono", "chunked_transfer", "log 0.4.17", - "url 2.2.2", + "url 2.3.0", ] [[package]] @@ -3399,19 +3573,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.19.2" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ + "autocfg 1.1.0", "bytes 1.1.0", "libc", "memchr", "mio 0.8.4", "num_cpus", - "once_cell", "pin-project-lite", "socket2", - "winapi 0.3.9", + "windows-sys 0.45.0", ] [[package]] @@ -3551,7 +3725,7 @@ checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" dependencies = [ "futures-core", "pin-project-lite", - "tokio 1.19.2", + "tokio 1.26.0", ] [[package]] @@ -3651,7 +3825,21 @@ dependencies = [ "futures-sink", "log 0.4.17", "pin-project-lite", - "tokio 1.19.2", + "tokio 1.26.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes 1.1.0", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio 1.26.0", + "tracing", ] [[package]] @@ -3660,8 +3848,8 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ - "indexmap", - "serde 1.0.139", + "indexmap 1.9.1", + "serde 1.0.209", ] [[package]] @@ -3778,13 +3966,12 @@ dependencies = [ [[package]] name = "url" -version = "2.2.2" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" dependencies = [ "form_urlencoded", "idna 0.2.3", - "matches", "percent-encoding 2.1.0", ] @@ -3914,8 +4101,8 @@ dependencies = [ "bumpalo", "lazy_static", "log 0.4.17", - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", "wasm-bindgen-shared", ] @@ -3938,7 +4125,7 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ - "quote 1.0.20", + "quote 1.0.37", "wasm-bindgen-macro-support", ] @@ -3948,8 +4135,8 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -4029,43 +4216,118 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "wpactrl" version = "0.5.0" diff --git a/peach-lib/Cargo.toml b/peach-lib/Cargo.toml index 7c8ea4a..c45253f 100644 --- a/peach-lib/Cargo.toml +++ b/peach-lib/Cargo.toml @@ -9,10 +9,12 @@ async-std = "1.10" chrono = "0.4" dirs = "4.0" fslock="0.1" -golgi = { git = "https://git.coopcloud.tech/golgi-ssb/golgi.git" } +kuska-ssb = { git = "https://github.com/Kuska-ssb/ssb" } +solar_client = { path = "../../solarpub/solar_client" } jsonrpc-client-core = "0.5" jsonrpc-client-http = "0.5" jsonrpc-core = "8.0" +jsonrpc_client = "0.7" log = "0.4" nanorand = { version = "0.6", features = ["getrandom"] } regex = "1" @@ -22,3 +24,4 @@ serde_yaml = "0.8" toml = "0.5" sha3 = "0.10" lazy_static = "1.4" +anyhow = "1.0.86" diff --git a/peach-lib/src/config_manager.rs b/peach-lib/src/config_manager.rs index 49d6d38..94b97d5 100644 --- a/peach-lib/src/config_manager.rs +++ b/peach-lib/src/config_manager.rs @@ -59,8 +59,8 @@ pub fn get_peach_config_defaults() -> HashMap { ("SSB_ADMIN_IDS", ""), ("ADMIN_PASSWORD_HASH", "47"), ("TEMPORARY_PASSWORD_HASH", ""), - ("GO_SBOT_DATADIR", "/home/peach/.ssb-go"), - ("GO_SBOT_SERVICE", "go-sbot.service"), + ("SOLAR_SBOT_DATADIR", "/home/peach/.ssb-solar"), + ("SOLAR_SBOT_SERVICE", "solar-sbot.service"), ("PEACH_CONFIGDIR", "/var/lib/peachcloud"), ("PEACH_HOMEDIR", "/home/peach"), ("PEACH_WEBDIR", "/usr/share/peach-web"), diff --git a/peach-lib/src/error.rs b/peach-lib/src/error.rs index 9c55c1d..abf336b 100644 --- a/peach-lib/src/error.rs +++ b/peach-lib/src/error.rs @@ -1,9 +1,9 @@ #![warn(missing_docs)] //! Error handling for various aspects of the PeachCloud system, including the network, OLED, stats and dyndns JSON-RPC clients, as well as the configuration manager, sbot client and password utilities. - -use golgi::GolgiError; use std::{io, str, string}; +use jsonrpc_client::JsonRpcError; +use anyhow::Error; // Add the anyhow crate for errors /// This type represents all possible errors that can occur when interacting with the PeachCloud library. #[derive(Debug)] @@ -104,8 +104,15 @@ pub enum PeachError { path: String, }, - /// Represents a Golgi error - Golgi(GolgiError), + /// Represents a JsonRpcError with Solar + JsonRpcError(JsonRpcError), + + /// Represents an Anyhow error with Solar + SolarClientError(String), + + /// Represents an error with encoding or decoding an SsbMessage + SsbMessageError(String), + } impl std::error::Error for PeachError { @@ -134,7 +141,9 @@ impl std::error::Error for PeachError { PeachError::Utf8ToStr(_) => None, PeachError::Utf8ToString(_) => None, PeachError::Write { ref source, .. } => Some(source), - PeachError::Golgi(_) => None, + PeachError::JsonRpcError(_) => None, + PeachError::SolarClientError(_) => None, + PeachError::SsbMessageError(_) => None, } } } @@ -192,7 +201,9 @@ impl std::fmt::Display for PeachError { PeachError::Write { ref path, .. } => { write!(f, "Write error: {}", path) } - PeachError::Golgi(ref err) => err.fmt(f), + PeachError::JsonRpcError(ref err) => err.fmt(f), + PeachError::SolarClientError(ref err) => err.fmt(f), + PeachError::SsbMessageError(ref err) => err.fmt(f), } } } @@ -263,8 +274,15 @@ impl From for PeachError { } } -impl From for PeachError { - fn from(err: GolgiError) -> PeachError { - PeachError::Golgi(err) +impl From for PeachError { + fn from(err: JsonRpcError) -> PeachError { + PeachError::JsonRpcError(err) } } + +impl From for PeachError { + fn from(error: anyhow::Error) -> Self { + // TODO: include whole error somehow? + PeachError::SolarClientError(error.to_string()) + } +} \ No newline at end of file diff --git a/peach-lib/src/lib.rs b/peach-lib/src/lib.rs index cdbe8fa..1a3afd7 100644 --- a/peach-lib/src/lib.rs +++ b/peach-lib/src/lib.rs @@ -6,6 +6,7 @@ pub mod oled_client; pub mod password_utils; pub mod sbot; pub mod stats_client; +pub mod ssb_messages; // re-export error types pub use jsonrpc_client_core; diff --git a/peach-lib/src/password_utils.rs b/peach-lib/src/password_utils.rs index cbdd158..cde3ad9 100644 --- a/peach-lib/src/password_utils.rs +++ b/peach-lib/src/password_utils.rs @@ -1,9 +1,9 @@ use async_std::task; -use golgi::{sbot::Keystore, Sbot}; use log::debug; use nanorand::{Rng, WyRand}; use sha3::{Digest, Sha3_256}; +use crate::sbot::init_sbot; use crate::{config_manager, error::PeachError, sbot::SbotConfig}; /// Returns Ok(()) if the supplied password is correct, @@ -122,22 +122,15 @@ async fn publish_private_msg(msg: &str, recipient: &str) -> Result<(), String> { let recipient = vec![recipient.to_string()]; // initialise sbot connection with ip:port and shscap from config file - let mut sbot_client = match sbot_config { - // TODO: panics if we pass `Some(conf.shscap)` as second arg - Some(conf) => { - let ip_port = conf.lis.clone(); - Sbot::init(Keystore::GoSbot, Some(ip_port), None) - .await - .map_err(|e| e.to_string())? - } - None => Sbot::init(Keystore::GoSbot, None, None) - .await - .map_err(|e| e.to_string())?, - }; + let mut sbot_client = init_sbot(); debug!("Publishing a Scuttlebutt private message with temporary password"); - match sbot_client.publish_private(msg, recipient).await { - Ok(_) => Ok(()), - Err(e) => Err(format!("Failed to publish private message: {}", e)), - } + // TODO: implement publish private message in solar, and then implement this + Err(format!("Failed to publish private message: \ + private publishing is not yet implemented in solar_client: \ + the message meant to be sent was: {}", msg)) + // match sbot_client.publish_private(msg, recipient).await { + // Ok(_) => Ok(()), + // Err(e) => Err(format!("Failed to publish private message: {}", e)), + // } } diff --git a/peach-lib/src/sbot.rs b/peach-lib/src/sbot.rs index 730df22..a694ce4 100644 --- a/peach-lib/src/sbot.rs +++ b/peach-lib/src/sbot.rs @@ -1,8 +1,8 @@ -//! Data types and associated methods for monitoring and configuring go-sbot. +//! Data types and associated methods for monitoring and configuring solar-sbot. use std::{fs, fs::File, io, io::Write, path::PathBuf, process::Command, str}; - -use golgi::{sbot::Keystore, Sbot}; +use std::os::linux::raw::ino_t; +use solar_client::{Client, SolarClient}; use log::debug; use crate::config_manager; @@ -30,7 +30,7 @@ fn dir_size(path: impl Into) -> io::Result { /* SBOT-RELATED TYPES AND METHODS */ -/// go-sbot process status. +/// solar-sbot process status. #[derive(Debug, Serialize, Deserialize)] pub struct SbotStatus { /// Current process state. @@ -62,7 +62,7 @@ impl Default for SbotStatus { } impl SbotStatus { - /// Retrieve statistics for the go-sbot systemd process by querying `systemctl`. + /// Retrieve statistics for the solar-sbot systemd process by querying `systemctl`. pub fn read() -> Result { let mut status = SbotStatus::default(); @@ -70,7 +70,7 @@ impl SbotStatus { // because non-privileged users are able to run systemctl show let info_output = Command::new("systemctl") .arg("show") - .arg(config_manager::get_config_value("GO_SBOT_SERVICE")?) + .arg(config_manager::get_config_value("SOLAR_SBOT_SERVICE")?) .arg("--no-page") .output()?; @@ -92,7 +92,7 @@ impl SbotStatus { // because non-privileged users are able to run systemctl status let status_output = Command::new("systemctl") .arg("status") - .arg(config_manager::get_config_value("GO_SBOT_SERVICE")?) + .arg(config_manager::get_config_value("SOLAR_SBOT_SERVICE")?) .output()?; let service_status = str::from_utf8(&status_output.stdout)?; @@ -100,7 +100,7 @@ impl SbotStatus { for line in service_status.lines() { // example of the output line we're looking for: - // `Loaded: loaded (/home/glyph/.config/systemd/user/go-sbot.service; enabled; vendor + // `Loaded: loaded (/home/glyph/.config/systemd/user/solar-sbot.service; enabled; vendor // preset: enabled)` if line.contains("Loaded:") { let before_boot_state = line.find(';'); @@ -133,7 +133,7 @@ impl SbotStatus { // get path to blobstore let blobstore_path = format!( "{}/blobs/sha256", - config_manager::get_config_value("GO_SBOT_DATADIR")? + config_manager::get_config_value("SOLAR_SBOT_DATADIR")? ); // determine the size of the blobstore directory in bytes @@ -143,10 +143,10 @@ impl SbotStatus { } } -/// go-sbot configuration parameters. -#[derive(Debug, Serialize, Deserialize)] +/// solar-sbot configuration parameters. +#[derive(Debug, Serialize, Deserialize, Default)] #[serde(default)] -pub struct SbotConfig { +pub struct Config { // TODO: maybe define as a Path type? /// Directory path for the log and indexes. pub repo: String, @@ -180,7 +180,27 @@ pub struct SbotConfig { pub repair: bool, } -/// Default configuration values for go-sbot. +// TODO: make this real +#[derive(Debug, Deserialize, Serialize)] +#[serde(default)] +pub struct SbotConfig { + pub repo: String, + pub debugdir: String, + pub shscap: String, + pub hmac: String, + pub hops: i8, + pub lis: String, + pub wslis: String, + pub debuglis: String, + pub localadv: bool, + pub localdiscov: bool, + pub enable_ebt: bool, + pub promisc: bool, + pub nounixsock: bool, + pub repair: bool, +} + +/// Default configuration values for solar-sbot. impl Default for SbotConfig { fn default() -> Self { Self { @@ -203,12 +223,12 @@ impl Default for SbotConfig { } impl SbotConfig { - /// Read the go-sbot `config.toml` file from file and deserialize into `SbotConfig`. + /// Read the solar-sbot `config.toml` file from file and deserialize into `SbotConfig`. pub fn read() -> Result { - // determine path of user's go-sbot config.toml + // determine path of user's solar-sbot config.toml let config_path = format!( "{}/config.toml", - config_manager::get_config_value("GO_SBOT_DATADIR")? + config_manager::get_config_value("SOLAR_SBOT_DATADIR")? ); let config_contents = fs::read_to_string(config_path)?; @@ -218,17 +238,17 @@ impl SbotConfig { Ok(config) } - /// Write the given `SbotConfig` to the go-sbot `config.toml` file. + /// Write the given `SbotConfig` to the solar-sbot `config.toml` file. pub fn write(config: SbotConfig) -> Result<(), PeachError> { - let repo_comment = "# For details about go-sbot configuration, please visit the repo: https://github.com/cryptoscope/ssb\n".to_string(); + let repo_comment = "# For details about solar-sbot configuration, please visit the repo: https://github.com/cryptoscope/ssb\n".to_string(); // convert the provided `SbotConfig` instance to a string let config_string = toml::to_string(&config)?; - // determine path of user's go-sbot config.toml + // determine path of user's solar-sbot config.toml let config_path = format!( "{}/config.toml", - config_manager::get_config_value("GO_SBOT_DATADIR")? + config_manager::get_config_value("SOLAR_SBOT_DATADIR")? ); // open config file for writing @@ -245,7 +265,7 @@ impl SbotConfig { } /// Initialise an sbot client -pub async fn init_sbot() -> Result { +pub async fn init_sbot() -> Result { // read sbot config from config.toml let sbot_config = SbotConfig::read().ok(); @@ -253,15 +273,10 @@ pub async fn init_sbot() -> Result { // initialise sbot connection with ip:port and shscap from config file let key_path = format!( "{}/secret", - config_manager::get_config_value("GO_SBOT_DATADIR")? + config_manager::get_config_value("SOLAR_SBOT_DATADIR")? ); - let sbot_client = match sbot_config { - // TODO: panics if we pass `Some(conf.shscap)` as second arg - Some(conf) => { - let ip_port = conf.lis.clone(); - Sbot::init(Keystore::CustomGoSbot(key_path), Some(ip_port), None).await? - } - None => Sbot::init(Keystore::CustomGoSbot(key_path), None, None).await?, - }; + // TODO: read this from config + const SERVER_ADDR: &str = "http://127.0.0.1:3030"; + let sbot_client = Client::new(SERVER_ADDR.to_owned())?; Ok(sbot_client) } diff --git a/peach-lib/src/ssb_messages.rs b/peach-lib/src/ssb_messages.rs new file mode 100644 index 0000000..6684d2b --- /dev/null +++ b/peach-lib/src/ssb_messages.rs @@ -0,0 +1,104 @@ +//! Message types and conversion methods. + +use kuska_ssb::api::dto::content::TypedMessage; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::fmt::Debug; +use crate::error::PeachError; +use crate::error::PeachError::SsbMessageError; + +/// `SsbMessageContent` is a type alias for `TypedMessage` from the `kuska_ssb` library. +/// It is aliased in golgi to fit the naming convention of the other message +/// types: `SsbMessageKVT` and `SsbMessageValue`. +/// +/// See the [kuska source code](https://github.com/Kuska-ssb/ssb/blob/master/src/api/dto/content.rs#L103) for the type definition of `TypedMessage`. +pub type SsbMessageContent = TypedMessage; + +/// The `value` of an SSB message (the `V` in `KVT`). +/// +/// More information concerning the data model can be found in the +/// [`Metadata` documentation](https://spec.scuttlebutt.nz/feed/messages.html#metadata). +#[derive(Serialize, Deserialize, Debug)] +#[serde(deny_unknown_fields)] +#[allow(missing_docs)] +pub struct SsbMessageValue { + pub previous: Option, + pub author: String, + pub sequence: u64, + pub timestamp: f64, + pub hash: String, + pub content: Value, + pub signature: String, +} + +/// Message content types. +#[derive(Debug, Eq, PartialEq)] +#[allow(missing_docs)] +pub enum SsbMessageContentType { + About, + Vote, + Post, + Contact, + Unrecognized, +} + +impl SsbMessageValue { + /// Get the type field of the message content as an enum, if found. + /// + /// If no `type` field is found or the `type` field is not a string, + /// it returns an `Err(GolgiError::ContentType)`. + /// + /// If a `type` field is found but with an unknown string, + /// it returns an `Ok(SsbMessageContentType::Unrecognized)`. + pub fn get_message_type(&self) -> Result { + let msg_type = self + .content + .get("type") + .ok_or_else(|| SsbMessageError("type field not found".to_string()))?; + let mtype_str: &str = msg_type.as_str().ok_or_else(|| { + SsbMessageError("type field value is not a string as expected".to_string()) + })?; + let enum_type = match mtype_str { + "about" => SsbMessageContentType::About, + "post" => SsbMessageContentType::Post, + "vote" => SsbMessageContentType::Vote, + "contact" => SsbMessageContentType::Contact, + _ => SsbMessageContentType::Unrecognized, + }; + Ok(enum_type) + } + + /// Helper function which returns `true` if this message is of the given type, + /// and `false` if the type does not match or is not found. + pub fn is_message_type(&self, message_type: SsbMessageContentType) -> bool { + let self_message_type = self.get_message_type(); + match self_message_type { + Ok(mtype) => mtype == message_type, + Err(_err) => false, + } + } + + /// Convert the content JSON value into an `SsbMessageContent` `enum`, + /// using the `type` field as a tag to select which variant of the `enum` + /// to deserialize into. + /// + /// See the [Serde docs on internally-tagged enum representations](https://serde.rs/enum-representations.html#internally-tagged) for further details. + pub fn into_ssb_message_content(self) -> Result { + let m: SsbMessageContent = serde_json::from_value(self.content)?; + Ok(m) + } +} + +/// An SSB message represented as a key-value-timestamp (`KVT`). +/// +/// More information concerning the data model can be found in the +/// [`Metadata` documentation](https://spec.scuttlebutt.nz/feed/messages.html#metadata). +#[derive(Serialize, Deserialize, Debug)] +#[serde(deny_unknown_fields)] +#[allow(missing_docs)] +pub struct SsbMessageKVT { + pub key: String, + pub value: SsbMessageValue, + pub timestamp: Option, + pub rts: Option, +} \ No newline at end of file diff --git a/peach-web/Cargo.toml b/peach-web/Cargo.toml index 1b13b00..4ab4f61 100644 --- a/peach-web/Cargo.toml +++ b/peach-web/Cargo.toml @@ -39,7 +39,7 @@ chrono = "0.4" dirs = "4.0" env_logger = "0.8" futures = "0.3" -golgi = { git = "https://git.coopcloud.tech/golgi-ssb/golgi.git" } +solar_client = { path = "../../solarpub/solar_client" } lazy_static = "1.4" log = "0.4" maud = "0.23" diff --git a/peach-web/src/error.rs b/peach-web/src/error.rs index 0d5453b..ebb3db5 100644 --- a/peach-web/src/error.rs +++ b/peach-web/src/error.rs @@ -2,7 +2,6 @@ use std::io::Error as IoError; -use golgi::GolgiError; use peach_lib::error::PeachError; use peach_lib::{serde_json, serde_yaml}; use serde_json::error::Error as JsonError; @@ -12,26 +11,26 @@ use serde_yaml::Error as YamlError; #[derive(Debug)] pub enum PeachWebError { FailedToRegisterDynDomain(String), - Golgi(GolgiError), HomeDir, Io(IoError), Json(JsonError), OsString, PeachLib { source: PeachError, msg: String }, Yaml(YamlError), + NotYetImplemented, } impl std::error::Error for PeachWebError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match *self { PeachWebError::FailedToRegisterDynDomain(_) => None, - PeachWebError::Golgi(ref source) => Some(source), PeachWebError::HomeDir => None, PeachWebError::Io(ref source) => Some(source), PeachWebError::Json(ref source) => Some(source), PeachWebError::OsString => None, PeachWebError::PeachLib { ref source, .. } => Some(source), PeachWebError::Yaml(ref source) => Some(source), + PeachWebError::NotYetImplemented => None } } } @@ -42,7 +41,6 @@ impl std::fmt::Display for PeachWebError { PeachWebError::FailedToRegisterDynDomain(ref msg) => { write!(f, "DYN DNS error: {}", msg) } - PeachWebError::Golgi(ref source) => write!(f, "Golgi error: {}", source), PeachWebError::HomeDir => write!( f, "Filesystem error: failed to determine home directory path" @@ -55,16 +53,11 @@ impl std::fmt::Display for PeachWebError { ), PeachWebError::PeachLib { ref source, .. } => write!(f, "{}", source), PeachWebError::Yaml(ref source) => write!(f, "Serde YAML error: {}", source), + PeachWebError::NotYetImplemented => write!(f, "Not yet implemented"), } } } -impl From for PeachWebError { - fn from(err: GolgiError) -> PeachWebError { - PeachWebError::Golgi(err) - } -} - impl From for PeachWebError { fn from(err: IoError) -> PeachWebError { PeachWebError::Io(err) @@ -91,3 +84,4 @@ impl From for PeachWebError { PeachWebError::Yaml(err) } } + diff --git a/peach-web/src/routes/settings/scuttlebutt/configure.rs b/peach-web/src/routes/settings/scuttlebutt/configure.rs index d2a54cf..5eb249b 100644 --- a/peach-web/src/routes/settings/scuttlebutt/configure.rs +++ b/peach-web/src/routes/settings/scuttlebutt/configure.rs @@ -205,7 +205,7 @@ pub fn handle_form(request: &Request, restart: bool) -> Response { debugdir: String, shscap: String, hmac: String, - hops: u8, + hops: i8, lis_ip: String, lis_port: String, wslis: String, diff --git a/peach-web/src/utils/sbot.rs b/peach-web/src/utils/sbot.rs index 95f7a31..9e9b4f3 100644 --- a/peach-web/src/utils/sbot.rs +++ b/peach-web/src/utils/sbot.rs @@ -11,29 +11,25 @@ use std::{ use async_std::task; use dirs; use futures::stream::TryStreamExt; -use golgi::{ - api::{friends::RelationshipQuery, history_stream::CreateHistoryStream}, - blobs, - messages::SsbMessageKVT, - sbot::Keystore, - Sbot, -}; use log::debug; use peach_lib::config_manager; use peach_lib::sbot::SbotConfig; +use peach_lib::sbot::init_sbot; +use peach_lib::ssb_messages::SsbMessageKVT; +use solar_client::{Client, SolarClient}; use rouille::input::post::BufferedFile; use temporary::Directory; - +use peach_lib::serde_json::json; use crate::{error::PeachWebError, utils::sbot}; // SBOT HELPER FUNCTIONS -/// Executes a systemctl command for the go-sbot.service process. +/// Executes a systemctl command for the solar-sbot.service process. pub fn systemctl_sbot_cmd(cmd: &str) -> Result { let output = Command::new("sudo") .arg("systemctl") .arg(cmd) - .arg(config_manager::get_config_value("GO_SBOT_SERVICE")?) + .arg(config_manager::get_config_value("SOLAR_SBOT_SERVICE")?) .output()?; Ok(output) } @@ -41,7 +37,7 @@ pub fn systemctl_sbot_cmd(cmd: &str) -> Result { /// Executes a systemctl stop command followed by start command. /// Returns a redirect with a flash message stating the output of the restart attempt. pub fn restart_sbot_process() -> (String, String) { - debug!("Restarting go-sbot.service"); + debug!("Restarting solar-sbot.service"); match systemctl_sbot_cmd("stop") { // if stop was successful, try to start the process Ok(_) => match systemctl_sbot_cmd("start") { @@ -70,21 +66,14 @@ pub fn restart_sbot_process() -> (String, String) { /// Initialise an sbot client with the given configuration parameters. pub async fn init_sbot_with_config( sbot_config: &Option, -) -> Result { +) -> Result { debug!("Initialising an sbot client with configuration parameters"); // initialise sbot connection with ip:port and shscap from config file let key_path = format!( "{}/secret", config_manager::get_config_value("GO_SBOT_DATADIR")? ); - let sbot_client = match sbot_config { - // TODO: panics if we pass `Some(conf.shscap)` as second arg - Some(conf) => { - let ip_port = conf.lis.clone(); - Sbot::init(Keystore::CustomGoSbot(key_path), Some(ip_port), None).await? - } - None => Sbot::init(Keystore::CustomGoSbot(key_path), None, None).await?, - }; + let sbot_client = init_sbot().await?; Ok(sbot_client) } @@ -127,50 +116,53 @@ pub fn validate_public_key(public_key: &str) -> Result<(), String> { /// reverses the list and reads the sequence number of the most recently /// authored message. This gives us the size of the database in terms of /// the total number of locally-authored messages. -pub fn latest_sequence_number() -> Result> { - // retrieve latest go-sbot configuration parameters +pub fn latest_sequence_number() -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config).await?; + Err(PeachWebError::NotYetImplemented) + // retrieve the local id - let id = sbot_client.whoami().await?; + // let id = sbot_client.whoami().await?; - let args = CreateHistoryStream::new(id).keys_values(true, true); - let history_stream = sbot_client.create_history_stream(args).await?; - let mut msgs: Vec = history_stream.try_collect().await?; + // let history_stream = sbot_client.feed(&id).await?; - // there will be zero messages when the sbot is run for the first time - if msgs.is_empty() { - Ok(0) - } else { - // reverse the list of messages so we can easily reference the latest one - msgs.reverse(); - - // return the sequence number of the latest msg - Ok(msgs[0].value.sequence) - } + // let mut msgs: Vec = history_stream.try_collect().await?; + // + // // there will be zero messages when the sbot is run for the first time + // if msgs.is_empty() { + // Ok(0) + // } else { + // // reverse the list of messages so we can easily reference the latest one + // msgs.reverse(); + // + // // return the sequence number of the latest msg + // Ok(msgs[0].value.sequence) + // } }) } -pub fn create_invite(uses: u16) -> Result> { - // retrieve latest go-sbot configuration parameters +pub fn create_invite(uses: u16) -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config).await?; debug!("Generating Scuttlebutt invite code"); - let mut invite_code = sbot_client.invite_create(uses).await?; - - // insert domain into invite if one is configured - let domain = config_manager::get_config_value("EXTERNAL_DOMAIN")?; - if !domain.is_empty() { - invite_code = domain + &invite_code[4..]; - } - - Ok(invite_code) + Err(PeachWebError::NotYetImplemented) + // let mut invite_code = sbot_client.invite_create(uses).await?; + // + // // insert domain into invite if one is configured + // let domain = config_manager::get_config_value("EXTERNAL_DOMAIN")?; + // if !domain.is_empty() { + // invite_code = domain + &invite_code[4..]; + // } + // + // Ok(invite_code) }) } @@ -209,91 +201,71 @@ impl Profile { } /// Retrieve the profile info for the given public key. -pub fn get_profile_info(ssb_id: Option) -> Result> { - // retrieve latest go-sbot configuration parameters +pub fn get_profile_info(ssb_id: Option) -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - let local_id = sbot_client.whoami().await?; - - let mut profile = Profile::default(); - - // if an ssb_id has been provided, we assume that the profile info - // being retrieved is for a peer (ie. not for our local profile) - let id = if let Some(peer_id) = ssb_id { - // we are not dealing with the local profile - profile.is_local_profile = false; - - // determine relationship between peer and local id - let follow_query = RelationshipQuery { - source: local_id.clone(), - dest: peer_id.clone(), - }; - - // query follow state - profile.following = match sbot_client.friends_is_following(follow_query).await { - Ok(following) if following == "true" => Some(true), - Ok(following) if following == "false" => Some(false), - _ => None, - }; - - // TODO: i don't like that we have to instantiate the same query object - // twice. see if we can streamline this in golgi - let block_query = RelationshipQuery { - source: local_id.clone(), - dest: peer_id.clone(), - }; - - // query block state - profile.blocking = match sbot_client.friends_is_blocking(block_query).await { - Ok(blocking) if blocking == "true" => Some(true), - Ok(blocking) if blocking == "false" => Some(false), - _ => None, - }; - - peer_id - } else { - // if an ssb_id has not been provided, retrieve the local id using whoami - profile.is_local_profile = true; - - local_id - }; - - // retrieve the profile info for the given id - let info = sbot_client.get_profile_info(&id).await?; - // set each profile field accordingly - for (key, val) in info { - match key.as_str() { - "name" => profile.name = Some(val), - "description" => profile.description = Some(val), - "image" => profile.image = Some(val), - _ => (), - } - } - - // assign the ssb public key - // (could be for the local profile or a peer) - profile.id = Some(id); - - // determine the path to the blob defined by the value of `profile.image` - if let Some(ref blob_id) = profile.image { - profile.blob_path = match blobs::get_blob_path(blob_id) { - Ok(path) => { - // if we get the path, check if the blob is in the blobstore. - // this allows us to default to a placeholder image in the template - if let Ok(exists) = blob_is_stored_locally(&path).await { - profile.blob_exists = exists - }; - - Some(path) - } - Err(_) => None, - } - } - - Ok(profile) + Err(PeachWebError::NotYetImplemented) + // let local_id = sbot_client.whoami().await?; + // + // let mut profile = Profile::default(); + // + // // if an ssb_id has been provided, we assume that the profile info + // // being retrieved is for a peer (ie. not for our local profile) + // let id = if let Some(peer_id) = ssb_id { + // // we are not dealing with the local profile + // profile.is_local_profile = false; + // + // // query follow state + // profile.following = Some(sbot_client.is_following(&local_id, &peer_id).await?); + // + // // TODO: implement this check in solar_client so that this can be a real value + // profile.blocking = Some(false); + // + // peer_id + // } else { + // // if an ssb_id has not been provided, retrieve the local id using whoami + // profile.is_local_profile = true; + // + // local_id + // }; + // + // // retrieve the profile info for the given id + // let info = sbot_client.get_profile_info(&id).await?; + // // set each profile field accordingly + // for (key, val) in info { + // match key.as_str() { + // "name" => profile.name = Some(val), + // "description" => profile.description = Some(val), + // "image" => profile.image = Some(val), + // _ => (), + // } + // } + // + // // assign the ssb public key + // // (could be for the local profile or a peer) + // profile.id = Some(id); + // + // // determine the path to the blob defined by the value of `profile.image` + // if let Some(ref blob_id) = profile.image { + // profile.blob_path = match blobs::get_blob_path(blob_id) { + // Ok(path) => { + // // if we get the path, check if the blob is in the blobstore. + // // this allows us to default to a placeholder image in the template + // if let Ok(exists) = blob_is_stored_locally(&path).await { + // profile.blob_exists = exists + // }; + // + // Some(path) + // } + // Err(_) => None, + // } + // } + // + // Ok(profile) }) } @@ -306,78 +278,78 @@ pub fn update_profile_info( new_name: Option, new_description: Option, image: Option, -) -> Result { - // retrieve latest go-sbot configuration parameters +) -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config) - .await - .map_err(|e| e.to_string())?; + .await?; - // track whether the name, description or image have been updated - let mut name_updated: bool = false; - let mut description_updated: bool = false; - let mut image_updated: bool = false; - - // check if a new_name value has been submitted in the form - if let Some(name) = new_name { - // only update the name if it has changed - if name != current_name { - debug!("Publishing a new Scuttlebutt profile name"); - if let Err(e) = sbot_client.publish_name(&name).await { - return Err(format!("Failed to update name: {}", e)); - } else { - name_updated = true - } - } - } - - if let Some(description) = new_description { - // only update the description if it has changed - if description != current_description { - debug!("Publishing a new Scuttlebutt profile description"); - if let Err(e) = sbot_client.publish_description(&description).await { - return Err(format!("Failed to update description: {}", e)); - } else { - description_updated = true - } - } - } - - // only update the image if a file was uploaded - if let Some(img) = image { - // only write the blob if it has a filename and data > 0 bytes - if img.filename.is_some() && !img.data.is_empty() { - match write_blob_to_store(img).await { - Ok(blob_id) => { - // if the file was successfully added to the blobstore, - // publish an about image message with the blob id - if let Err(e) = sbot_client.publish_image(&blob_id).await { - return Err(format!("Failed to update image: {}", e)); - } else { - image_updated = true - } - } - Err(e) => return Err(format!("Failed to add image to blobstore: {}", e)), - } - } else { - image_updated = false - } - } - - if name_updated || description_updated || image_updated { - Ok("Profile updated".to_string()) - } else { - // no updates were made but no errors were encountered either - Ok("Profile info unchanged".to_string()) - } + Err(PeachWebError::NotYetImplemented) + // // track whether the name, description or image have been updated + // let mut name_updated: bool = false; + // let mut description_updated: bool = false; + // let mut image_updated: bool = false; + // + // // check if a new_name value has been submitted in the form + // if let Some(name) = new_name { + // // only update the name if it has changed + // if name != current_name { + // debug!("Publishing a new Scuttlebutt profile name"); + // if let Err(e) = sbot_client.publish_name(&name).await { + // return Err(format!("Failed to update name: {}", e)); + // } else { + // name_updated = true + // } + // } + // } + // + // if let Some(description) = new_description { + // // only update the description if it has changed + // if description != current_description { + // debug!("Publishing a new Scuttlebutt profile description"); + // if let Err(e) = sbot_client.publish_description(&description).await { + // return Err(format!("Failed to update description: {}", e)); + // } else { + // description_updated = true + // } + // } + // } + // + // // only update the image if a file was uploaded + // if let Some(img) = image { + // // only write the blob if it has a filename and data > 0 bytes + // if img.filename.is_some() && !img.data.is_empty() { + // match write_blob_to_store(img).await { + // Ok(blob_id) => { + // // if the file was successfully added to the blobstore, + // // publish an about image message with the blob id + // if let Err(e) = sbot_client.publish_image(&blob_id).await { + // return Err(format!("Failed to update image: {}", e)); + // } else { + // image_updated = true + // } + // } + // Err(e) => return Err(format!("Failed to add image to blobstore: {}", e)), + // } + // } else { + // image_updated = false + // } + // } + // + // if name_updated || description_updated || image_updated { + // Ok("Profile updated".to_string()) + // } else { + // // no updates were made but no errors were encountered either + // Ok("Profile info unchanged".to_string()) + // } }) } /// Follow a peer. pub fn follow_peer(public_key: &str) -> Result { - // retrieve latest go-sbot configuration parameters + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { @@ -386,7 +358,7 @@ pub fn follow_peer(public_key: &str) -> Result { .map_err(|e| e.to_string())?; debug!("Following a Scuttlebutt peer"); - match sbot_client.follow(public_key).await { + match sbot_client.follows(public_key).await { Ok(_) => Ok("Followed peer".to_string()), Err(e) => Err(format!("Failed to follow peer: {}", e)), } @@ -394,26 +366,26 @@ pub fn follow_peer(public_key: &str) -> Result { } /// Unfollow a peer. -pub fn unfollow_peer(public_key: &str) -> Result { - // retrieve latest go-sbot configuration parameters +pub fn unfollow_peer(public_key: &str) -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config) - .await - .map_err(|e| e.to_string())?; + .await?; - debug!("Unfollowing a Scuttlebutt peer"); - match sbot_client.unfollow(public_key).await { - Ok(_) => Ok("Unfollowed peer".to_string()), - Err(e) => Err(format!("Failed to unfollow peer: {}", e)), - } + Err(PeachWebError::NotYetImplemented) + // debug!("Unfollowing a Scuttlebutt peer"); + // match sbot_client.unfollow(public_key).await { + // Ok(_) => Ok("Unfollowed peer".to_string()), + // Err(e) => Err(format!("Failed to unfollow peer: {}", e)), + // } }) } /// Block a peer. pub fn block_peer(public_key: &str) -> Result { - // retrieve latest go-sbot configuration parameters + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { @@ -422,7 +394,7 @@ pub fn block_peer(public_key: &str) -> Result { .map_err(|e| e.to_string())?; debug!("Blocking a Scuttlebutt peer"); - match sbot_client.block(public_key).await { + match sbot_client.blocks(public_key).await { Ok(_) => Ok("Blocked peer".to_string()), Err(e) => Err(format!("Failed to block peer: {}", e)), } @@ -430,172 +402,171 @@ pub fn block_peer(public_key: &str) -> Result { } /// Unblock a peer. -pub fn unblock_peer(public_key: &str) -> Result { - // retrieve latest go-sbot configuration parameters +pub fn unblock_peer(public_key: &str) -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config) - .await - .map_err(|e| e.to_string())?; + .await?; debug!("Unblocking a Scuttlebutt peer"); - match sbot_client.unblock(public_key).await { - Ok(_) => Ok("Unblocked peer".to_string()), - Err(e) => Err(format!("Failed to unblock peer: {}", e)), - } + Err(PeachWebError::NotYetImplemented) + // match sbot_client.unblock(public_key).await { + // Ok(_) => Ok("Unblocked peer".to_string()), + // Err(e) => Err(format!("Failed to unblock peer: {}", e)), + // } }) } /// Retrieve a list of peers blocked by the local public key. -pub fn get_blocks_list() -> Result>, Box> { - // retrieve latest go-sbot configuration parameters +pub fn get_blocks_list() -> Result>, PeachWebError> { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - let blocks = sbot_client.get_blocks().await?; - - // we'll use this to store the profile info for each peer whom we block - let mut peer_list = Vec::new(); - - if !blocks.is_empty() { - for peer in blocks.iter() { - // trim whitespace (including newline characters) and - // remove the inverted-commas around the id - let key = peer.trim().replace('"', ""); - // retrieve the profile info for the given peer - let mut peer_info = sbot_client.get_profile_info(&key).await?; - // insert the public key of the peer into the info hashmap - peer_info.insert("id".to_string(), key.to_string()); - // we do not even attempt to find the blob for a blocked peer, - // since it may be vulgar to cause distress to the local peer. - peer_info.insert("blob_exists".to_string(), "false".to_string()); - // push profile info to peer_list vec - peer_list.push(peer_info) - } - } - - // return the list of blocked peers - Ok(peer_list) + Err(PeachWebError::NotYetImplemented) + // let blocks = sbot_client.get_blocks().await?; + // + // // we'll use this to store the profile info for each peer whom we block + // let mut peer_list = Vec::new(); + // + // if !blocks.is_empty() { + // for peer in blocks.iter() { + // // trim whitespace (including newline characters) and + // // remove the inverted-commas around the id + // let key = peer.trim().replace('"', ""); + // // retrieve the profile info for the given peer + // let mut peer_info = sbot_client.get_profile_info(&key).await?; + // // insert the public key of the peer into the info hashmap + // peer_info.insert("id".to_string(), key.to_string()); + // // we do not even attempt to find the blob for a blocked peer, + // // since it may be vulgar to cause distress to the local peer. + // peer_info.insert("blob_exists".to_string(), "false".to_string()); + // // push profile info to peer_list vec + // peer_list.push(peer_info) + // } + // } + // + // // return the list of blocked peers + // Ok(peer_list) }) } /// Retrieve a list of peers followed by the local public key. -pub fn get_follows_list() -> Result>, Box> { - // retrieve latest go-sbot configuration parameters +pub fn get_follows_list() -> Result>, PeachWebError> { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - let follows = sbot_client.get_follows().await?; + Err(PeachWebError::NotYetImplemented) - // we'll use this to store the profile info for each peer who follows us - let mut peer_list = Vec::new(); - - if !follows.is_empty() { - for peer in follows.iter() { - // trim whitespace (including newline characters) and - // remove the inverted-commas around the id - let key = peer.trim().replace('"', ""); - // retrieve the profile info for the given peer - let mut peer_info = sbot_client.get_profile_info(&key).await?; - // insert the public key of the peer into the info hashmap - peer_info.insert("id".to_string(), key.to_string()); - // retrieve the profile image blob id for the given peer - if let Some(blob_id) = peer_info.get("image") { - // look-up the path for the image blob - if let Ok(blob_path) = blobs::get_blob_path(blob_id) { - // insert the image blob path of the peer into the info hashmap - peer_info.insert("blob_path".to_string(), blob_path.to_string()); - // check if the blob is in the blobstore - // set a flag in the info hashmap - match blob_is_stored_locally(&blob_path).await { - Ok(exists) if exists => { - peer_info.insert("blob_exists".to_string(), "true".to_string()) - } - _ => peer_info.insert("blob_exists".to_string(), "false".to_string()), - }; - } - } - // push profile info to peer_list vec - peer_list.push(peer_info) - } - } - - // return the list of peers - Ok(peer_list) + // let follows = sbot_client.get_follows().await?; + // + // // we'll use this to store the profile info for each peer who follows us + // let mut peer_list = Vec::new(); + // + // if !follows.is_empty() { + // for peer in follows.iter() { + // // trim whitespace (including newline characters) and + // // remove the inverted-commas around the id + // let key = peer.trim().replace('"', ""); + // // retrieve the profile info for the given peer + // let mut peer_info = sbot_client.get_profile_info(&key).await?; + // // insert the public key of the peer into the info hashmap + // peer_info.insert("id".to_string(), key.to_string()); + // // retrieve the profile image blob id for the given peer + // if let Some(blob_id) = peer_info.get("image") { + // // look-up the path for the image blob + // if let Ok(blob_path) = blobs::get_blob_path(blob_id) { + // // insert the image blob path of the peer into the info hashmap + // peer_info.insert("blob_path".to_string(), blob_path.to_string()); + // // check if the blob is in the blobstore + // // set a flag in the info hashmap + // match blob_is_stored_locally(&blob_path).await { + // Ok(exists) if exists => { + // peer_info.insert("blob_exists".to_string(), "true".to_string()) + // } + // _ => peer_info.insert("blob_exists".to_string(), "false".to_string()), + // }; + // } + // } + // // push profile info to peer_list vec + // peer_list.push(peer_info) + // } + // } + // + // // return the list of peers + // Ok(peer_list) }) } /// Retrieve a list of peers friended by the local public key. -pub fn get_friends_list() -> Result>, Box> { - // retrieve latest go-sbot configuration parameters +pub fn get_friends_list() -> Result>, PeachWebError> { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - let local_id = sbot_client.whoami().await?; + Err(PeachWebError::NotYetImplemented) - let follows = sbot_client.get_follows().await?; - - // we'll use this to store the profile info for each friend - let mut peer_list = Vec::new(); - - if !follows.is_empty() { - for peer in follows.iter() { - // trim whitespace (including newline characters) and - // remove the inverted-commas around the id - let peer_id = peer.trim().replace('"', ""); - // retrieve the profile info for the given peer - let mut peer_info = sbot_client.get_profile_info(&peer_id).await?; - // insert the public key of the peer into the info hashmap - peer_info.insert("id".to_string(), peer_id.to_string()); - // retrieve the profile image blob id for the given peer - if let Some(blob_id) = peer_info.get("image") { - // look-up the path for the image blob - if let Ok(blob_path) = blobs::get_blob_path(blob_id) { - // insert the image blob path of the peer into the info hashmap - peer_info.insert("blob_path".to_string(), blob_path.to_string()); - // check if the blob is in the blobstore - // set a flag in the info hashmap - match sbot::blob_is_stored_locally(&blob_path).await { - Ok(exists) if exists => { - peer_info.insert("blob_exists".to_string(), "true".to_string()) - } - _ => peer_info.insert("blob_exists".to_string(), "false".to_string()), - }; - } - } - - // check if the peer follows us (making us friends) - let follow_query = RelationshipQuery { - source: peer_id.to_string(), - dest: local_id.clone(), - }; - - // query follow state - match sbot_client.friends_is_following(follow_query).await { - Ok(following) if following == "true" => { - // only push profile info to peer_list vec if they follow us - peer_list.push(peer_info) - } - _ => (), - }; - } - } - - // return the list of peers - Ok(peer_list) + // let local_id = sbot_client.whoami().await?; + // + // let follows = sbot_client.get_follows().await?; + // + // // we'll use this to store the profile info for each friend + // let mut peer_list = Vec::new(); + // + // if !follows.is_empty() { + // for peer in follows.iter() { + // // trim whitespace (including newline characters) and + // // remove the inverted-commas around the id + // let peer_id = peer.trim().replace('"', ""); + // // retrieve the profile info for the given peer + // let mut peer_info = sbot_client.get_profile_info(&peer_id).await?; + // // insert the public key of the peer into the info hashmap + // peer_info.insert("id".to_string(), peer_id.to_string()); + // // retrieve the profile image blob id for the given peer + // if let Some(blob_id) = peer_info.get("image") { + // // look-up the path for the image blob + // if let Ok(blob_path) = blobs::get_blob_path(blob_id) { + // // insert the image blob path of the peer into the info hashmap + // peer_info.insert("blob_path".to_string(), blob_path.to_string()); + // // check if the blob is in the blobstore + // // set a flag in the info hashmap + // match sbot::blob_is_stored_locally(&blob_path).await { + // Ok(exists) if exists => { + // peer_info.insert("blob_exists".to_string(), "true".to_string()) + // } + // _ => peer_info.insert("blob_exists".to_string(), "false".to_string()), + // }; + // } + // } + // + // // query follow state + // match sbot_client.is_following(peer.id, local_id).await { + // Ok(true) => { + // // only push profile info to peer_list vec if they follow us + // peer_list.push(peer_info) + // } + // _ => (), + // }; + // } + // } + // + // // return the list of peers + // Ok(peer_list) }) } /// Retrieve the local public key (id). pub fn get_local_id() -> Result> { - // retrieve latest go-sbot configuration parameters + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { @@ -609,7 +580,7 @@ pub fn get_local_id() -> Result> { /// Publish a public post. pub fn publish_public_post(text: String) -> Result { - // retrieve latest go-sbot configuration parameters + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { @@ -618,7 +589,11 @@ pub fn publish_public_post(text: String) -> Result { .map_err(|e| e.to_string())?; debug!("Publishing a new Scuttlebutt public post"); - match sbot_client.publish_post(&text).await { + let post = json!({ + "type": "post", + "text": &text, + }); + match sbot_client.publish(post).await { Ok(_) => Ok("Published post".to_string()), Err(e) => Err(format!("Failed to publish post: {}", e)), } @@ -626,23 +601,23 @@ pub fn publish_public_post(text: String) -> Result { } /// Publish a private message. -pub fn publish_private_msg(text: String, recipients: Vec) -> Result { - // retrieve latest go-sbot configuration parameters +pub fn publish_private_msg(text: String, recipients: Vec) -> Result { + // retrieve latest solar-sbot configuration parameters let sbot_config = SbotConfig::read().ok(); task::block_on(async { let mut sbot_client = init_sbot_with_config(&sbot_config) - .await - .map_err(|e| e.to_string())?; + .await?; - debug!("Publishing a new Scuttlebutt private message"); - match sbot_client - .publish_private(text.to_string(), recipients) - .await - { - Ok(_) => Ok("Published private message".to_string()), - Err(e) => Err(format!("Failed to publish private message: {}", e)), - } + Err(PeachWebError::NotYetImplemented) + // debug!("Publishing a new Scuttlebutt private message"); + // match sbot_client + // .publish_private(text.to_string(), recipients) + // .await + // { + // Ok(_) => Ok("Published private message".to_string()), + // Err(e) => Err(format!("Failed to publish private message: {}", e)), + // } }) } @@ -696,20 +671,23 @@ pub async fn write_blob_to_store(image: BufferedFile) -> Result