pluralsync/src/main.rs

622 lines
18 KiB
Rust
Raw Normal View History

2023-11-26 09:20:09 +00:00
use std::fs::{self, remove_file};
2023-11-21 13:20:21 +00:00
use std::fs::create_dir;
2023-11-20 15:39:40 +00:00
use std::path::Path;
2023-11-21 13:20:21 +00:00
use std::collections::HashMap;
2023-11-26 09:20:09 +00:00
use std::process::Command;
2023-11-21 13:20:21 +00:00
2023-11-20 15:39:40 +00:00
use reqwest::header::{USER_AGENT, AUTHORIZATION};
2023-11-21 13:20:21 +00:00
2023-11-20 15:39:40 +00:00
use serde::{Serialize, Deserialize};
use serde_json::Value;
2023-11-21 13:20:21 +00:00
2023-11-20 15:39:40 +00:00
use dirs;
2023-11-26 09:20:09 +00:00
#[derive(Debug, Serialize, Deserialize)]
struct Config {
pk_key: String,
sp_key: String,
pfp_module: PfpModule,
disc_module: DiscModule
}
#[derive(Debug, Serialize, Deserialize)]
struct PfpModule {
enabled: bool,
pfp_folder: String,
pfp_output_path: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct DiscModule {
enabled: bool,
token: String,
python_path: String,
script_path: String,
}
2023-11-24 14:01:56 +00:00
#[derive(Debug, Serialize, Deserialize, Clone)]
2023-11-20 15:39:40 +00:00
struct System {
pk_userid: String,
sp_userid: String,
members: Vec<Member>,
}
2023-11-24 14:01:56 +00:00
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2023-11-20 15:39:40 +00:00
struct Member {
pk_id: String,
sp_id: String,
name: String,
alias: String
}
2023-11-24 14:01:56 +00:00
#[derive(Debug)]
struct Fronters {
sp: Vec<Member>,
pk: Vec<Member>,
}
impl Fronters {
fn new(pk: Vec<Member>, sp: Vec<Member>) -> Self {
Self {sp, pk}
}
}
2023-11-27 07:42:45 +00:00
const PK_URL: &str = "https://api.pluralkit.me/v2";
const SP_URL: &str = "https://api.apparyllis.com/v1";
const EXAMPLE_JSON: &str = r#"{
"pk_key": "// Pluralkit token",
"sp_key": "// Simplplural token",
"pfp_module": {
"enabled": false,
"pfp_folder": "// Folder to grab profile pictures, they follow they member1member2.png format",
"pfp_output_path": "// Path for the copied selected pfp"
},
"disc_module": {
"enabled": false,
"token": "// Discord user token",
"python_path": "// Path of the python executable",
"script_path": "// Path of the pfp changer python script"
}
}"#;
const HELP_STRING: &str = r#"PluralSync
2023-11-24 14:01:56 +00:00
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"#;
2023-11-27 07:42:45 +00:00
fn main() {
2023-11-20 15:39:40 +00:00
if std::env::args().len() > 1 {
2023-11-22 12:11:49 +00:00
let augs: Vec<String> = std::env::args().collect();
let command = &augs[1];
2023-11-20 15:39:40 +00:00
let config_path: String;
2023-11-24 14:01:56 +00:00
2023-11-20 15:39:40 +00:00
match dirs::config_dir() {
Some(x) => {
2023-11-24 14:01:56 +00:00
config_path = format!("{}/pluralsync", x.display());
2023-11-20 15:39:40 +00:00
match command.as_str() {
2023-11-21 13:20:21 +00:00
"sync" => {
let _ = sync(config_path);
},
2023-11-20 15:39:40 +00:00
"set" => {
if std::env::args().len() > 2 {
2023-11-24 14:01:56 +00:00
let _ = set_member(config_path, &augs[2..]).map_err(|e| println!("{e}"));
2023-11-20 15:39:40 +00:00
} else {
2023-11-21 13:20:21 +00:00
//set_empty(config_path);
2023-11-20 15:39:40 +00:00
}
},
2023-11-23 13:55:30 +00:00
"add" => {
if std::env::args().len() > 2 {
2023-11-24 14:01:56 +00:00
let _ = add_member(config_path, &augs[2..]).map_err(|e| println!("{e}"));
2023-11-23 13:55:30 +00:00
} else {
//add_empty(config_path);
}
}
2023-11-26 09:20:09 +00:00
"get" => {
let _ = get(config_path);
},
2023-11-22 10:24:05 +00:00
"memberlist" => memberlist(config_path),
2023-11-27 07:42:45 +00:00
&_ => println!("{}", HELP_STRING),
2023-11-20 15:39:40 +00:00
}
},
None => println!("Something went wrong")
}
} else {
2023-11-27 07:42:45 +00:00
println!("{}", HELP_STRING);
2023-11-20 15:39:40 +00:00
}
}
2023-11-26 09:20:09 +00:00
fn sync(config_path: String) -> Result<(), &'static str> {
2023-11-20 15:39:40 +00:00
// Get config
2023-11-26 09:20:09 +00:00
let config: Config = match get_config(&config_path) {
Ok(c) => c,
Err(e) => return Err(e)
};
2023-11-20 15:39:40 +00:00
// Get Pluralkit system id
2023-11-26 09:20:09 +00:00
let pk_sys = pk_get_system(&config.pk_key);
2023-11-20 15:39:40 +00:00
let pk_sysid = pk_sys["id"].as_str().unwrap();
// Get Simplyplural user id
2023-11-26 09:20:09 +00:00
let sp_user_id = sp_get_userid(&config.sp_key);
2023-11-20 15:39:40 +00:00
// Get Simplyplural member ids
2023-11-26 09:20:09 +00:00
let sp_member_ids = sp_get_memberids(&config.sp_key, &sp_user_id);
2023-11-20 15:39:40 +00:00
// get members
2023-11-26 09:20:09 +00:00
let pk_members = pk_get_members(&config.pk_key, pk_sysid);
2023-11-20 15:39:40 +00:00
let mut members: Vec<Member> = Vec::new();
for member in pk_members {
let mut m = Member {
pk_id: member["id"].as_str().unwrap().to_string(),
sp_id: String::new(),
name: member["name"].as_str().unwrap().to_string(),
alias: String::new()
};
if member["display_name"].as_str() != None {
m.alias = member["display_name"].as_str().unwrap().to_string();
} else {
m.alias = String::from(&m.name);
}
m.sp_id = get_sp_id(&m, &sp_member_ids);
members.push(m);
}
let sys = System {
pk_userid: pk_sysid.to_string(),
sp_userid: sp_user_id,
members: members.clone(),
};
let json = serde_json::to_string(&sys);
let _ = fs::write(format!("{}/system.json", config_path), &json.unwrap());
2023-11-21 13:20:21 +00:00
Ok(())
2023-11-20 15:39:40 +00:00
}
2023-11-21 15:03:51 +00:00
/*
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 }
*/
2023-11-22 12:11:49 +00:00
fn set_member(config_path: String, tf_members: &[String]) -> Result<(), &'static str> {
2023-11-26 09:20:09 +00:00
let config: Config = match get_config(&config_path) {
Ok(c) => c,
Err(e) => return Err(e)
};
2023-11-21 15:03:51 +00:00
let system: System = get_system(&config_path);
2023-11-22 12:11:49 +00:00
let mut to_front: Vec<Member> = Vec::new();
for member in tf_members {
for mem in &system.members {
if mem.name.to_lowercase() == member.to_lowercase() || mem.alias.to_lowercase() == member.to_lowercase() {
println!("Member {member} found");
to_front.push(mem.clone());
break;
}
2023-11-21 15:03:51 +00:00
}
}
2023-11-22 12:11:49 +00:00
if to_front.len() != 0 {
2023-11-26 09:20:09 +00:00
let fronters = get_fronters(&config.pk_key, &config.sp_key, &system);
2023-11-26 09:20:09 +00:00
pk_set_fronters(&config.pk_key, &system, &to_front, &fronters);
sp_set_fronters(&config.sp_key, &to_front, &fronters);
2023-11-26 09:20:09 +00:00
let _ = get(config_path);
} else {
println!("No members found. Known members:\n--------------------------");
memberlist(config_path);
2023-11-24 14:01:56 +00:00
println!("--------------------------\nIf a member is missing from the system try running \"pluralsync sync\" to refresh the local database");
2023-11-23 13:55:30 +00:00
}
Ok(())
}
fn add_member(config_path: String, tf_members: &[String]) -> Result<(), &'static str> {
2023-11-26 09:20:09 +00:00
let config: Config = match get_config(&config_path) {
Ok(c) => c,
Err(e) => return Err(e)
};
2023-11-23 13:55:30 +00:00
let system: System = get_system(&config_path);
let mut to_front: Vec<Member> = Vec::new();
for member in tf_members {
for mem in &system.members {
if mem.name.to_lowercase() == member.to_lowercase() || mem.alias.to_lowercase() == member.to_lowercase() {
to_front.push(mem.clone());
break;
}
}
}
if to_front.len() != 0 {
2023-11-26 09:20:09 +00:00
let fronters = get_fronters(&config.pk_key, &config.sp_key, &system);
2023-11-23 13:55:30 +00:00
let mut aux: Vec<Member> = Vec::new();
2023-11-24 14:01:56 +00:00
aux.append(&mut fronters.pk.clone());
2023-11-23 13:55:30 +00:00
aux.append(&mut to_front);
to_front = aux;
2023-11-26 09:20:09 +00:00
pk_set_fronters(&config.pk_key, &system, &to_front, &fronters);
sp_set_fronters(&config.sp_key, &to_front, &fronters);
2023-11-26 09:20:09 +00:00
let _ = get(config_path);
} else {
println!("No members found. Known members:\n--------------------------");
memberlist(config_path);
2023-11-24 14:01:56 +00:00
println!("--------------------------\nIf a member is missing from the system try running \"pluralsync sync\" to refresh the local database");
2023-11-21 15:03:51 +00:00
}
2023-11-22 12:11:49 +00:00
Ok(())
2023-11-22 10:24:05 +00:00
}
fn memberlist(config_path: String) {
let sys = get_system(&config_path);
for mem in sys.members {
2023-11-22 12:11:49 +00:00
if mem.name != mem.alias {
println!("{} / {}", mem.name, mem.alias);
} else {
println!("{}", mem.name);
}
2023-11-22 10:24:05 +00:00
}
2023-11-21 15:03:51 +00:00
}
2023-11-22 12:56:08 +00:00
2023-11-26 09:20:09 +00:00
fn get(config_path: String) -> Result<(), &'static str> {
let config: Config = match get_config(&config_path) {
Ok(c) => c,
Err(e) => return Err(e)
};
2023-11-22 12:56:08 +00:00
let sys = get_system(&config_path);
2023-11-26 09:20:09 +00:00
let f = get_fronters(&config.pk_key, &config.sp_key, &sys);
2023-11-22 12:56:08 +00:00
let mut names = Vec::new();
2023-11-26 09:20:09 +00:00
for m in &f.sp {
2023-11-22 12:56:08 +00:00
names.push(String::from(&m.name));
}
2023-11-22 12:59:39 +00:00
let fronters = names.join(" || ");
2023-11-22 12:56:08 +00:00
println!("Currently fronting: {}", fronters);
let _ = fs::write(format!("{}/.front", config_path), fronters);
2023-11-26 09:20:09 +00:00
if config.pfp_module.enabled {
let pfpnames = names.join("").to_lowercase() + ".png";
if Path::new(&config.pfp_module.pfp_output_path).exists() {
let _ = remove_file(&config.pfp_module.pfp_output_path);
}
2023-11-27 07:39:41 +00:00
if cfg!(target_os = "windows") {
2023-11-27 08:05:56 +00:00
Command::new("cmd").args(["/C", format!("copy {}/{} {}", &config.pfp_module.pfp_folder, pfpnames, &config.pfp_module.pfp_output_path).as_str()]).output().expect("PFP module error");
2023-11-26 09:20:09 +00:00
2023-11-27 07:39:41 +00:00
if config.disc_module.enabled {
2023-11-27 08:05:56 +00:00
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");
2023-11-27 07:39:41 +00:00
let _ = c.wait().expect("Error");
}
} else {
Command::new("sh").arg("-c").arg(format!("cp {}/{} {}", &config.pfp_module.pfp_folder, pfpnames, &config.pfp_module.pfp_output_path)).output().expect("PFP 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");
}
2023-11-26 09:20:09 +00:00
}
}
Ok(())
2023-11-22 12:56:08 +00:00
}
2023-11-20 15:39:40 +00:00
2023-11-21 11:47:07 +00:00
fn pk_get_system(key: &str) -> Value {
let url = format!("{}/systems/@me", PK_URL);
2023-11-20 15:39:40 +00:00
2023-11-21 13:20:21 +00:00
let res = http_get_request(url,key);
2023-11-21 11:47:07 +00:00
return serde_json::from_str(&res.unwrap()).unwrap();
}
2023-11-20 15:39:40 +00:00
2023-11-21 11:47:07 +00:00
fn pk_get_members(key: &str, sysid: &str) -> Vec<Value> {
let url = format!("{}/systems/{}/members", PK_URL, sysid);
2023-11-20 15:39:40 +00:00
2023-11-21 13:20:21 +00:00
let res = http_get_request(url,key);
2023-11-21 11:47:07 +00:00
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
2023-11-20 15:39:40 +00:00
2023-11-21 11:47:07 +00:00
return datas;
2023-11-20 15:39:40 +00:00
}
2023-11-21 14:38:25 +00:00
2023-11-22 12:56:08 +00:00
fn pk_get_fronters(key: &str, sys: &System) -> Vec<Member> {
let url = format!("{}/systems/{}/fronters", PK_URL, sys.pk_userid);
2023-11-21 14:38:25 +00:00
let res = http_get_request(url,key);
2023-11-22 12:56:08 +00:00
let data: Value = serde_json::from_str(&res.unwrap()).unwrap();
let memberdata = &data["members"].as_array();
2023-11-21 14:38:25 +00:00
2023-11-22 12:11:49 +00:00
let mut members: Vec<Member> = Vec::new();
2023-11-22 12:56:08 +00:00
for member in memberdata {
for m in member.into_iter() {
for dbmem in &sys.members {
if m["name"].as_str().unwrap() == dbmem.name {
members.push(dbmem.clone());
}
2023-11-22 12:11:49 +00:00
}
2023-11-21 14:38:25 +00:00
}
2023-11-22 12:11:49 +00:00
}
2023-11-22 12:56:08 +00:00
return members;
2023-11-22 12:11:49 +00:00
}
2023-11-22 12:56:08 +00:00
2023-11-24 14:01:56 +00:00
fn pk_set_fronters(key: &str, sys: &System, to_front: &Vec<Member>, fronters: &Fronters) {
2023-11-22 12:56:08 +00:00
let url = format!("{}/systems/{}/switches", PK_URL, sys.pk_userid);
2023-11-24 14:01:56 +00:00
if to_front != &fronters.pk {
2023-11-22 12:56:08 +00:00
let mut frontcodes = Vec::new();
for tf in to_front {
2023-11-23 13:55:30 +00:00
frontcodes.push(String::from(&tf.pk_id));
2023-11-22 12:56:08 +00:00
}
let mut body: HashMap<&str, Vec<String>> = HashMap::new();
body.insert("members", frontcodes);
let _ = http_post_request(url, key, &body);
} else {
println!("Members already fonting");
}
}
2023-11-20 15:39:40 +00:00
fn sp_get_userid(key: &str) -> String {
let url = format!("{}/me", SP_URL);
2023-11-21 13:20:21 +00:00
let res = http_get_request(url,key);
2023-11-20 15:39:40 +00:00
let json_res : Value = serde_json::from_str(&res.unwrap()).unwrap();
return json_res["id"].as_str().unwrap().to_string();
}
fn sp_get_memberids(key: &str, system_id: &str) -> HashMap<String, String> {
let url = format!("{}/members/{}", SP_URL, system_id);
2023-11-21 13:20:21 +00:00
let res = http_get_request(url,key);
2023-11-20 15:39:40 +00:00
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
let mut sp_memberdata: HashMap<String, String> = HashMap::new();
for data in datas {
sp_memberdata.insert(String::from(data["content"]["name"].as_str().unwrap()), String::from(data["id"].as_str().unwrap()));
}
return sp_memberdata;
}
fn get_sp_id(mem: &Member, ids: &HashMap<String, String>) -> String {
let mut member_id = String::new();
for (mn, mid) in ids {
if &mem.name == mn || &mem.alias == mn {
member_id = String::from(mid);
}
}
return member_id;
}
2023-11-21 14:38:25 +00:00
2023-11-22 12:56:08 +00:00
fn sp_get_fronters(key: &str, sys: &System) -> Vec<Member> {
2023-11-21 14:38:25 +00:00
let url = format!("{}/fronters", SP_URL);
let res = http_get_request(url,key);
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
2023-11-23 13:55:30 +00:00
let mut members = Vec::new();
2023-11-21 14:38:25 +00:00
for data in datas {
let sp_id = &data["content"]["member"].as_str().unwrap();
for member in &sys.members {
if &member.sp_id == sp_id {
2023-11-22 12:56:08 +00:00
members.push(member.clone());
2023-11-21 14:38:25 +00:00
}
}
}
return members;
}
2023-11-20 15:39:40 +00:00
2023-11-23 13:55:30 +00:00
fn sp_get_frontids(key: &str, to_id: &Member) -> String {
let url = format!("{}/fronters", SP_URL);
let res = http_get_request(url,key);
let datas: Vec<Value> = serde_json::from_str(&res.unwrap()).unwrap();
for data in datas {
let sp_f_id = &data["id"].as_str().unwrap();
let sp_id = &data["content"]["member"].as_str().unwrap();
if sp_id.to_string() == to_id.sp_id {
return sp_f_id.to_string();
}
}
return String::new();
}
2023-11-24 14:01:56 +00:00
fn sp_set_fronters(key: &str, to_front: &Vec<Member>, fronters: &Fronters) {
if to_front == &fronters.sp {
println!("Members already fonting");
return;
}
2023-11-23 13:55:30 +00:00
2023-11-24 14:01:56 +00:00
for fronting_member in &fronters.sp {
if !to_front.contains(&fronting_member) {
let f_id = sp_get_frontids(&key, &fronting_member);
2023-11-23 13:55:30 +00:00
2023-11-24 14:01:56 +00:00
let url = format!("{}/frontHistory/{}", SP_URL, f_id);
2023-11-23 13:55:30 +00:00
2023-11-24 14:01:56 +00:00
#[derive (Serialize)]
#[allow (non_snake_case)]
struct SpRem {
live: bool,
endTime: u64
2023-11-23 13:55:30 +00:00
}
2023-11-24 14:01:56 +00:00
let end_time = std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH).expect("wa").as_secs();
let rem = SpRem {
live: false,
endTime: end_time * 1000
};
2023-11-23 13:55:30 +00:00
2023-11-24 14:01:56 +00:00
let body = serde_json::to_string(&rem).expect("Error");
2023-11-23 13:55:30 +00:00
2023-11-24 14:01:56 +00:00
let _ = http_patch_request(url, key, body);
}
}
2023-11-23 13:55:30 +00:00
2023-11-24 14:01:56 +00:00
for tf_member in to_front {
if !fronters.sp.contains(&tf_member) {
let url = format!("{}/frontHistory", SP_URL);
#[derive (Serialize)]
#[allow (non_snake_case)]
struct SpAdd {
member: String,
custom: bool,
live: bool,
startTime: u64
2023-11-23 13:55:30 +00:00
}
2023-11-24 14:01:56 +00:00
let start_time = std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH).expect("wa").as_secs();
let rem = SpAdd {
member: String::from(&tf_member.sp_id),
custom: false,
live: true,
startTime: start_time * 1000
};
let body = serde_json::to_string(&rem).expect("Error");
let _ = http_post_request_st(url, key, body);
2023-11-23 13:55:30 +00:00
}
}
}
2023-11-21 11:47:07 +00:00
fn load_json(path: String) -> Value {
if Path::new(&path).exists() {
2023-11-21 13:20:21 +00:00
let config_data = fs::read_to_string(&path).expect("File not found");
2023-11-21 11:47:07 +00:00
return serde_json::from_str(&config_data).unwrap();
} else {
println!("Config file in {path} not found");
return Value::Null;
}
2023-11-20 15:39:40 +00:00
}
2023-11-26 09:20:09 +00:00
fn get_config(config_path: &str) -> Result<Config, &'static str> {
2023-11-21 13:20:21 +00:00
let path = format!("{}/config.json", config_path);
if Path::new(config_path).exists() {
2023-11-20 15:39:40 +00:00
2023-11-21 13:20:21 +00:00
let result = load_json(String::from(&path));
2023-11-20 15:39:40 +00:00
2023-11-21 13:20:21 +00:00
if result == Value::Null {
2023-11-26 09:20:09 +00:00
let _ = fs::write(path, EXAMPLE_JSON);
return Err("Config file missing, creating template in {path}");
} else {
let config: Config = serde_json::from_value(result).expect("Error unwrapping");
return Ok(config);
}
2023-11-21 11:47:07 +00:00
} else {
2023-11-21 13:20:21 +00:00
let _ = create_dir(config_path);
2023-11-26 09:20:09 +00:00
let _ = fs::write(path, EXAMPLE_JSON);
return Err("Directory {config_path} does not exist. Creating with template config");
2023-11-21 11:47:07 +00:00
}
2023-11-20 15:39:40 +00:00
}
2023-11-21 13:20:21 +00:00
fn get_system(config_path: &str) -> System {
let path = format!("{}/system.json", config_path);
let mut result = load_json(String::from(&path));
if result == Value::Null {
println!("Syncing system config");
let _ = sync(String::from(config_path));
result = load_json(String::from(&path));
}
let vec = serde_json::to_vec(&result).unwrap();
let sys = serde_json::from_slice::<System>(&vec).unwrap();
return sys;
}
2023-11-21 14:38:25 +00:00
2023-11-24 14:01:56 +00:00
fn get_fronters(pk_key: &str, sp_key: &str, sys: &System) -> Fronters {
let fronters = Fronters::new(
pk_get_fronters(pk_key, sys),
sp_get_fronters(sp_key, sys)
);
2023-11-21 14:38:25 +00:00
2023-11-23 13:55:30 +00:00
// if fronters["pk"] != fronters["sp"] {
// fronters.insert(String::from("pk"), fronters["sp"].clone());
// }
2023-11-21 14:38:25 +00:00
return fronters;
}
2023-11-20 15:39:40 +00:00
#[tokio::main]
2023-11-21 13:20:21 +00:00
async fn http_get_request(url: String, key: &str) -> Result<String, Box<dyn std::error::Error>> {
2023-11-20 15:39:40 +00:00
let client = reqwest::Client::new();
let res = client
.get(url)
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key)
.send()
.await?
.text()
.await?;
Ok(res)
}
2023-11-22 12:11:49 +00:00
#[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();
2023-11-24 14:01:56 +00:00
let _= client
2023-11-22 12:11:49 +00:00
.post(url)
.json(body)
.header(USER_AGENT, "Pluralsync")
.header(AUTHORIZATION, key)
.send()
.await?;
Ok(())
}
#[tokio::main]
2023-11-23 13:55:30 +00:00
async fn http_post_request_st(url: String, key: &str, body: String) -> Result<(), Box<dyn std::error::Error>> {
2023-11-22 12:11:49 +00:00
let client = reqwest::Client::new();
2023-11-23 13:55:30 +00:00
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()
2023-11-23 13:55:30 +00:00
.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
2023-11-22 12:11:49 +00:00
.patch(url)
2023-11-23 13:55:30 +00:00
.body(body)
.header("content-type", "application/json; charset=utf-8")
2023-11-22 12:11:49 +00:00
.header(USER_AGENT, "Pluralsync")
2023-11-23 13:55:30 +00:00
.header(AUTHORIZATION, key);
let _res = c.send()
2023-11-22 12:11:49 +00:00
.await?;
2023-11-23 13:55:30 +00:00
Ok(())
2023-11-22 12:11:49 +00:00
}