volt/
user.rs

1//! User Client
2//! 
3//! Makes requests for different information about users
4//! 
5//! ## Examples:
6//! For all of the examples you will need to replace the path with the path to 
7//! your own .env file and add the key "USER_KEY" with you revolt authentication token
8//! 
9//! This fetchs all the data about the user and prints it out
10//! 
11//! ```rust
12//! use volt::user::UserClient;
13//! use dotenv::from_path;
14//! use std::env::var;
15//! 
16//! let path = r#"C:\Users\conno\Downloads\volt\tests\.env"#;
17//! from_path(path).unwrap();
18//! let user: String = var("USER_KEY").unwrap();
19//! let mut client = UserClient::new(user);
20//! println!("{:?}", client.fetch_self().get());
21//! ```
22//!
23//! This returns just the id of the user as string
24//! 
25//! ```rust
26//! use volt::user::UserClient;
27//! use dotenv::from_path;
28//! use std::env::var;
29//! 
30//! let path = r#"C:\Users\conno\Downloads\volt\tests\.env"#;
31//! from_path(path).unwrap();
32//! let user: String = var("USER_KEY").unwrap();
33//! let mut client = UserClient::new(user);
34//! println!("{:?}", client.fetch_self().get().id());
35//! ```
36//! 
37
38use crate::core::structs::user_structs::{User, UserFlags, UserProfile, UserDmChannels as Channels, UserDms, UserMutuals, Image};
39use crate::core::Cache;
40use crate::core::TokenBucket;
41
42use reqwest::{Client as ReqwestClient};
43use reqwest::header::{HeaderMap, HeaderValue};
44use serde::{Serialize, Deserialize};
45use tokio::time;
46
47use std::time::Duration;
48use std::sync::{Arc, Mutex};
49
50/// The client to acsess user information
51/// 
52/// ## Returns:
53/// 
54/// The desired information as the inbuild `UserResult` enum type
55
56#[derive(Debug, Clone)]
57pub struct UserClient {
58    auth: String, 
59    cache: Cache,
60    url: String,
61    bucket: Arc<Mutex<TokenBucket>>,
62    user: String,
63    json: String,
64    data: Data,
65}
66
67#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
68pub(crate) enum Data {
69    Users(),
70    UsersFlags(),
71    UsersProfile(),
72    UserDmChannels(),
73    UserDms(),
74    UserMutuals(),
75    String(),
76}
77
78/// The enum for data returning
79/// 
80/// The variations of this enum are the types that are returned after .run() is called
81/// 
82/// **Note!:**
83/// 
84/// If any of the methods that impliment this enum are called the type will change
85 
86#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
87pub enum UserResult {
88    User(User),
89    UserFlags(UserFlags),
90    UserProfile(UserProfile),
91    UserDmChannels(Vec<Channels>),
92    UserDms(UserDms),
93    UserMutuals(UserMutuals),
94    String(String),
95}
96
97impl UserClient {
98
99    /// Creates a new UserClient object
100    /// 
101    /// What this function does is initialize all of the values for the client to use
102    /// 
103    /// This function must be directly called after UserClient (ex: UserClient::new(auth))
104    /// 
105    /// ## Parameters
106    /// 
107    /// `auth: String` - The revolt authentication token of the user
108    
109    pub fn new(auth: String) -> UserClient {
110        UserClient {
111            auth, 
112            cache: Cache::new(),
113            url: String::new(),
114            bucket: Arc::new(Mutex::new(TokenBucket::new(20))),
115            user: String::new(),
116            json: String::new(),
117            data: Data::Users(), // Data::Users() is defult as it is the most common
118        }
119    }
120
121    /// Fetchs the data of the currently authenticated user
122    /// 
123    /// Sets the UserResult enum to UserResult::User
124    
125    pub fn fetch_self(&mut self) -> &mut Self{
126        self.url ="https://api.revolt.chat/users/@me".to_string();
127        self
128    } 
129
130    /// Fetchs a user's data
131    /// 
132    /// Sets the UserResult enum to UserResult::User
133    /// 
134    /// ## Parameters:
135    /// 
136    /// `target: &str` - The userid of the user you want data for on revolt
137    
138    pub fn fetch_user(&mut self, target: &str) -> &mut Self{
139        self.url = format!("https://api.revolt.chat/users/{}", target);
140        self.user = target.to_string();
141        self
142    }
143
144    /// Edits a users details
145    /// 
146    /// ## Parameters:
147    /// 
148    /// - `target: &str` - The userid of your user
149    /// - `changes: &str` - A &str repersentation of the changes you want to make to your user
150    /// 
151    /// **Flaged as experimental until further testing can be done!!**
152    
153    #[cfg(feature="experimental")]
154    pub fn edit_user(&mut self, target: &str, changes: &str) -> &mut Self{
155        self.data = Data::String();
156        self.url = format!("https://api.revolt.chat/users/{}", target);
157        self.json = changes.to_string();
158        self
159    }
160
161    /// Fetchs the flags of a user
162    /// 
163    /// Flags are information about the users account status on revolt
164    /// 
165    /// - 1: Suspended
166    /// - 2: Deleted
167    /// - 4: Banned
168    /// 
169    /// Sets the UserResult enum to UserResult::UsersFlags
170    /// 
171    /// ## Parameters:
172    /// 
173    /// `target: &str` - The userid of the user you want data for on revolt
174
175    pub fn fetch_user_flags(&mut self, target: &str) -> &mut Self{
176        self.data = Data::UsersFlags();
177        self.url = format!("https://api.revolt.chat/users/{}/flags", target);
178        self.user = target.to_string();
179        self
180    }
181
182    /// Changes a users username
183    /// 
184    /// ## Parameters:
185    /// 
186    /// - `username: &str` - The username you want to change to
187    /// - `pass: &str` - Your revolt password
188    /// 
189    /// **Flaged as experimental until further testing can be done!!**
190    
191    #[cfg(feature="experimental")]
192    pub fn change_username(&mut self, username: &str, pass: &str) -> &mut Self {
193        self.data = Data::String();
194        self.url ="https://api.revolt.chat/users/@me/username".to_string();
195        self.json = format!("{{\"username\": {}, \"password\": {},}}", username, pass);
196        self
197    }
198
199    /// Returns the binary data of a persons avatar
200    /// 
201    /// This function in pair with 'avatar' in UserResult will return a string that you will have to parse to form an image
202    /// 
203    /// ## Parameters:
204    /// 
205    /// `target: &str` - The id of the user that you want the avatar of
206    
207    pub fn fetch_default_avatar(&mut self, target: &str) -> &mut Self {
208        self.data = Data::String();
209        self.url = format!("https://api.revolt.chat/users/{}/default_avatar", target);
210        self.user = target.to_string();
211        self    
212    }
213
214    /// Fetchs the profile data of a user
215    /// 
216    /// ## Parameters: 
217    /// 
218    /// `target: &str` - The id of the user that you want to fetch the profile of
219    
220    pub fn fetch_user_profile(&mut self, target: &str) -> &mut Self {
221        self.data = Data::UsersProfile();
222        self.url = format!("https://api.revolt.chat/users/{}/profile", target);
223        self.user = target.to_string();
224        self
225    }
226
227    /// **Flaged as experimental until further testing can be done!!**
228    #[cfg(feature="experimental")]
229    pub fn fetch_direct_message_channels(&mut self) -> &mut Self {
230        self.data = Data::UserDmChannels();
231        self.url ="https://api.revolt.chat/users/dms".to_string();
232        self
233    }
234
235    /// **Flaged as experimental until further testing can be done!!**
236    #[cfg(feature="experimental")]
237    pub fn open_direct_message(&mut self, target: &str) -> &mut Self {
238        self.data = Data::UserDms();
239        self.url = format!("https://api.revolt.chat/users/{}/dm", target);
240        self
241    }
242
243    /// Fetches the mutual users and servers of a person
244    /// 
245    /// ## Parameters:
246    /// 
247    /// `target: &str` - The user id of the person you want to compare 
248
249    pub fn fetch_mutuals(&mut self, target: &str) -> &mut Self { 
250        self.data = Data::UserMutuals();
251        self.url = format!("https://api.revolt.chat/users/{}/mutual", target);
252        self
253    }
254
255    /// Accepts or denies a friend request
256    /// 
257    /// ## Prameters:
258    /// 
259    /// `target: &str` - The persons whoes friend request you want to accep/deny
260    /// 
261    /// **Note**
262    /// If you do `.put()` after it will accept the request, `.del()` will deny it or remove the friend
263    
264    pub fn friend(&mut self, target: &str) -> &mut Self {
265        self.url = format!("https://api.revolt.chat/users/{}/friend", target);
266        self
267    }
268
269    /// Blocks or unblocks a user
270    /// 
271    /// ## Prameters:
272    /// 
273    /// `target: &str` - The person who you want to block/unblock
274    /// 
275    /// **Note**
276    /// If you do `.put()` it will block the user, `.del()` will unblock them
277    
278    pub fn block(&mut self, target: &str) -> &mut Self {
279        self.url = format!("https://api.revolt.chat/users/{}/block", target);
280        self
281    }
282
283    /// Sends a friend request to a user
284    /// 
285    /// ## Prameters: 
286    /// 
287    /// `target: &str` - The username and discrimeter of the user you want to send a friend request to 
288    /// ex: "Bird#9223"
289    
290    pub fn friend_request(&mut self, target: &str) -> &mut Self {
291        self.url = "https://api.revolt.chat/users/friend".to_string();
292        self.json = format!("{{\"username\":\"{}\"}}", target);
293        self
294    }
295
296    /// Runs the client for a get request
297    /// 
298    /// This function makes the request, applies rate limits, and caches/retrives values from the cache 
299    /// 
300    /// ## Retruns:
301    /// 
302    /// This function returns a UserResult enum that can be printed out 
303    /// or used to get more specific data from the json data provided
304
305    #[tokio::main]
306    pub async fn get(&mut self) -> UserResult{
307        // Checks the cache for the item
308        // Only used on GET requests
309        if self.cache.get(&self.user).is_some() {
310            let text = self.cache.get(&self.user).unwrap();
311            match text.1.to_lowercase().as_str(){
312                "user" => {
313                    if self.data == Data::Users(){
314                        let parsed_value: User = serde_json::from_str(&text.0).unwrap();
315                        return UserResult::User(parsed_value);
316                    }
317                }
318                "userflags" => {
319                    if self.data == Data::UsersFlags(){
320                        let parsed_value: UserFlags = serde_json::from_str(&text.0).unwrap();
321                        return UserResult::UserFlags(parsed_value);
322                    }
323                }
324                "userprofile" => {
325                    if self.data == Data::UsersProfile(){
326                        let parsed_value: UserProfile = serde_json::from_str(&text.0).unwrap();
327                        return UserResult::UserProfile(parsed_value);
328                    }
329                }
330                _ => panic!("Something went very wrong"),
331            }
332        }
333
334        let bucket = self.bucket.clone();
335        let mut bucket = bucket.lock().unwrap();
336
337        let mut header: HeaderMap = HeaderMap::new();
338        header.insert("x-session-token", HeaderValue::from_str(&self.auth).unwrap()); 
339
340        while !bucket.try_acquire() {
341            time::sleep(Duration::from_millis(100)).await;
342        }
343
344        let client = ReqwestClient::new().get(&self.url).headers(header).send().await.unwrap();
345
346        // Might be a problem in the future
347        let body = client.text().await.unwrap();
348
349        return self.return_data(body)
350    }
351
352    /// Runs the client for a patch request
353    /// 
354    /// This function makes the request, applies rate limits, sends the data, and returns the result
355    /// 
356    /// ## Retruns:
357    /// 
358    /// This function returns a UserResult enum that can be printed out 
359    /// or used to get more specific data from the json data provided
360
361    #[tokio::main]
362    pub async fn patch(&mut self) -> UserResult {
363        let bucket = self.bucket.clone();
364        let mut bucket = bucket.lock().unwrap();
365
366        let mut header: HeaderMap = HeaderMap::new();
367        header.insert("x-session-token", HeaderValue::from_str(&self.auth).unwrap()); 
368        header.insert("Content-Type", HeaderValue::from_str("application/json").unwrap());
369
370        while !bucket.try_acquire() {
371            time::sleep(Duration::from_millis(100)).await;
372        }
373
374        let client = ReqwestClient::new().patch(&self.url).headers(header).body(self.json.clone()).send().await.unwrap();
375
376        let body = client.text().await.unwrap();
377
378        return self.return_data(body)
379    }
380    
381    /// Runs the client for a put request
382    /// 
383    /// This function makes the request, applies rate limits, and returns the result
384    /// 
385    /// ## Retruns:
386    /// 
387    /// This function returns a UserResult enum that can be printed out 
388    /// or used to get more specific data from the json data provided
389    
390    #[tokio::main]
391    pub async fn put(&mut self) -> UserResult {
392        let bucket = self.bucket.clone();
393        let mut bucket = bucket.lock().unwrap();
394
395        let mut header: HeaderMap = HeaderMap::new();
396        header.insert("x-session-token", HeaderValue::from_str(&self.auth).unwrap()); 
397
398        while !bucket.try_acquire() {
399            time::sleep(Duration::from_millis(100)).await;
400        }
401
402        let client = ReqwestClient::new().put(&self.url).headers(header).send().await.unwrap();
403
404        let body = client.text().await.unwrap();
405
406        return self.return_data(body)
407    }
408
409    /// Runs the client for a delete request
410    /// 
411    /// This function makes the request, applies rate limits, and returns the result
412    /// 
413    /// ## Retruns:
414    /// 
415    /// This function returns a UserResult enum that can be printed out 
416    /// or used to get more specific data from the json data provided
417    
418    #[tokio::main]
419    pub async fn del(&mut self) -> UserResult {
420        let bucket = self.bucket.clone();
421        let mut bucket = bucket.lock().unwrap();
422
423        let mut header: HeaderMap = HeaderMap::new();
424        header.insert("x-session-token", HeaderValue::from_str(&self.auth).unwrap()); 
425
426        while !bucket.try_acquire() {
427            time::sleep(Duration::from_millis(100)).await;
428        }
429
430        let client = ReqwestClient::new().delete(&self.url).headers(header).send().await.unwrap();
431
432        let body = client.text().await.unwrap();
433
434        return self.return_data(body)
435    }   
436
437    /// Runs the client for a post request
438    /// 
439    /// This function makes the request, applies rate limits, sends the data, and returns the result
440    /// 
441    /// ## Retruns:
442    /// 
443    /// This function returns a UserResult enum that can be printed out 
444    /// or used to get more specific data from the json data provided
445
446    #[tokio::main]
447    pub async fn post(&mut self) -> UserResult {
448        let bucket = self.bucket.clone();
449        let mut bucket = bucket.lock().unwrap();
450
451        let mut header: HeaderMap = HeaderMap::new();
452        header.insert("x-session-token", HeaderValue::from_str(&self.auth).unwrap()); 
453        header.insert("Content-Type", HeaderValue::from_str("application/json").unwrap());
454
455        while !bucket.try_acquire() {
456            time::sleep(Duration::from_millis(100)).await;
457        }
458
459        let client = ReqwestClient::new().post(&self.url).headers(header).body(self.json.clone()).send().await.unwrap();
460
461        let body = client.text().await.unwrap();
462
463        return self.return_data(body)
464    }
465
466    // Literally returns the data for the main 'get, patch, etc.' functions
467    fn return_data(&mut self, body: String) -> UserResult{
468        match self.data{
469            Data::Users() => {
470                let value: User = serde_json::from_str(&body).unwrap();
471                self.cache.add(value.id.clone(), (body, "user".to_string()));
472                return UserResult::User(value);
473            },
474            Data::UsersFlags() => {
475                let value: UserFlags = serde_json::from_str(&body).unwrap();
476                self.cache.add(self.user.clone(), (body, "userflags".to_string()));
477                return UserResult::UserFlags(value);
478            },
479            Data::UsersProfile() => {
480                let value: UserProfile = serde_json::from_str(&body).unwrap();
481                self.cache.add(self.user.clone(), (body, "userprofile".to_string()));
482                return UserResult::UserProfile(value);
483            },
484            Data::UserDmChannels() => {
485                let value: Vec<Channels> = serde_json::from_str(&body).unwrap();
486                return UserResult::UserDmChannels(value);
487            },
488            Data::UserDms() => {
489                let value: UserDms = serde_json::from_str(&body).unwrap();
490                return UserResult::UserDms(value);
491            },
492            Data::UserMutuals() => {
493                let value: UserMutuals = serde_json::from_str(&body).unwrap();
494                return UserResult::UserMutuals(value);
495            }
496            Data::String() => {
497                return UserResult::String(body);
498            }
499        }
500    }
501}
502
503impl UserResult {
504
505    /// Returns a users id
506    /// 
507    /// ## Returns:
508    /// 
509    /// The users id as a string
510    /// 
511    /// ## Panics!:
512    /// 
513    /// This funtion will panic if the enum variant UserResult::User has not been called
514    
515    pub fn id(&self) -> String {
516        if let UserResult::User(user_data) = self {
517            user_data.id.clone()
518        } else{
519            panic!("Cannot get id from: {:?}", self);
520        }
521    }
522
523    /// Returns a users name
524    /// 
525    /// ## Returns:
526    /// 
527    /// The users name as a string
528    /// 
529    /// ## Panics!:
530    /// 
531    /// This funtion will panic if the enum variant UserResult::User has not been called
532
533    pub fn name(&self) -> String {
534        if let UserResult::User(user_data) = self {
535            user_data.username.clone()
536        } else{
537            panic!("Cannot get name from: {:?}", self);
538        }
539    }
540
541    /// Returns a users discriminator
542    /// 
543    /// ## Returns:
544    /// 
545    /// The discriminator of a user as a string
546    
547    pub fn discriminator(&self) -> String {
548        if let UserResult::User(user_data) = self {
549            user_data.discriminator.clone()
550        } else{
551            panic!("Cannot get discriminator from: {:?}", self);
552        }
553    }
554
555    /// Returns a users avatar
556    /// 
557    /// ## Returns:
558    /// 
559    /// The users avatar data in the form of a struct called image that can be parsed down to get the specific values
560    /// 
561    /// ## Panics!:
562    /// 
563    /// This funtion will panic if the enum variant UserResult::User has not been called
564
565    pub fn avatar(&self) -> Image{
566        if let UserResult::User(user_data) = self {
567            match user_data.avatar.clone().is_some() {
568                true => user_data.avatar.clone().unwrap(),
569                false => panic!("Avatar not found!"),
570            }
571        } else {
572            panic!("Cannot get avatar from: {:?}", self);
573        }
574    }
575
576    /// Returns the badges a users has
577    /// 
578    /// Badges can be earned on Revolt for different things (will explain below)
579    /// 
580    /// The API shows badges as the sum of the values of all the badges
581    /// 
582    /// Badge Values:
583    /// 
584    /// - 1: Developer (Develops Revolt)
585    /// - 2: Translator (Translated Revolt into another language)
586    /// - 4: Supporter (Supported Revolt with a donation)
587    /// - 8: Responsibly Disclosed Bug(s) (Disclosed a bug responibly)
588    /// - 16: Founder (Founded Revolt)
589    /// - 32: Platform Moderation (Moderates Revolt)
590    /// - 64: Active Supporter (Activlty supports Revolt)
591    /// - 128: Paw (🦊🦝)
592    /// - 256: Early Adopter (One of the first 1000 users)
593    /// - 512: ReservedRelevantJokeBadge1 (Amogus)
594    /// - 1024 ReservedRelevantJokeBadge2 (Amogus Troll Face)
595    /// 
596    /// ## Returns
597    /// 
598    /// A `vec<&str>` of the badges the user has earned in order from highest value to lowest value
599    /// 
600    /// ## Panics!:
601    /// 
602    /// This funtion will panic if the enum variant UserResult::User has not been called
603
604    pub fn badges(&self) -> Vec<&str> {
605        // Credit to FatalErrorMogus for the inital design
606        if let UserResult::User(user_data) = self {
607            let badges: Vec<(&i32, &str)> = vec![
608                (&1024, "ReservedRelevantJokeBadge1"),
609                (&512, "ReservedRelevantJokeBadge1"),
610                (&256, "EarlyAdopter"),
611                (&128, "Paw"),
612                (&64, "ActiveSupporter"),
613                (&32, "PlatformModeration"),
614                (&16, "Founder"),
615                (&8, "ResponsibleDisclosure"),
616                (&4, "Supporter"),
617                (&2, "Translator"),
618                (&1, "Developer"),
619            ];
620            let mut badge = user_data.badges;
621            let mut final_badges: Vec<&str> = Vec::new();
622            for i in badges{
623                if badge - i.0 >= 0 {
624                    final_badges.push(i.1);
625                    badge -= i.0;
626                };
627            }
628            final_badges
629        } else {
630           panic!("Cannot get badges from: {:?}", self) ;
631        }
632    }
633
634    /// Returns the users flags
635    /// 
636    /// Flags are information about the users account status on revolt
637    /// 
638    /// - 1: Suspended
639    /// - 2: Deleted
640    /// - 4: Banned
641    /// 
642    /// ## Returns:
643    /// 
644    /// The users flags as a usize
645    /// 
646    /// ## Panics!:
647    /// 
648    /// This function will panic if fetch_user_flags() was not called
649    
650    pub fn flags(&self) -> usize {
651        if let UserResult::UserFlags(user_data) = self {
652            user_data.flags.clone()
653        } else {
654           panic!("Cannot get flags from: {:?}", self) ;
655        }
656    }
657
658    /// Returns a users background image
659    /// 
660    /// ## Returns:
661    /// 
662    /// The users background data in the form of a struct called image that can be parsed down to get the specific values
663    /// 
664    /// ## Panics!:
665    /// 
666    /// This funtion will panic if the enum variant UserResult::UserProfile has not been called
667
668    pub fn background(&self) -> Image{
669        if let UserResult::UserProfile(user_data) = self {
670            user_data.background.clone()
671        } else {
672            panic!("Cannot get background from: {:?}", self);
673        }
674    }
675
676    /// Returns the status text of a user
677    /// 
678    /// ## Returns:
679    /// 
680    /// The status text of a user as a string
681    /// 
682    /// **Note:**
683    /// 
684    /// This function takes both UserResult::UserProfile and UserResult::User
685    /// 
686    /// When UserResult::User is called the value may be "None" 
687    /// if there was no status or there was and error parsing the status
688    /// 
689    /// ## Panics!:
690    /// 
691    /// This function will panic if fetch_user_flags was called before
692    
693    pub fn status(&self) -> String {
694        if let UserResult::UserProfile(user_data) = self {
695            user_data.content.clone()
696        }
697        else if let UserResult::User(user_data) = self {
698            match user_data.status.clone().is_some(){
699                true => user_data.status.clone().unwrap().text.unwrap_or("None".to_string()),
700                false => "None".to_string(),
701            }
702        } else {
703            panic!("Cannot get status from: {:?} \nMake sure you are not calling: \"fetch_user_flags\"", self);
704        }
705    }
706
707    #[cfg(feature="experimental")]
708    pub fn channel_types(&self) -> Vec<String> {
709        let mut types: Vec<String> = Vec::new();
710        if let UserResult::UserDmChannels(user_data) = self {
711            for channel_types in user_data {
712                types.push(channel_types.channel_type.clone());
713            }
714            types
715        }
716        else if let UserResult::UserDms(user_data) = self {
717            // Unnessisary but ok
718            types.push(user_data.channel_type.clone());
719            types
720        }
721        else {
722            panic!("Cannot get channel type(s) from: {:?}", self)
723        }
724    }
725
726    #[cfg(feature="experimental")]
727    pub fn channel_ids(&self) -> Vec<String> {
728        let mut ids: Vec<String> = Vec::new();
729        if let UserResult::UserDmChannels(user_data) = self {
730            for channel_types in user_data {
731                ids.push(channel_types.channel_id.clone());
732            }
733            ids
734        }
735        else if let UserResult::UserDms(user_data) = self {
736            // Unnessisary but ok
737            ids.push(user_data.channel_type.clone());
738            ids
739        }
740        else {
741            panic!("Cannot get channel id(s) from: {:?}", self)
742        }
743    }
744
745    /// Returns the mutual users a person has
746    /// 
747    /// ## Returns:
748    /// 
749    /// The mutual users of a person as a `Vec<String>`
750    /// 
751    /// ## Panics!
752    /// 
753    /// This function will panic if the enum varient UserMutuals was not called
754    
755    pub fn mutual_users(&self) -> Vec<String> {
756        if let UserResult::UserMutuals(user_data) = self {
757            user_data.users.clone()
758        }
759        else {
760            panic!("Cannot Get mutual users from: {:?}", self)
761        }
762    }
763
764    /// Returns the mutual servers a person has
765    /// 
766    /// ## Returns:
767    /// 
768    /// The mutual servers of a person as a `Vec<String>`
769    /// 
770    /// ## Panics!
771    /// 
772    /// This function will panic if the enum varient UserMutuals was not called
773    /// 
774    pub fn mutual_servers(&self) -> Vec<String> {
775        if let UserResult::UserMutuals(user_data) = self {
776            user_data.servers.clone()
777        }
778        else {
779            panic!("Cannot Get mutual servers from: {:?}", self)
780        }
781    }
782}