uggo_lol_client/
lib.rs

1use std::sync::Arc;
2
3use native_tls::TlsConnector;
4use serde::Serialize;
5use serde::de::DeserializeOwned;
6use thiserror::Error;
7use ureq::{Agent, AgentBuilder};
8
9use ugg_types::client_runepage::{NewRunePage, RunePage, RunePages};
10use ugg_types::client_summoner::ClientSummoner;
11
12mod lcc;
13use lcc::{LeagueClientConnector, RiotLockFile};
14
15#[derive(Error, Debug)]
16pub enum LOLClientError {
17    #[error("Unable to create TLS connector")]
18    TlsConnectorError(#[from] native_tls::Error),
19    #[error("Unable to read lockfile")]
20    LockfileReadError(#[from] lcc::LeagueConnectorError),
21    #[error("Linux is not supported")]
22    LinuxNotSupported,
23}
24
25pub struct LOLClientAPI {
26    agent: Agent,
27    lockfile: RiotLockFile,
28}
29
30impl LOLClientAPI {
31    pub fn new() -> Result<LOLClientAPI, LOLClientError> {
32        if cfg!(target_os = "linux") {
33            return Err(LOLClientError::LinuxNotSupported);
34        }
35        Ok(LOLClientAPI {
36            agent: AgentBuilder::new()
37                .tls_connector(Arc::new(
38                    TlsConnector::builder()
39                        .danger_accept_invalid_certs(true)
40                        .build()?,
41                ))
42                .build(),
43            lockfile: LeagueClientConnector::parse_lockfile()?,
44        })
45    }
46
47    fn get_data<T: DeserializeOwned>(&self, url: &str) -> Option<T> {
48        match self
49            .agent
50            .get(url)
51            .set(
52                "Authorization",
53                &format!("Basic {}", self.lockfile.b64_auth),
54            )
55            .call()
56        {
57            Ok(response) => {
58                if response.status() == 200 {
59                    response.into_json().ok()
60                } else {
61                    None
62                }
63            }
64            Err(_) => None,
65        }
66    }
67
68    fn delete_data(&self, url: &str) {
69        match self
70            .agent
71            .delete(url)
72            .set(
73                "Authorization",
74                &format!("Basic {}", self.lockfile.b64_auth),
75            )
76            .call()
77        {
78            Err(_) | Ok(_) => (),
79        }
80    }
81
82    fn post_data<T: Serialize>(&self, url: &str, data: &T) {
83        match self
84            .agent
85            .post(url)
86            .set(
87                "Authorization",
88                &format!("Basic {}", self.lockfile.b64_auth),
89            )
90            .send_json(data)
91        {
92            Err(_) | Ok(_) => (),
93        }
94    }
95
96    #[must_use]
97    pub fn get_summoner_info(&self) -> Option<ClientSummoner> {
98        self.get_data::<ClientSummoner>(&format!(
99            "https://127.0.0.1:{}/lol-summoner/v1/current-summoner",
100            self.lockfile.port
101        ))
102    }
103
104    #[must_use]
105    pub fn get_current_rune_page(&self) -> Option<RunePage> {
106        match self.get_data::<RunePages>(&format!(
107            "https://127.0.0.1:{}/lol-perks/v1/pages",
108            self.lockfile.port
109        )) {
110            Some(data) => {
111                for page in &data {
112                    if page.name.starts_with("uggo:") && page.is_deletable {
113                        return Some(page.clone());
114                    }
115                }
116                for page in &data {
117                    if page.current && page.is_deletable {
118                        return Some(page.clone());
119                    }
120                }
121                None
122            }
123            None => None,
124        }
125    }
126
127    pub fn update_rune_page(&self, old_page_id: i64, rune_page: &NewRunePage) {
128        self.delete_data(&format!(
129            "https://127.0.0.1:{}/lol-perks/v1/pages/{}",
130            self.lockfile.port, old_page_id
131        ));
132        self.post_data::<NewRunePage>(
133            &format!(
134                "https://127.0.0.1:{}/lol-perks/v1/pages",
135                self.lockfile.port
136            ),
137            rune_page,
138        );
139    }
140}