dcss_api/
lobby.rs

1use crate::Error;
2use crate::Webtile;
3use serde_json::json;
4
5impl Webtile {
6    /// Login to the game, using a username and password. It returns a vector
7    /// of all playable game IDs.
8    ///
9    /// # Arguments
10    ///
11    /// * `username` - A string slice of the user's username.
12    /// * `password` - A string slice of the user's password.
13    ///
14    /// # Example
15    ///
16    /// ```no_run
17    /// // Login under the user "Username", with a password of "Password"
18    /// webtile.login_with_credentials("Username", "Password")?;
19    /// ```
20    pub fn login_with_credentials(
21        &mut self,
22        username: &str,
23        password: &str,
24    ) -> Result<Vec<String>, Box<Error>> {
25        self.write_json(json!({
26            "msg": "login",
27            "username": username,
28            "password": password,
29        }))?;
30
31        self.read_until("login_success", None, None)?;
32
33        self.write_json(json!({
34            "msg": "go_lobby"
35        }))?;
36        self.read_until("go_lobby", None, None)?;
37
38        Ok(self.get_playable_games())
39    }
40
41    /// Login to the game, using a cookie. It returns a vector of all playable
42    /// game IDs.
43    ///
44    /// # Arguments
45    ///
46    /// * `cookie` - A string slice of the user's cookie (received previously).
47    ///
48    /// # Example
49    ///
50    /// ```no_run
51    /// // Login under the user "Username", with a cookie
52    /// webtile.login_with_cookie("Username%123456789123456789123456789")?;
53    /// ```
54    pub fn login_with_cookie(&mut self, cookie: &str) -> Result<Vec<String>, Box<Error>> {
55        self.write_json(json!({"msg": "token_login", "cookie": cookie}))?;
56
57        self.read_until("login_success", None, None)?;
58
59        self.write_json(json!({
60            "msg": "go_lobby"
61        }))?;
62        self.read_until("go_lobby", None, None)?;
63
64        Ok(self.get_playable_games())
65    }
66
67    /// Create an account and login to the game, using a username and password. It returns a vector
68    /// of all playable game IDs. If the account exists, it will simply login using the provided
69    /// password.
70    ///
71    /// # Arguments
72    ///
73    /// * `username` - A string slice of the user's username.
74    /// * `password` - A string slice of the user's password.
75    /// * `email` - A optional string slice of the user's email.
76    ///
77    /// # Example
78    ///
79    /// ```no_run
80    /// // Register and login under the user "Username", with a password of "Password"
81    /// webtile.register_account("Username", "Password", None)?;
82    /// ```
83    pub fn register_account(
84        &mut self,
85        username: &str,
86        password: &str,
87        email: Option<&str>,
88    ) -> Result<Vec<String>, Box<Error>> {
89        self.write_json(
90            json!({"msg": "register", "username": username, "password": password, "email": email.unwrap_or("")}),
91        )?;
92
93        if let Err(e) = self.read_until("login_success", None, None) {
94            match *e {
95                Error::RegisterFailed => self.login_with_credentials(username, password)?,
96                _ => Err(e)?,
97            };
98        };
99
100        self.write_json(json!({
101            "msg": "go_lobby"
102        }))?;
103        self.read_until("go_lobby", None, None)?;
104
105        Ok(self.get_playable_games())
106    }
107
108    /// Request a cookie from the DCSS Webtile.
109    ///
110    /// # Example
111    ///
112    /// ```no_run
113    /// webtile.request_cookie()?;
114    /// ```
115    pub fn request_cookie(&mut self) -> Result<String, Box<Error>> {
116        self.write_json(json!({"msg": "set_login_cookie"}))?;
117
118        self.read_until("login_cookie", None, None)?;
119
120        for message in self.read_only_messages() {
121            let message_obj = message.as_object().unwrap();
122            if message_obj["msg"] == "login_cookie" {
123                return Ok(message_obj["cookie"].as_str().unwrap().to_owned());
124            }
125        }
126
127        unreachable!()
128    }
129
130    /// Get the RC file content for a specific game ID.
131    ///
132    /// # Arguments
133    ///
134    /// * `game_id` - A string slice of the game's ID.
135    ///
136    /// # Example
137    ///
138    /// ```no_run
139    /// webtile.get_rc_file("dcss-web-trunk")?;
140    /// ```
141    pub fn get_rc_file(&mut self, game_id: &str) -> Result<String, Box<Error>> {
142        self.write_json(json!({"msg": "get_rc", "game_id": game_id}))?;
143
144        self.read_until("rcfile_contents", None, None)?;
145
146        for message in self.read_only_messages() {
147            let message_obj = message.as_object().unwrap();
148            if message_obj["msg"] == "rcfile_contents" {
149                return Ok(message_obj["contents"].as_str().unwrap().to_owned());
150            }
151        }
152
153        unreachable!()
154    }
155
156    /// Set the RC file content of a specific game ID.
157    ///
158    /// # Arguments
159    ///
160    /// * `game_id` - A string slice of the game's ID.
161    /// * `content` - A string slice of the content to write to the RC file.
162    ///
163    /// # Example
164    ///
165    /// ```no_run
166    /// webtile.set_rc_file("dcss-web-trunk", "show_more = false\nrest_delay = -1")?;
167    /// ```
168    pub fn set_rc_file(&mut self, game_id: &str, content: &str) -> Result<(), Box<Error>> {
169        self.write_json(json!({"msg": "set_rc", "game_id": game_id, "contents": content}))?;
170
171        Ok(())
172    }
173
174    /// Process the data received when successfully logging in, to extract the playable games
175    fn get_playable_games(&self) -> Vec<String> {
176        for message in self.read_only_messages() {
177            let message_obj = message.as_object().unwrap();
178            if message_obj["msg"] == "set_game_links" {
179                return process_playable_game(message_obj["content"].as_str().unwrap());
180            }
181        }
182
183        unreachable!()
184    }
185}
186
187/// Process the data received when successfully logging in, to extract the playable games
188fn process_playable_game(game_list_html: &str) -> Vec<String> {
189    let mut game_list_vec = game_list_html
190        .split('#')
191        .map(|x| x.split('\"').next().unwrap_or("").to_owned())
192        .map(|x| x[5..x.len()].to_owned())
193        .collect::<Vec<String>>();
194
195    game_list_vec.remove(0);
196
197    game_list_vec
198}