Pluralsync 1.2

This commit is contained in:
lafresita 2024-01-16 13:04:25 +00:00
commit b450a1d9f6
7 changed files with 656 additions and 256 deletions

227
Cargo.lock generated
View File

@ -17,6 +17,54 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anstream"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -83,6 +131,52 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80932e03c33999b9235edb8655bc9df3204adc9887c2f95b50cb1deb9fd54253"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c0db58c659eef1c73e444d298c27322a1b52f6927d2ad470c0c0f96fa7b8fa"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.3" version = "0.9.3"
@ -117,7 +211,7 @@ dependencies = [
"libc", "libc",
"option-ext", "option-ext",
"redox_users", "redox_users",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -142,7 +236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -262,6 +356,12 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.3.3" version = "0.3.3"
@ -464,7 +564,7 @@ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -580,7 +680,7 @@ dependencies = [
"libc", "libc",
"redox_syscall", "redox_syscall",
"smallvec", "smallvec",
"windows-targets", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -609,11 +709,11 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]] [[package]]
name = "pluralsync" name = "pluralsync"
version = "1.0.0" version = "1.2.0"
dependencies = [ dependencies = [
"clap",
"dirs", "dirs",
"reqwest", "reqwest",
"rofi",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
@ -696,15 +796,6 @@ dependencies = [
"winreg", "winreg",
] ]
[[package]]
name = "rofi"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4bc8f88160318ab75508e32d837e72ecfac4270d27cdf44315495d614636df6"
dependencies = [
"thiserror",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.23"
@ -721,7 +812,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -736,7 +827,7 @@ version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
dependencies = [ dependencies = [
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -852,9 +943,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.39" version = "2.0.39"
@ -897,7 +994,7 @@ dependencies = [
"fastrand", "fastrand",
"redox_syscall", "redox_syscall",
"rustix", "rustix",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -951,7 +1048,7 @@ dependencies = [
"signal-hook-registry", "signal-hook-registry",
"socket2 0.5.5", "socket2 0.5.5",
"tokio-macros", "tokio-macros",
"windows-sys", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -1061,6 +1158,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
@ -1192,7 +1295,16 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [ dependencies = [
"windows-targets", "windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
] ]
[[package]] [[package]]
@ -1201,13 +1313,28 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc", "windows_aarch64_msvc 0.48.5",
"windows_i686_gnu", "windows_i686_gnu 0.48.5",
"windows_i686_msvc", "windows_i686_msvc 0.48.5",
"windows_x86_64_gnu", "windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm", "windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc", "windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
] ]
[[package]] [[package]]
@ -1216,42 +1343,84 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.50.0" version = "0.50.0"
@ -1259,5 +1428,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-sys", "windows-sys 0.48.0",
] ]

View File

@ -1,7 +1,8 @@
[package] [package]
name = "pluralsync" name = "pluralsync"
version = "1.0.0" version = "1.2.0"
edition = "2021" edition = "2021"
authors = ["jvnkyard@ak.lavenderfield.xyz"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -10,9 +11,14 @@ dirs = "5.0.1"
serde = { version = "1.0.192", features = ["derive"] } serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
reqwest = { version = "0.11.22", features = ["json", "multipart"] } reqwest = { version = "0.11.22", features = ["json", "multipart"] }
rofi = "0.3.0" clap = { version = "4.4.10", features = ["derive"] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
[features]
avatar = []
discord = ["avatar"]
fedi = ["avatar"]
[profile.release] [profile.release]
opt-level = 'z' opt-level = 'z'
lto = true lto = true

View File

@ -66,15 +66,15 @@ Should be compatible with Mastodon, Pleroma and Akkoma.
Requires the =avatar module= to be enabled. Will set the avatar of your fediverse account to the one selected by the avatar module. Requires the =avatar module= to be enabled. Will set the avatar of your fediverse account to the one selected by the avatar module.
* Installation * Installation
Just build with cargo and move or symlink the executable wherever is more comofortable for you. Just build with cargo and move or symlink the executable wherever is more comofortable for you. Optionally, you can add the =avatar=, =discord= and =fedi= features
#+begin_src shell #+begin_src shell
cargo build -r cargo build -r --features discord,fedi
#+end_src #+end_src
* Future * Future
Given the nature of the project as a learning exercise, there are currently a set of features and improvements I'd like to add eventually. Given the nature of the project as a learning exercise, there are currently a set of features and improvements I'd like to add eventually.
- [X] Proper error handling (What I have currently is simply a mess) - [X] Proper error handling (What I have currently is simply a mess)
- [ ] Allow the user to set which front is used in cased of mismatch between PK and SP - [X] Allow the user to set which front is used in cased of mismatch between PK and SP
- [ ] Implement clap for command inputs - [X] Implement clap for command inputs
- [ ] Actually separate the modules as actual modules - [X] Actually separate the modules as actual modules

75
src/clap_ps.rs Normal file
View File

@ -0,0 +1,75 @@
use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser)]
#[clap(arg_required_else_help = true, verbatim_doc_comment, author)]
#[command(name = "PluralSync")]
#[command(author = "jvnkyard <lafresita@protonmail.com>")]
#[command(version = "1.2")]
#[command(
help_template = "{name} Version {version} \n {author} \n {about-section} \n {usage-heading} {usage} \n \n {all-args} {tab}"
)]
#[command(about, long_about = None)]
/// Tool written in Rust to syncronize API calls between pluralkit and SimplyPlural.
/// Sets avatars for discord and fediverse.
pub struct Args {
/// Command to execute
#[command(subcommand)]
pub cmd: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
///Fetches the system member information from PluralKit and SimplyPlural
Sync,
/// Sets one or more members to the front
#[clap(arg_required_else_help = true)]
Set {
/// Members to set
members: Vec<String>,
/// Overrides the configuration file to run the discord module
#[cfg(feature = "discord")]
#[arg[short, long]]
discord: bool,
/// Overrides the configuration file to run the fedi module
#[cfg(feature = "fedi")]
#[arg[short, long]]
fedi: bool,
},
/// Refreshes the current front information
Get {
/// Selects which front takes priority in case of mismatch
#[arg(short = 'o',long)]
force_from: Option<ForceFrom>,
/// Overrides the configuration file to run the discord module
#[cfg(feature = "discord")]
#[arg[short, long]]
discord: bool,
/// Overrides the configuration file to run the fedi module
#[cfg(feature = "fedi")]
#[arg[short, long]]
fedi: bool,
},
/// Appends a member to the existing front
#[clap(arg_required_else_help = true)]
Add {
/// Members to add
members: Vec<String>,
/// Overrides the configuration file to run the discord module
#[cfg(feature = "discord")]
#[arg[short, long]]
discord: bool,
/// Overrides the configuration file to run the fedi module
#[cfg(feature = "fedi")]
#[arg[short, long]]
fedi: bool,
},
/// Displays a list with all members
Members,
}
#[derive(ValueEnum, Clone)]
pub enum ForceFrom {
SP,
PK,
None,
}

38
src/configdata.rs Normal file
View File

@ -0,0 +1,38 @@
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub pk_key: String,
pub sp_key: String,
#[cfg(feature = "avatar")]
pub avatar_module: AvatarModule,
#[cfg(feature = "discord")]
pub disc_module: DiscModule,
#[cfg(feature = "fedi")]
pub fedi_module: FediModule,
}
#[cfg(feature = "avatar")]
#[derive(Debug, Serialize, Deserialize)]
pub struct AvatarModule {
pub enabled: bool,
pub avatar_folder: String,
pub avatar_output_path: String,
}
#[cfg(feature = "discord")]
#[derive(Debug, Serialize, Deserialize)]
pub struct DiscModule {
pub enabled: bool,
pub token: String,
pub python_path: String,
pub script_path: String,
}
#[cfg(feature = "fedi")]
#[derive(Debug, Serialize, Deserialize)]
pub struct FediModule {
pub enabled: bool,
pub instance: String,
pub token: String,
}

View File

@ -1,74 +1,31 @@
use std::fs::{self, remove_file}; use std::fs;
#[cfg(feature = "avatar")]
use std::fs::remove_file;
use std::fs::create_dir; use std::fs::create_dir;
use std::path::Path; use std::path::Path;
use std::collections::HashMap; use std::collections::HashMap;
#[cfg(feature = "avatar")]
use std::process::Command; use std::process::Command;
use reqwest::RequestBuilder;
use reqwest::header::{USER_AGENT, AUTHORIZATION}; use reqwest::header::{USER_AGENT, AUTHORIZATION};
#[cfg(feature = "fedi")]
use reqwest::multipart::{Part, Form}; use reqwest::multipart::{Part, Form};
use serde::{Serialize, Deserialize}; use serde::Serialize;
use serde_json::Value; use serde_json::Value;
use dirs; use dirs;
#[derive(Debug, Serialize, Deserialize)] mod configdata;
struct Config { use configdata::*;
pk_key: String,
sp_key: String,
avatar_module: AvatarModule,
disc_module: DiscModule,
fedi_module: FediModule,
}
#[derive(Debug, Serialize, Deserialize)] mod systemdata;
struct AvatarModule { use systemdata::*;
enabled: bool,
avatar_folder: String,
avatar_output_path: String,
}
#[derive(Debug, Serialize, Deserialize)] mod clap_ps;
struct DiscModule { use clap_ps::*;
enabled: bool, use clap::Parser;
token: String,
python_path: String,
script_path: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct FediModule {
enabled: bool,
instance: String,
token: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct System {
pk_userid: String,
sp_userid: String,
members: Vec<Member>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
struct Member {
pk_id: String,
sp_id: String,
name: String,
alias: String
}
#[derive(Debug)]
struct Fronters {
sp: Vec<Member>,
pk: Vec<Member>,
}
impl Fronters {
fn new(pk: Vec<Member>, sp: Vec<Member>) -> Self {
Self {sp, pk}
}
}
const PK_URL: &str = "https://api.pluralkit.me/v2"; const PK_URL: &str = "https://api.pluralkit.me/v2";
const SP_URL: &str = "https://api.apparyllis.com/v1"; const SP_URL: &str = "https://api.apparyllis.com/v1";
@ -94,58 +51,143 @@ const EXAMPLE_JSON: &str = r#"{
} }
}"#; }"#;
const HELP_STRING: &str = r#"PluralSync
Made by Jvnko@lavenderfield
Usage:\npluralsync [COMMAND] [member1] [member2]...
Commands:
sync - Fetches the system member information from PluralKit and SimplyPlural
set - Sets one or more members to the front
get - Refreshes the current front information
add - Adds a member to the existing front
memberlist - Shows loaded member list"#;
fn main() { fn main() {
if std::env::args().len() > 1 {
let augs: Vec<String> = std::env::args().collect();
let command = &augs[1];
let config_path: String;
match dirs::config_dir() { let cli = Args::parse();
Some(x) => {
config_path = format!("{}/pluralsync", x.display());
match command.as_str() {
"sync" => {
let _ = sync(config_path);
},
"set" => {
if std::env::args().len() > 2 {
let _ = set_member(config_path, &augs[2..]).map_err(|e| println!("{e}"));
} else { let config_path = match dirs::config_dir() {
//set_empty(config_path); Some(d) => format!("{}/pluralsync", d.display()),
} None => {
}, println!("Could not fetch the config directory");
"add" => { return ();
if std::env::args().len() > 2 {
let _ = add_member(config_path, &augs[2..]).map_err(|e| println!("{e}"));
} else {
//add_empty(config_path);
}
}
"get" => {
let _ = get(config_path);
},
"memberlist" => memberlist(config_path),
&_ => println!("{}", HELP_STRING),
}
},
None => println!("Something went wrong")
} }
} else { };
println!("{}", HELP_STRING);
let mut res: Result<(), &str> = Ok(());
match cli.cmd {
Commands::Sync => {
res = sync(config_path);
},
// SET MEMBER
#[cfg(all(feature = "discord", feature = "fedi"))]
Commands::Set { members, discord, fedi } => {
res = set_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), discord, fedi);
},
#[cfg(all(feature = "discord", not(feature = "fedi")))]
Commands::Set { members, discord } => {
res = set_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), discord, false);
},
#[cfg(all(not(feature = "discord"), feature = "fedi"))]
Commands::Set { members, fedi} => {
res = set_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), false, fedi);
},
#[cfg(all(not(feature = "discord"), not(feature = "fedi")))]
Commands::Set { members } => {
res = set_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), false, false);
},
// ADD MEMBER
#[cfg(all(feature = "discord", feature = "fedi"))]
Commands::Add { members, discord, fedi } => {
res = add_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), discord, fedi);
},
#[cfg(all(feature = "discord", not(feature = "fedi")))]
Commands::Add { members, discord } => {
res = add_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), discord, false);
},
#[cfg(all(not(feature = "discord"), feature = "fedi"))]
Commands::Add { members, fedi} => {
res = add_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), false, fedi);
},
#[cfg(all(not(feature = "discord"), not(feature = "fedi")))]
Commands::Add { members } => {
res = add_member(config_path.clone(), members);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), false, false);
},
// Get MEMBER
#[cfg(all(feature = "discord", feature = "fedi"))]
Commands::Get { force_from, discord, fedi } => {
let ff = match force_from {
Some(x) => x,
None => ForceFrom::None,
};
let _ = get(config_path.clone(), ff);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), discord, fedi);
},
#[cfg(all(feature = "discord", not(feature = "fedi")))]
Commands::Get { force_from, discord } => {
let ff = match force_from {
Some(x) => x,
None => ForceFrom::None,
};
let _ = get(config_path.clone(), ff);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), discord, false);
},
#[cfg(all(not(feature = "discord"), feature = "fedi"))]
Commands::Get { force_from, fedi} => {
let ff = match force_from {
Some(x) => x,
None => ForceFrom::None,
};
let _ = get(config_path.clone(), ff);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), false, fedi);
},
#[cfg(all(not(feature = "discord"), not(feature = "fedi")))]
Commands::Get { force_from } => {
let ff = match force_from {
Some(x) => x,
None => ForceFrom::None,
};
let _ = get(config_path.clone(), ff);
#[cfg(feature = "avatar")]
let _ = update_avatars(config_path.clone(), false, false);
},
Commands::Members => {
res = memberlist(config_path);
},
}
match res {
Ok(_) => (),
Err(e) => println!("{}", e),
} }
} }
@ -200,14 +242,7 @@ fn sync(config_path: String) -> Result<(), &'static str> {
Ok(()) Ok(())
} }
/* fn set_member(config_path: String, tf_members: Vec<String>) -> Result<(), &'static str> {
TODO fn set_empty(config_path: String) {
TODO let config = load_json(format!("{}/config.json", config_path));
TODO let system = get_system(&config_path);
TODO }
*/
fn set_member(config_path: String, tf_members: &[String]) -> Result<(), &'static str> {
let config: Config = match get_config(&config_path) { let config: Config = match get_config(&config_path) {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(e) Err(e) => return Err(e)
@ -216,7 +251,7 @@ fn set_member(config_path: String, tf_members: &[String]) -> Result<(), &'static
let system: System = get_system(&config_path); let system: System = get_system(&config_path);
let mut to_front: Vec<Member> = Vec::new(); let mut to_front: Vec<Member> = Vec::new();
for member in tf_members { for member in &tf_members {
for mem in &system.members { for mem in &system.members {
if mem.name.to_lowercase() == member.to_lowercase() || mem.alias.to_lowercase() == member.to_lowercase() { if mem.name.to_lowercase() == member.to_lowercase() || mem.alias.to_lowercase() == member.to_lowercase() {
println!("Member {member} found"); println!("Member {member} found");
@ -226,22 +261,20 @@ fn set_member(config_path: String, tf_members: &[String]) -> Result<(), &'static
} }
} }
} }
if to_front.len() != 0 { if to_front.len() == tf_members.len() {
let fronters = get_fronters(&config.pk_key, &config.sp_key, &system); let fronters = get_fronters(&config.pk_key, &config.sp_key, &system, ForceFrom::None);
pk_set_fronters(&config.pk_key, &system, &to_front, &fronters); pk_set_fronters(&config.pk_key, &system, &to_front, &fronters);
sp_set_fronters(&config.sp_key, &to_front, &fronters); sp_set_fronters(&config.sp_key, &to_front, &fronters);
let _ = get(config_path);
} else { } else {
println!("No members found. Known members:\n--------------------------"); println!("One or more members were not found. Known members:\n--------------------------");
memberlist(config_path); let _ = memberlist(config_path);
println!("--------------------------\nIf a member is missing from the system try running \"pluralsync sync\" to refresh the local database"); println!("--------------------------\nIf a member is missing from the system try running \"pluralsync sync\" to refresh the local database");
} }
Ok(()) Ok(())
} }
fn add_member(config_path: String, tf_members: &[String]) -> Result<(), &'static str> { fn add_member(config_path: String, tf_members: Vec<String>) -> Result<(), &'static str> {
let config: Config = match get_config(&config_path) { let config: Config = match get_config(&config_path) {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(e) Err(e) => return Err(e)
@ -250,7 +283,7 @@ fn add_member(config_path: String, tf_members: &[String]) -> Result<(), &'static
let system: System = get_system(&config_path); let system: System = get_system(&config_path);
let mut to_front: Vec<Member> = Vec::new(); let mut to_front: Vec<Member> = Vec::new();
for member in tf_members { for member in &tf_members {
for mem in &system.members { for mem in &system.members {
if mem.name.to_lowercase() == member.to_lowercase() || mem.alias.to_lowercase() == member.to_lowercase() { if mem.name.to_lowercase() == member.to_lowercase() || mem.alias.to_lowercase() == member.to_lowercase() {
to_front.push(mem.clone()); to_front.push(mem.clone());
@ -258,8 +291,8 @@ fn add_member(config_path: String, tf_members: &[String]) -> Result<(), &'static
} }
} }
} }
if to_front.len() != 0 { if to_front.len() == tf_members.len() {
let fronters = get_fronters(&config.pk_key, &config.sp_key, &system); let fronters = get_fronters(&config.pk_key, &config.sp_key, &system, ForceFrom::None);
let mut aux: Vec<Member> = Vec::new(); let mut aux: Vec<Member> = Vec::new();
aux.append(&mut fronters.pk.clone()); aux.append(&mut fronters.pk.clone());
@ -269,16 +302,16 @@ fn add_member(config_path: String, tf_members: &[String]) -> Result<(), &'static
pk_set_fronters(&config.pk_key, &system, &to_front, &fronters); pk_set_fronters(&config.pk_key, &system, &to_front, &fronters);
sp_set_fronters(&config.sp_key, &to_front, &fronters); sp_set_fronters(&config.sp_key, &to_front, &fronters);
let _ = get(config_path); let _ = get(config_path, ForceFrom::None);
} else { } else {
println!("No members found. Known members:\n--------------------------"); println!("One or more members were not found. Known members:\n--------------------------");
memberlist(config_path); let _ = memberlist(config_path);
println!("--------------------------\nIf a member is missing from the system try running \"pluralsync sync\" to refresh the local database"); println!("--------------------------\nIf a member is missing from the system try running \"pluralsync sync\" to refresh the local database");
} }
Ok(()) Ok(())
} }
fn memberlist(config_path: String) { fn memberlist(config_path: String) -> Result<(), &'static str> {
let sys = get_system(&config_path); let sys = get_system(&config_path);
for mem in sys.members { for mem in sys.members {
@ -289,16 +322,18 @@ fn memberlist(config_path: String) {
} }
} }
Ok(())
} }
fn get(config_path: String) -> Result<(), &'static str> { fn get(config_path: String, ff: ForceFrom) -> Result<Vec<String>, &'static str> {
let config: Config = match get_config(&config_path) { let config: Config = match get_config(&config_path) {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(e) Err(e) => return Err(e)
}; };
let sys = get_system(&config_path); let sys = get_system(&config_path);
let f = get_fronters(&config.pk_key, &config.sp_key, &sys); let f = get_fronters(&config.pk_key, &config.sp_key, &sys, ff);
let mut names = Vec::new(); let mut names = Vec::new();
for m in &f.pk { for m in &f.pk {
names.push(String::from(&m.name)); names.push(String::from(&m.name));
@ -307,6 +342,37 @@ fn get(config_path: String) -> Result<(), &'static str> {
println!("Currently fronting: {}", fronters); println!("Currently fronting: {}", fronters);
let _ = fs::write(format!("{}/.front", config_path), fronters); let _ = fs::write(format!("{}/.front", config_path), fronters);
Ok(names)
}
#[cfg(feature = "avatar")]
#[allow(unused_variables)]
fn update_avatars(config_path: String, discord: bool, fedi: bool) -> Result<(), &'static str>{
#[allow(unused_mut)]
let mut config: Config = match get_config(&config_path) {
Ok(c) => c,
Err(e) => return Err(e)
};
let names = get(config_path, ForceFrom::None).unwrap();
#[cfg(feature = "avatar")]
avatar_module(&config, &names);
#[cfg(feature = "discord")] {
config.disc_module.enabled |= discord;
discord_module(&config);
}
#[cfg(feature = "fedi")] {
config.fedi_module.enabled |= fedi;
fedi_module(&config);
}
Ok(())
}
#[cfg(feature = "avatar")]
fn avatar_module(config: &Config, names: &Vec<String>) {
if config.avatar_module.enabled { if config.avatar_module.enabled {
let avatarnames = names.join("").to_lowercase() + ".png"; let avatarnames = names.join("").to_lowercase() + ".png";
@ -317,40 +383,57 @@ fn get(config_path: String) -> Result<(), &'static str> {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
let cmdaug = format!("copy {}\\{} {}", &config.avatar_module.avatar_folder, avatarnames, &config.avatar_module.avatar_output_path); let cmdaug = format!("copy {}\\{} {}", &config.avatar_module.avatar_folder, avatarnames, &config.avatar_module.avatar_output_path);
Command::new("cmd").args(["/C", &cmdaug]).output().expect("Avatar module error"); Command::new("cmd").args(["/C", &cmdaug]).output().expect("Avatar module error");
if config.disc_module.enabled {
let mut c = Command::new("cmd").args(["/C", format!("{} {}", &config.disc_module.python_path, &config.disc_module.script_path).as_str()]).spawn().expect("Discord module error");
let _ = c.wait().expect("Error");
}
} else { } else {
Command::new("sh").arg("-c").arg(format!("cp {}/{} {}", &config.avatar_module.avatar_folder, avatarnames, &config.avatar_module.avatar_output_path)).output().expect("Avatar module error"); Command::new("sh").arg("-c").arg(format!("cp {}/{} {}", &config.avatar_module.avatar_folder, avatarnames, &config.avatar_module.avatar_output_path)).output().expect("Avatar module error");
if config.disc_module.enabled {
let mut c = Command::new("sh").arg("-c").arg(format!("{} {}", &config.disc_module.python_path, &config.disc_module.script_path)).spawn().expect("Discord module error");
let _ = c.wait().expect("Error");
}
if config.fedi_module.enabled {
let _ = http_patch_request_fedi(config.fedi_module.instance + "/api/v1/accounts/update_credentials", format!("Bearer {}", &config.fedi_module.token).as_str(), config.avatar_module.avatar_output_path);
}
} }
} }
Ok(()) }
#[cfg(feature = "discord")]
fn discord_module(config: &Config) {
if config.disc_module.enabled {
if cfg!(target_os = "windows") {
let mut c = Command::new("cmd").args(["/C", format!("{} {}", &config.disc_module.python_path, &config.disc_module.script_path).as_str()]).spawn().expect("Discord module error");
let _ = c.wait().expect("Error");
} else {
let mut c = Command::new("sh").arg("-c").arg(format!("{} {}", &config.disc_module.python_path, &config.disc_module.script_path)).spawn().expect("Discord module error");
let _ = c.wait().expect("Error");
}
}
}
#[cfg(feature = "fedi")]
fn fedi_module(config: &Config) {
if config.fedi_module.enabled {
let client = reqwest::Client::new();
let form = Form::new().part("avatar", Part::bytes(fs::read(config.avatar_module.avatar_output_path.clone()).unwrap()).file_name("face.png").mime_str("image/png").unwrap());
let rb = client
.patch(config.fedi_module.instance.clone() + "/api/v1/accounts/update_credentials")
.multipart(form)
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, format!("Bearer {}", &config.fedi_module.token).as_str());
match http_request(rb) {
Ok(_) => (),
Err(e) => println!("{}", e.to_string()),
}
}
} }
fn pk_get_system(key: &str) -> Value { fn pk_get_system(key: &str) -> Value {
let url = format!("{}/systems/@me", PK_URL); let url = format!("{}/systems/@me", PK_URL);
let res = http_get_request(url,key); let res = http_get(url,key);
return serde_json::from_str(&res.unwrap()).unwrap(); return serde_json::from_str(&res.unwrap()).unwrap();
} }
fn pk_get_members(key: &str, sysid: &str) -> Vec<Value> { fn pk_get_members(key: &str, sysid: &str) -> Vec<Value> {
let url = format!("{}/systems/{}/members", PK_URL, sysid); let url = format!("{}/systems/{}/members", PK_URL, sysid);
let res = http_get_request(url,key); let res = http_get(url,key);
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap(); let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
return datas; return datas;
@ -359,7 +442,7 @@ fn pk_get_members(key: &str, sysid: &str) -> Vec<Value> {
fn pk_get_fronters(key: &str, sys: &System) -> Vec<Member> { fn pk_get_fronters(key: &str, sys: &System) -> Vec<Member> {
let url = format!("{}/systems/{}/fronters", PK_URL, sys.pk_userid); let url = format!("{}/systems/{}/fronters", PK_URL, sys.pk_userid);
let res = http_get_request(url,key); let res = http_get(url,key);
let data: Value = serde_json::from_str(&res.unwrap()).unwrap(); let data: Value = serde_json::from_str(&res.unwrap()).unwrap();
let memberdata = &data["members"].as_array(); let memberdata = &data["members"].as_array();
@ -385,9 +468,23 @@ fn pk_set_fronters(key: &str, sys: &System, to_front: &Vec<Member>, fronters: &F
for tf in to_front { for tf in to_front {
frontcodes.push(String::from(&tf.pk_id)); frontcodes.push(String::from(&tf.pk_id));
} }
let mut body: HashMap<&str, Vec<String>> = HashMap::new(); let mut body: HashMap<&str, Vec<String>> = HashMap::new();
body.insert("members", frontcodes); body.insert("members", frontcodes);
let _ = http_post_request(url, key, &body);
let client = reqwest::Client::new();
let rb = client
.post(url)
.json(&body)
.header("content-type", "application/json; charset=utf-8")
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key);
match http_request(rb) {
Ok(_) => (),
Err(e) => println!("{}", e.to_string()),
}
} else { } else {
println!("Members already fonting"); println!("Members already fonting");
} }
@ -397,7 +494,7 @@ fn pk_set_fronters(key: &str, sys: &System, to_front: &Vec<Member>, fronters: &F
fn sp_get_userid(key: &str) -> String { fn sp_get_userid(key: &str) -> String {
let url = format!("{}/me", SP_URL); let url = format!("{}/me", SP_URL);
let res = http_get_request(url,key); let res = http_get(url,key);
let json_res : Value = serde_json::from_str(&res.unwrap()).unwrap(); let json_res : Value = serde_json::from_str(&res.unwrap()).unwrap();
return json_res["id"].as_str().unwrap().to_string(); return json_res["id"].as_str().unwrap().to_string();
} }
@ -405,7 +502,7 @@ fn sp_get_userid(key: &str) -> String {
fn sp_get_memberids(key: &str, system_id: &str) -> HashMap<String, String> { fn sp_get_memberids(key: &str, system_id: &str) -> HashMap<String, String> {
let url = format!("{}/members/{}", SP_URL, system_id); let url = format!("{}/members/{}", SP_URL, system_id);
let res = http_get_request(url,key); let res = http_get(url,key);
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap(); let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
let mut sp_memberdata: HashMap<String, String> = HashMap::new(); let mut sp_memberdata: HashMap<String, String> = HashMap::new();
@ -432,7 +529,7 @@ fn get_sp_id(mem: &Member, ids: &HashMap<String, String>) -> String {
fn sp_get_fronters(key: &str, sys: &System) -> Vec<Member> { fn sp_get_fronters(key: &str, sys: &System) -> Vec<Member> {
let url = format!("{}/fronters", SP_URL); let url = format!("{}/fronters", SP_URL);
let res = http_get_request(url,key); let res = http_get(url,key);
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap(); let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
let mut members = Vec::new(); let mut members = Vec::new();
@ -451,7 +548,7 @@ fn sp_get_fronters(key: &str, sys: &System) -> Vec<Member> {
fn sp_get_frontids(key: &str, to_id: &Member) -> String { fn sp_get_frontids(key: &str, to_id: &Member) -> String {
let url = format!("{}/fronters", SP_URL); let url = format!("{}/fronters", SP_URL);
let res = http_get_request(url,key); let res = http_get(url,key);
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap(); let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
for data in datas { for data in datas {
@ -491,7 +588,19 @@ fn sp_set_fronters(key: &str, to_front: &Vec<Member>, fronters: &Fronters) {
let body = serde_json::to_string(&rem).expect("Error"); let body = serde_json::to_string(&rem).expect("Error");
let _ = http_patch_request(url, key, body);
let client = reqwest::Client::new();
let rb = client
.patch(url)
.body(body)
.header("content-type", "application/json; charset=utf-8")
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key);
match http_request(rb) {
Ok(_) => (),
Err(e) => println!("{}", e.to_string()),
}
} }
} }
@ -518,7 +627,18 @@ fn sp_set_fronters(key: &str, to_front: &Vec<Member>, fronters: &Fronters) {
let body = serde_json::to_string(&rem).expect("Error"); let body = serde_json::to_string(&rem).expect("Error");
let _ = http_post_request_st(url, key, body); let client = reqwest::Client::new();
let rb = client
.post(url)
.body(body)
.header("content-type", "application/json; charset=utf-8")
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key);
match http_request(rb) {
Ok(_) => (),
Err(e) => println!("{}", e.to_string()),
}
} }
} }
} }
@ -571,84 +691,48 @@ fn get_system(config_path: &str) -> System {
} }
fn get_fronters(pk_key: &str, sp_key: &str, sys: &System) -> Fronters { fn get_fronters(pk_key: &str, sp_key: &str, sys: &System, ff: ForceFrom) -> Fronters {
let fronters = Fronters::new( let mut fronters = Fronters::new(
pk_get_fronters(pk_key, sys), pk_get_fronters(pk_key, sys),
sp_get_fronters(sp_key, sys) sp_get_fronters(sp_key, sys)
); );
// if fronters.pk != fronters.sp { if fronters.pk != fronters.sp {
// fronters.sp = fronters.pk.clone(); match ff {
// } ForceFrom::PK => {
fronters.sp = fronters.pk.clone()
}
ForceFrom::SP => {
fronters.pk = fronters.sp.clone()
}
ForceFrom::None => {
}
}
}
return fronters; return fronters;
} }
#[tokio::main] #[tokio::main]
async fn http_get_request(url: String, key: &str) -> Result<String, Box<dyn std::error::Error>> { async fn http_get(url: String, key: &str) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let res = client let rb = client
.get(url) .get(url)
.header(USER_AGENT, "Pluralsync") .header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key) .header(AUTHORIZATION, key);
.send() let res = rb.send()
.await?
.text()
.await?;
Ok(res)
}
#[tokio::main]
async fn http_request(rb: RequestBuilder) -> Result<String, Box<dyn std::error::Error>> {
let res = rb.send()
.await? .await?
.text() .text()
.await?; .await?;
Ok(res) Ok(res)
} }
#[tokio::main]
async fn http_post_request(url: String, key: &str, body: &HashMap<&str, Vec<String>>) -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let _= client
.post(url)
.json(body)
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key)
.send()
.await?;
Ok(())
}
#[tokio::main]
async fn http_post_request_st(url: String, key: &str, body: String) -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let c = client
.post(url)
.body(body)
.header("content-type", "application/json; charset=utf-8")
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key);
let _res = c.send()
.await?;
Ok(())
}
#[tokio::main]
async fn http_patch_request(url: String, key: &str, body: String ) -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let c = client
.patch(url)
.body(body)
.header("content-type", "application/json; charset=utf-8")
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key);
let _res = c.send()
.await?;
Ok(())
}
#[tokio::main]
async fn http_patch_request_fedi(url: String, key: &str, file_path: String ) -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let form = Form::new().part("avatar", Part::bytes(fs::read(file_path).unwrap()).file_name("face.png").mime_str("image/png").unwrap());
let c = client
.patch(url)
.multipart(form)
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key);
let _res = c.send()
.await?;
Ok(())
}

28
src/systemdata.rs Normal file
View File

@ -0,0 +1,28 @@
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct System {
pub pk_userid: String,
pub sp_userid: String,
pub members: Vec<Member>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Member {
pub pk_id: String,
pub sp_id: String,
pub name: String,
pub alias: String
}
#[derive(Debug)]
pub struct Fronters {
pub sp: Vec<Member>,
pub pk: Vec<Member>,
}
impl Fronters {
pub fn new(pk: Vec<Member>, sp: Vec<Member>) -> Self {
Self {sp, pk}
}
}