keyauth/
v1_2.rs

1/*!
2unofficial [keyauth](https://keyauth.cc) library that uses 1.2 api version
3
4basic usage:
5```rust
6let mut auth = keyauth::v1_2::KeyauthApi::new("application name", "ownerid", "application secret", "application version", "api url"); // if you dont have a custom domain for api use "https://keyauth.win/api/1.2/"
7auth.init().unwrap();
8auth.login("username", "password", Some("hwid".to_string()).unwrap()); // if you want to automaticly generate hwid use None insted.
9```
10
11also if you want to use an obfuscator for rust i recommend using [obfstr](https://crates.io/crates/obfstr) and [llvm obfuscator](https://github.com/eshard/obfuscator-llvm/wiki/Rust-obfuscation-guide)
12*/
13
14use uuid::Uuid;
15use std::collections::HashMap;
16use std::io::Read;
17use std::net::TcpListener;
18use reqwest::blocking::Client;
19use reqwest::blocking::Response;
20use hmac_sha256::HMAC;
21use base16::decode;
22
23/// every function in this struct (accept log) returns a Result and Err("Request was tampered with") will be returned if the request signature doesnt mathc the sha256 hmac of the message
24#[derive(Debug, Clone)]
25pub struct KeyauthApi {
26    name: String,
27    owner_id: String,
28    secret: String,
29    version: String,
30    enckey: String,
31    enckey_s: String,
32    session_id: String,
33    pub api_url: String,
34    pub num_keys: String,
35    pub num_online_users: String,
36    pub num_users: String,
37    pub app_version: String,
38    pub customer_panel_link: String,
39    pub username: String,
40    pub ip: String,
41    pub hwid: String,
42    pub create_date: String,
43    pub last_login: String,
44    pub subscription: String,
45    pub message: String,
46    pub success: bool,
47    pub blacklisted: bool,
48    pub response: String,
49}
50
51impl KeyauthApi {
52    /// creats a new KeyauthApi and its defaults, api_url has to be api version 1.2 example: "https://keyauth.win/api/1.2/" or if you have a custom api domain: "https://api.example.com/1.2/"
53    pub fn new(name: &str, owner_id: &str, secret: &str, version: &str, api_url: &str) -> Self {
54        Self {
55            name: name.to_string(),
56            owner_id: owner_id.to_string(),
57            secret: secret.to_string(),
58            version: version.to_string(),
59            enckey: String::new(),
60            enckey_s: String::new(),
61            session_id: String::new(),
62            num_keys: String::new(),
63            api_url: api_url.to_string(),
64            num_online_users: String::new(),
65            num_users: String::new(),
66            app_version: version.to_string(),
67            customer_panel_link: String::new(),
68            username: String::new(),
69            ip: String::new(),
70            hwid: machine_uuid::get(),
71            create_date: String::new(),
72            last_login: String::new(),
73            subscription: String::new(),
74            message: String::new(),
75            success: false,
76            blacklisted: false,
77            response: String::new(),
78        }
79    }
80
81    /// initializes a session, **required to run before any other function in this struct!!!** accept new
82    pub fn init(&mut self, hash: Option<&str>) -> Result<(), String> {
83        self.enckey = Uuid::new_v4().simple().to_string();
84        self.enckey_s = format!("{}-{}", self.enckey, self.secret);
85        let mut req_data = HashMap::new();
86        req_data.insert("type", "init");
87        if hash.is_some() {
88            req_data.insert("hash", hash.unwrap());
89        }
90        req_data.insert("ver", &self.version);
91        req_data.insert("name", &self.name);
92        req_data.insert("ownerid", &self.owner_id);
93        req_data.insert("enckey", &self.enckey);
94
95        let req = Self::request(req_data, &self.api_url);
96        let head = req.headers().clone();
97        let resp = req.text().unwrap();
98
99        if resp == "KeyAuth_Invalid" {
100            return Err("The application doesn't exist".to_string());
101        }
102        if !head.contains_key("signature") {
103            #[cfg(feature = "panic")]
104            {
105                panic!("response was tampered with");
106            }
107            #[cfg(not(feature = "panic"))]
108            {
109                return Err("response was tampered with".to_string());
110            }
111            #[cfg(feature = "panic")]
112            {
113                panic!("response was tampered with");
114            }
115            #[cfg(not(feature = "panic"))]
116            {
117                return Err("response was tampered with".to_string());
118            }
119        }
120        let sig = head.get("signature").unwrap().to_str().unwrap();
121        if sig != Self::make_hmac(&resp, &self.secret) {
122            #[cfg(feature = "panic")]
123            {
124                panic!("response was tampered with");
125            }
126            #[cfg(not(feature = "panic"))]
127            {
128                return Err("response was tampered with".to_string());
129            }
130        }
131        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
132        if json_rep["success"].as_bool().unwrap() {
133            self.session_id = json_rep["sessionid"].as_str().unwrap().to_string();
134            self.num_keys = json_rep["appinfo"]["numKeys"].as_str().unwrap().to_string();
135            self.num_online_users = json_rep["appinfo"]["numOnlineUsers"].as_str().unwrap().to_string();
136            self.num_users = json_rep["appinfo"]["numUsers"].as_str().unwrap().to_string();
137            self.customer_panel_link = json_rep["appinfo"]["customerPanelLink"].as_str().unwrap_or("").to_string();
138            Ok(())
139        } else {
140            if json_rep["message"].as_str().unwrap() == "invalidver" {
141                let download_url = json_rep["download"].as_str().unwrap();
142                if !download_url.is_empty() {
143                    webbrowser::open(download_url).unwrap();
144                }
145            }
146            Err(json_rep["message"].as_str().unwrap().to_string())
147        }
148    }
149
150    /// registeres a new user
151    pub fn register(&mut self, username: String, password: String, license: String, hwid: Option<String>) -> Result<(), String> {
152        let hwidd = match hwid {
153            Some(hwid) => hwid,
154            None => machine_uuid::get(),
155        };
156        let mut req_data = HashMap::new();
157        req_data.insert("type", "register");
158        req_data.insert("username", &username);
159        req_data.insert("pass", &password);
160        req_data.insert("key", &license);
161        req_data.insert("sessionid", &self.session_id);
162        req_data.insert("name", &self.name);
163        req_data.insert("ownerid", &self.owner_id);
164        req_data.insert("hwid", &hwidd);
165
166        let req = Self::request(req_data, &self.api_url);
167        let head = req.headers().clone();
168        let resp = req.text().unwrap();
169
170        if !head.contains_key("signature") {
171            #[cfg(feature = "panic")]
172            {
173                panic!("response was tampered with");
174            }
175            #[cfg(not(feature = "panic"))]
176            {
177                return Err("response was tampered with".to_string());
178            }
179        }
180        let sig = head.get("signature").unwrap().to_str().unwrap();
181        if sig != Self::make_hmac(&resp, &self.enckey_s) {
182            #[cfg(feature = "panic")]
183            {
184                panic!("Response was tampered with");
185            }
186            #[cfg(not(feature = "panic"))]
187            {
188                return Err("Response was tampered with".to_string());
189            }
190        }
191        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
192        if json_rep["success"].as_bool().unwrap() {
193            self.username = username;
194            self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
195            self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
196            self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
197            self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
198            Ok(())
199        } else {
200            Err(json_rep["message"].as_str().unwrap().to_string())
201        }
202    }
203
204    /// upgrades a user license level or extends a license
205    pub fn upgrade(&mut self, username: String, license: String) -> Result<(), String> {
206        let mut req_data = HashMap::new();
207        req_data.insert("type", "upgrade");
208        req_data.insert("username", &username);
209        req_data.insert("key", &license);
210        req_data.insert("sessionid", &self.session_id);
211        req_data.insert("name", &self.name);
212        req_data.insert("ownerid", &self.owner_id);
213
214        let req = Self::request(req_data, &self.api_url);
215        let head = req.headers().clone();
216        let resp = req.text().unwrap();
217
218        if !head.contains_key("signature") {
219            #[cfg(feature = "panic")]
220            {
221                panic!("response was tampered with");
222            }
223            #[cfg(not(feature = "panic"))]
224            {
225                return Err("response was tampered with".to_string());
226            }
227        }
228        let sig = head.get("signature").unwrap().to_str().unwrap();
229        if sig != Self::make_hmac(&resp, &self.enckey_s) {
230            #[cfg(feature = "panic")]
231            {
232                panic!("Response was tampered with");
233            }
234            #[cfg(not(feature = "panic"))]
235            {
236                return Err("Response was tampered with".to_string());
237            }
238        }
239        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
240        if json_rep["success"].as_bool().unwrap() {
241            Ok(())
242        } else {
243            Err(json_rep["message"].as_str().unwrap().to_string())
244        }
245    }
246
247    /// login self explanatory
248    pub fn login(&mut self, username: String, password: String, hwid: Option<String>) -> Result<(), String> {
249        let hwidd = match hwid {
250            Some(hwid) => hwid,
251            None => machine_uuid::get(),
252        };
253
254        let mut req_data = HashMap::new();
255        req_data.insert("type", "login");
256        req_data.insert("username", &username);
257        req_data.insert("pass", &password);
258        req_data.insert("hwid", &hwidd);
259        req_data.insert("sessionid", &self.session_id);
260        req_data.insert("name", &self.name);
261        req_data.insert("ownerid", &self.owner_id);
262
263        let req = Self::request(req_data, &self.api_url);
264        let head = req.headers().clone();
265        let resp = req.text().unwrap();
266
267        if !head.contains_key("signature") {
268            #[cfg(feature = "panic")]
269            {
270                panic!("response was tampered with");
271            }
272            #[cfg(not(feature = "panic"))]
273            {
274                return Err("response was tampered with".to_string());
275            }
276        }
277        let sig = head.get("signature").unwrap().to_str().unwrap();
278        if sig != Self::make_hmac(&resp, &self.enckey_s) {
279            #[cfg(feature = "panic")]
280            {
281                panic!("Response was tampered with");
282            }
283            #[cfg(not(feature = "panic"))]
284            {
285                return Err("Response was tampered with".to_string());
286            }
287        }
288        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
289
290        if json_rep["success"].as_bool().unwrap() {
291            self.username = username;
292            self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
293            self.hwid = hwidd;
294            self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
295            self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
296            self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
297            Ok(())
298        } else {
299            Err(json_rep["message"].as_str().unwrap().to_string())
300        }
301    }
302
303    /// <https://docs.keyauth.cc/api/license>
304    pub fn license(&mut self, license: String, hwid: Option<String>) -> Result<(), String> {
305        let hwidd = match hwid {
306            Some(hwid) => hwid,
307            None => machine_uuid::get(),
308        };
309
310        let mut req_data = HashMap::new();
311        req_data.insert("type", "license");
312        req_data.insert("key", &license);
313        req_data.insert("hwid", &hwidd);
314        req_data.insert("sessionid", &self.session_id);
315        req_data.insert("name", &self.name);
316        req_data.insert("ownerid", &self.owner_id);
317
318        let req = Self::request(req_data, &self.api_url);
319        let head = req.headers().clone();
320        let resp = req.text().unwrap();
321
322        if !head.contains_key("signature") {
323            #[cfg(feature = "panic")]
324            {
325                panic!("response was tampered with");
326            }
327            #[cfg(not(feature = "panic"))]
328            {
329                return Err("response was tampered with".to_string());
330            }
331        }
332        let sig = head.get("signature").unwrap().to_str().unwrap();
333        if sig != Self::make_hmac(&resp, &self.enckey_s) {
334            #[cfg(feature = "panic")]
335            {
336                panic!("Response was tampered with");
337            }
338            #[cfg(not(feature = "panic"))]
339            {
340                return Err("Response was tampered with".to_string());
341            }
342        }
343        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
344
345        if json_rep["success"].as_bool().unwrap() {
346            self.username = json_rep["info"]["username"].as_str().unwrap().to_string();
347            self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
348            self.hwid = hwidd;
349            self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
350            self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
351            self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
352            Ok(())
353        } else {
354            Err(json_rep["message"].as_str().unwrap().to_string())
355        }
356    }
357
358    /// this will get a global variable (not user) and return it
359    pub fn var(&mut self, varid: String) -> Result<String, String> {
360        let mut req_data = HashMap::new();
361        req_data.insert("type", "var");
362        req_data.insert("varid", &varid);
363        req_data.insert("sessionid", &self.session_id);
364        req_data.insert("name", &self.name);
365        req_data.insert("ownerid", &self.owner_id);
366
367        let req = Self::request(req_data, &self.api_url);
368        let head = req.headers().clone();
369        let resp = req.text().unwrap();
370
371        if !head.contains_key("signature") {
372            #[cfg(feature = "panic")]
373            {
374                panic!("response was tampered with");
375            }
376            #[cfg(not(feature = "panic"))]
377            {
378                return Err("response was tampered with".to_string());
379            }
380        }
381        let sig = head.get("signature").unwrap().to_str().unwrap();
382        if sig != Self::make_hmac(&resp, &self.enckey_s) {
383            #[cfg(feature = "panic")]
384            {
385                panic!("Response was tampered with");
386            }
387            #[cfg(not(feature = "panic"))]
388            {
389                return Err("Response was tampered with".to_string());
390            }
391        }
392        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
393
394        if json_rep["success"].as_bool().unwrap() {
395            Ok(json_rep["message"].as_str().unwrap().to_string())
396        } else {
397            Err(json_rep["message"].as_str().unwrap().to_string())
398        }
399    }
400
401    /// downloads a file, and decodes using base16::decode
402    pub fn file(&mut self, fileid: String) -> Result<Vec<u8>, String> {
403        let mut req_data = HashMap::new();
404        req_data.insert("type", "file");
405        req_data.insert("fileid", &fileid);
406        req_data.insert("sessionid", &self.session_id);
407        req_data.insert("name", &self.name);
408        req_data.insert("ownerid", &self.owner_id);
409
410        let req = Self::request(req_data, &self.api_url);
411        let head = req.headers().clone();
412        let resp = req.text().unwrap();
413
414        if !head.contains_key("signature") {
415            #[cfg(feature = "panic")]
416            {
417                panic!("response was tampered with");
418            }
419            #[cfg(not(feature = "panic"))]
420            {
421                return Err("response was tampered with".to_string());
422            }
423        }
424        let sig = head.get("signature").unwrap().to_str().unwrap();
425        if sig != Self::make_hmac(&resp, &self.enckey_s) {
426            #[cfg(feature = "panic")]
427            {
428                panic!("Response was tampered with");
429            }
430            #[cfg(not(feature = "panic"))]
431            {
432                return Err("Response was tampered with".to_string());
433            }
434        }
435        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
436
437        if json_rep["success"].as_bool().unwrap() {
438            Ok(decode(json_rep["contents"].as_str().unwrap()).unwrap())
439        } else {
440            Err(json_rep["message"].as_str().unwrap().to_string())
441        }
442    }
443
444    /// sends a webhook from keyauth's servers so the url isnt exposed
445    pub fn webhook(&mut self, webid: String, params: String) -> Result<String, String> {
446        let mut req_data = HashMap::new();
447        req_data.insert("type", "webhook");
448        req_data.insert("webid", &webid);
449        req_data.insert("params", &params);
450        req_data.insert("sessionid", &self.session_id);
451        req_data.insert("name", &self.name);
452        req_data.insert("ownerid", &self.owner_id);
453
454        let req = Self::request(req_data, &self.api_url);
455        let head = req.headers().clone();
456        let resp = req.text().unwrap();
457
458        if !head.contains_key("signature") {
459            #[cfg(feature = "panic")]
460            {
461                panic!("response was tampered with");
462            }
463            #[cfg(not(feature = "panic"))]
464            {
465                return Err("response was tampered with".to_string());
466            }
467        }
468        let sig = head.get("signature").unwrap().to_str().unwrap();
469        if sig != Self::make_hmac(&resp, &self.enckey_s) {
470            #[cfg(feature = "panic")]
471            {
472                panic!("Response was tampered with");
473            }
474            #[cfg(not(feature = "panic"))]
475            {
476                return Err("Response was tampered with".to_string());
477            }
478        }
479        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
480
481        if json_rep["success"].as_bool().unwrap() {
482            Ok(json_rep["message"].as_str().unwrap().to_string())
483        } else {
484            Err(json_rep["message"].as_str().unwrap().to_string())
485        }
486    }
487
488    /// checks if the user is blacklisted and sets self.blacklisted acordingly
489    pub fn checkblacklist(&mut self) -> Result<(), String> {
490        let mut req_data = HashMap::new();
491        req_data.insert("type", "checkblacklist");
492        req_data.insert("sessionid", &self.session_id);
493        req_data.insert("name", &self.name);
494        req_data.insert("ownerid", &self.owner_id);
495
496        let req = Self::request(req_data, &self.api_url);
497        let head = req.headers().clone();
498        let resp = req.text().unwrap();
499
500        if !head.contains_key("signature") {
501            #[cfg(feature = "panic")]
502            {
503                panic!("response was tampered with");
504            }
505            #[cfg(not(feature = "panic"))]
506            {
507                return Err("response was tampered with".to_string());
508            }
509        }
510        let sig = head.get("signature").unwrap().to_str().unwrap();
511        if sig != Self::make_hmac(&resp, &self.enckey_s) {
512            #[cfg(feature = "panic")]
513            {
514                panic!("Response was tampered with");
515            }
516            #[cfg(not(feature = "panic"))]
517            {
518                return Err("Response was tampered with".to_string());
519            }
520        }
521        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
522
523        if json_rep["success"].as_bool().unwrap() {
524            self.blacklisted = true;
525            Ok(())
526        } else {
527            self.blacklisted = false;
528            Ok(())
529        }
530    }
531
532    /// checks if the session is still active or if it expired
533    pub fn check_session(&mut self) -> Result<bool, String> {
534        let mut req_data = HashMap::new();
535        req_data.insert("type", "check");
536        req_data.insert("sessionid", &self.session_id);
537        req_data.insert("name", &self.name);
538        req_data.insert("ownerid", &self.owner_id);
539
540        let req = Self::request(req_data, &self.api_url);
541        let head = req.headers().clone();
542        let resp = req.text().unwrap();
543
544        if !head.contains_key("signature") {
545            #[cfg(feature = "panic")]
546            {
547                panic!("response was tampered with");
548            }
549            #[cfg(not(feature = "panic"))]
550            {
551                return Err("response was tampered with".to_string());
552            }
553        }
554        let sig = head.get("signature").unwrap().to_str().unwrap();
555        if sig != Self::make_hmac(&resp, &self.enckey_s) {
556            #[cfg(feature = "panic")]
557            {
558                panic!("Response was tampered with");
559            }
560            #[cfg(not(feature = "panic"))]
561            {
562                return Err("Response was tampered with".to_string());
563            }
564        }
565        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
566
567        Ok(json_rep["success"].as_bool().unwrap())
568    }
569
570    /// gets json of online users
571    pub fn fetch_online(&mut self) -> Result<serde_json::Value, String> {
572        let mut req_data = HashMap::new();
573        req_data.insert("type", "fetchOnline");
574        req_data.insert("sessionid", &self.session_id);
575        req_data.insert("name", &self.name);
576        req_data.insert("ownerid", &self.owner_id);
577
578        let req = Self::request(req_data, &self.api_url);
579        let head = req.headers().clone();
580        let resp = req.text().unwrap();
581
582        if !head.contains_key("signature") {
583            #[cfg(feature = "panic")]
584            {
585                panic!("response was tampered with");
586            }
587            #[cfg(not(feature = "panic"))]
588            {
589                return Err("response was tampered with".to_string());
590            }
591        }
592        let sig = head.get("signature").unwrap().to_str().unwrap();
593        if sig != Self::make_hmac(&resp, &self.enckey_s) {
594            #[cfg(feature = "panic")]
595            {
596                panic!("Response was tampered with");
597            }
598            #[cfg(not(feature = "panic"))]
599            {
600                return Err("Response was tampered with".to_string());
601            }
602        }
603        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
604
605        if json_rep["success"].as_bool().unwrap() {
606            Ok(json_rep["users"].clone())
607        } else {
608            Err(json_rep["message"].as_str().unwrap().to_string())
609        }
610    }
611
612    /// gets the arry of messages in a channel
613    pub fn get_chat(&mut self, channel: String) -> Result<serde_json::Value, String> {
614        let mut req_data = HashMap::new();
615        req_data.insert("type", "chatget");
616        req_data.insert("channel", &channel);
617        req_data.insert("sessionid", &self.session_id);
618        req_data.insert("name", &self.name);
619        req_data.insert("ownerid", &self.owner_id);
620
621        let req = Self::request(req_data, &self.api_url);
622        let head = req.headers().clone();
623        let resp = req.text().unwrap();
624
625        if !head.contains_key("signature") {
626            #[cfg(feature = "panic")]
627            {
628                panic!("response was tampered with");
629            }
630            #[cfg(not(feature = "panic"))]
631            {
632                return Err("response was tampered with".to_string());
633            }
634        }
635        let sig = head.get("signature").unwrap().to_str().unwrap();
636        if sig != Self::make_hmac(&resp, &self.enckey_s) {
637            #[cfg(feature = "panic")]
638            {
639                panic!("Response was tampered with");
640            }
641            #[cfg(not(feature = "panic"))]
642            {
643                return Err("Response was tampered with".to_string());
644            }
645        }
646        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
647
648        if json_rep["success"].as_bool().unwrap() {
649            Ok(json_rep["messages"].clone())
650        } else {
651            Err(json_rep["message"].as_str().unwrap().to_string())
652        }
653    }
654
655    /// sends a chat message in a channel
656    pub fn send_chat_message(&mut self, channel: String, message: String) -> Result<(), String> {
657        let mut req_data = HashMap::new();
658        req_data.insert("type", "chatsend");
659        req_data.insert("channel", &channel);
660        req_data.insert("message", &message);
661        req_data.insert("sessionid", &self.session_id);
662        req_data.insert("name", &self.name);
663        req_data.insert("ownerid", &self.owner_id);
664
665        let req = Self::request(req_data, &self.api_url);
666        let head = req.headers().clone();
667        let resp = req.text().unwrap();
668
669        if !head.contains_key("signature") {
670            #[cfg(feature = "panic")]
671            {
672                panic!("response was tampered with");
673            }
674            #[cfg(not(feature = "panic"))]
675            {
676                return Err("response was tampered with".to_string());
677            }
678        }
679        let sig = head.get("signature").unwrap().to_str().unwrap();
680        if sig != Self::make_hmac(&resp, &self.enckey_s) {
681            #[cfg(feature = "panic")]
682            {
683                panic!("Response was tampered with");
684            }
685            #[cfg(not(feature = "panic"))]
686            {
687                return Err("Response was tampered with".to_string());
688            }
689        }
690        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
691
692        if json_rep["success"].as_bool().unwrap() {
693            Ok(())
694        } else {
695            Err(json_rep["message"].as_str().unwrap().to_string())
696        }
697    }
698
699    /// self explanatory
700    pub fn ban(&mut self) {
701        let mut req_data = HashMap::new();
702        req_data.insert("type", "ban");
703        req_data.insert("sessionid", &self.session_id);
704        req_data.insert("name", &self.name);
705        req_data.insert("ownerid", &self.owner_id);
706
707        Self::request(req_data, &self.api_url);
708    }
709
710    /// sets a user variable to varvalue
711    pub fn setvar(&mut self, varname: String, varvalue: String) -> Result<(), String> {
712        let mut req_data = HashMap::new();
713        req_data.insert("type", "setvar");
714        req_data.insert("var", &varname);
715        req_data.insert("data", &varvalue);
716        req_data.insert("sessionid", &self.session_id);
717        req_data.insert("name", &self.name);
718        req_data.insert("ownerid", &self.owner_id);
719
720        let req = Self::request(req_data, &self.api_url);
721        let head = req.headers().clone();
722        let resp = req.text().unwrap();
723
724        if !head.contains_key("signature") {
725            #[cfg(feature = "panic")]
726            {
727                panic!("response was tampered with");
728            }
729            #[cfg(not(feature = "panic"))]
730            {
731                return Err("response was tampered with".to_string());
732            }
733        }
734        let sig = head.get("signature").unwrap().to_str().unwrap();
735        if sig != Self::make_hmac(&resp, &self.enckey_s) {
736            #[cfg(feature = "panic")]
737            {
738                panic!("Response was tampered with");
739            }
740            #[cfg(not(feature = "panic"))]
741            {
742                return Err("Response was tampered with".to_string());
743            }
744        }
745        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
746
747        self.message = json_rep["message"].as_str().unwrap().to_string();
748        self.success = json_rep["success"].as_bool().unwrap();
749        Ok(())
750    }
751
752    /// gets a user variable
753    pub fn getvar(&mut self, varname: String) -> Result<String, String> {
754        let mut req_data = HashMap::new();
755        req_data.insert("type", "getvar");
756        req_data.insert("var", &varname);
757        req_data.insert("sessionid", &self.session_id);
758        req_data.insert("name", &self.name);
759        req_data.insert("ownerid", &self.owner_id);
760
761        let req = Self::request(req_data, &self.api_url);
762        let head = req.headers().clone();
763        let resp = req.text().unwrap();
764
765        if !head.contains_key("signature") {
766            #[cfg(feature = "panic")]
767            {
768                panic!("response was tampered with");
769            }
770            #[cfg(not(feature = "panic"))]
771            {
772                return Err("response was tampered with".to_string());
773            }
774        }
775        let sig = head.get("signature").unwrap().to_str().unwrap();
776        if sig != Self::make_hmac(&resp, &self.enckey_s) {
777            #[cfg(feature = "panic")]
778            {
779                panic!("Response was tampered with");
780            }
781            #[cfg(not(feature = "panic"))]
782            {
783                return Err("Response was tampered with".to_string());
784            }
785        }
786        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
787
788        if json_rep["success"].as_bool().unwrap() {
789            Ok(json_rep["response"].as_str().unwrap().to_string())
790        } else {
791            Err(json_rep["message"].as_str().unwrap().to_string())
792        }
793    }
794
795    /// logs somethink to keyauth
796    pub fn log(&mut self, message: String, pcuser: Option<String>) {
797        let usr = match pcuser {
798            Some(pcuser) => pcuser,
799            None => self.username.clone(),
800        };
801
802        let mut req_data = HashMap::new();
803        req_data.insert("type", "log");
804        req_data.insert("message", &message);
805        req_data.insert("pcuser", &usr);
806        req_data.insert("sessionid", &self.session_id);
807        req_data.insert("name", &self.name);
808        req_data.insert("ownerid", &self.owner_id);
809
810        Self::request(req_data, &self.api_url);
811    }
812
813    /// changes Username, 
814    pub fn change_username(&mut self, new_username: String) -> Result<String, String> {
815        let mut req_data = HashMap::new();
816        req_data.insert("type", "changeUsername");
817        req_data.insert("newUsername", &new_username);
818        req_data.insert("sessionid", &self.session_id);
819        req_data.insert("name", &self.name);
820        req_data.insert("ownerid", &self.owner_id);
821
822        let req = Self::request(req_data, &self.api_url);
823        let head = req.headers().clone();
824        let resp = req.text().unwrap();
825
826        if !head.contains_key("signature") {
827            #[cfg(feature = "panic")]
828            {
829                panic!("response was tampered with");
830            }
831            #[cfg(not(feature = "panic"))]
832            {
833                return Err("response was tampered with".to_string());
834            }
835        }
836        let sig = head.get("signature").unwrap().to_str().unwrap();
837        if sig != Self::make_hmac(&resp, &self.enckey_s) {
838            #[cfg(feature = "panic")]
839            {
840                panic!("Response was tampered with");
841            }
842            #[cfg(not(feature = "panic"))]
843            {
844                return Err("Response was tampered with".to_string());
845            }
846        }
847        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
848
849        if json_rep["success"].as_bool().unwrap() {
850            Ok(json_rep["message"].as_str().unwrap().to_string())
851        } else {
852            Err(json_rep["message"].as_str().unwrap().to_string())
853        }
854    }
855
856    #[cfg(feature = "web_loader")]
857    pub fn web_login(&mut self, hwid: Option<String>) -> Result<(), String> {
858        use std::io::Write;
859
860        let hwidd = match hwid {
861            Some(hwid) => hwid,
862            None => self.hwid.clone(),
863        };
864
865        let listener = TcpListener::bind("127.0.0.1:1337");
866        if listener.is_err() {
867            return Err("Couldnt bind to port 1337".to_string());
868        }
869        let listener = listener.unwrap();
870
871        for stream in listener.incoming() {
872            if stream.is_err() {
873                continue;
874            }
875            let mut stream = stream.unwrap();
876            let mut buf = [0u8; 4096];
877            stream.read(&mut buf).unwrap();
878            let mut headers = [httparse::EMPTY_HEADER; 16];
879            let mut req = httparse::Request::new(&mut headers);
880            req.parse(&buf).unwrap();
881            if req.path.unwrap().starts_with("/handshake") {
882                let s = req.path.unwrap();
883                let start = s.find("?user=").unwrap_or(0) + 6;
884                let end = s.rfind("&token=").unwrap_or(s.len());
885                let user = &s[start..end];
886                let start = s.find("&token=").unwrap_or(0) + 7;
887                let token = &s[start..];
888                let mut req_data = HashMap::new();
889                req_data.insert("type", "login");
890                req_data.insert("username", &user);
891                req_data.insert("token", &token);
892                req_data.insert("name", &self.name);
893                req_data.insert("ownerid", &self.owner_id);
894                req_data.insert("hwid", &self.hwid);
895                req_data.insert("sessionid", &self.session_id);
896
897                let req = Self::request(req_data, &self.api_url);
898                let head = req.headers().clone();
899                let resp = req.text().unwrap();
900
901                if !head.contains_key("signature") {
902                    #[cfg(feature = "panic")]
903                    {
904                        panic!("response was tampered with");
905                    }
906                    #[cfg(not(feature = "panic"))]
907                    {
908                        return Err("response was tampered with".to_string());
909                    }
910                }
911                let sig = head.get("signature").unwrap().to_str().unwrap();
912                if sig != Self::make_hmac(&resp, &self.enckey_s) {
913                    #[cfg(feature = "panic")]
914                    {
915                        panic!("Response was tampered with");
916                    }
917                    #[cfg(not(feature = "panic"))]
918                    {
919                        return Err("Response was tampered with".to_string());
920                    }
921                }
922                let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
923                let (status, body) = if json_rep["success"].as_bool().unwrap() {
924                    self.username = user.to_string();
925                    self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
926                    self.hwid = hwidd;
927                    self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
928                    self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
929                    self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
930
931                    (420, "SHEESH")
932                } else {
933                    (200, json_rep["message"].as_str().unwrap())
934                };
935                let response = format!(r#"HTTP/1.1 {} OK
936Access-Control-Allow-Methods: Get, Post
937Access-Control-Allow-Origin: *
938Via: hugzho's big brain
939Location: your kernel ;)
940Retry-After: never lmao
941Server: \r\n\r\n
942
943{}"#, status, body);
944                stream.write_all(response.as_bytes()).unwrap();
945                return Ok(());
946            }
947        }
948        Ok(())
949    }
950
951    #[cfg(feature = "web_loader")]
952    pub fn button(&self, button: &str) -> Result<(), String> {
953         use std::io::Write;
954
955        let listener = TcpListener::bind("127.0.0.1:1337");
956        if listener.is_err() {
957            return Err("Couldnt bind to port 1337".to_string());
958        }
959        let listener = listener.unwrap();
960
961        for stream in listener.incoming() {
962            if stream.is_err() {
963                continue;
964            }
965            let mut stream = stream.unwrap();
966            let mut buf = [0u8; 4096];
967            stream.read(&mut buf).unwrap();
968            let mut headers = [httparse::EMPTY_HEADER; 16];
969            let mut req = httparse::Request::new(&mut headers);
970            req.parse(&buf).unwrap();
971            if req.path.unwrap().starts_with(format!("/{}", button).as_str()) {
972                let response = format!(r#"HTTP/1.1 {} OK
973Access-Control-Allow-Methods: Get, Post
974Access-Control-Allow-Origin: *
975Via: hugzho's big brain
976Location: your kernel ;)
977Retry-After: never lmao
978Server: \r\n\r\n
979
980{}"#, 420, "SHEESH");
981                stream.write_all(response.as_bytes()).unwrap();
982                return Ok(());
983            }
984        }
985        Ok(())
986    }
987
988    fn request(req_data: HashMap<&str, &str>, url: &str) -> Response {
989        let client = Client::new();
990        let mut req_data_str = String::new();
991        for d in req_data {
992            req_data_str.push_str(&format!("{}={}&", d.0, d.1))
993        }
994        req_data_str = req_data_str.strip_suffix("&").unwrap().to_string();
995        client.post(url.to_string())
996            .body(req_data_str)
997            .header("User-Agent", "KeyAuth")
998            .header("Content-Type", "application/x-www-form-urlencoded")
999            .send().unwrap()
1000    }
1001
1002    fn make_hmac(message: &str, key: &str) -> String {
1003        hex::encode(HMAC::mac(message, key)).to_string()
1004    }
1005}