]> git.lizzy.rs Git - istanco_ddns.git/blob - src/main.rs
Clarify functionality of form_set
[istanco_ddns.git] / src / main.rs
1 use anyhow::anyhow;
2 use scraper::{Html, Selector};
3
4 async fn form_get(
5     client: &reqwest::Client,
6     addr: &str,
7     form: &str,
8 ) -> anyhow::Result<Vec<(String, String)>> {
9     Ok(
10         Html::parse_document(&client.get(addr).send().await?.text().await?)
11             .select(&Selector::parse(form).unwrap())
12             .next()
13             .ok_or(anyhow!("form for selector {form} not found"))?
14             .select(&Selector::parse("input").unwrap())
15             .map(|item| item.value())
16             .flat_map(|item| {
17                 if matches!(item.attr("type"), Some(x) if x == "checkbox" || x == "submit") {
18                     return None;
19                 }
20
21                 Some((
22                     item.attr("name")?.into(),
23                     item.attr("value").unwrap_or_default().into(),
24                 ))
25             })
26             .collect(),
27     )
28 }
29
30 // this is dumb but it works
31 // we don't use a hashmap because keys may be duplicated
32 // this overwrites the first entry with a certain key
33 fn form_set(form: &mut Vec<(String, String)>, key: &str, value: String) {
34     for entry in form.iter_mut() {
35         if entry.0 == key {
36             entry.1 = value;
37             return;
38         }
39     }
40
41     form.push((key.into(), value));
42 }
43
44 #[tokio::main]
45 async fn main() -> anyhow::Result<()> {
46     dotenv::dotenv()?;
47
48     use std::env;
49
50     let target_host = env::var("DDNS_TARGET_HOST")?;
51     let username = env::var("DDNS_USERNAME")?;
52     let password = env::var("DDNS_PASSWORD")?;
53     let domain_id = env::var("DDNS_DOMAIN_ID")?;
54
55     let target_ip = *dns_lookup::lookup_host(&target_host)?
56         .first()
57         .ok_or(anyhow!("no ip found for {target_host}"))?;
58
59     let client = reqwest::ClientBuilder::new().cookie_store(true).build()?;
60
61     let mut login = form_get(
62         &client,
63         "https://cp.istanco.net/clientarea.php",
64         r#"form[action="https://cp.istanco.net/dologin.php"]"#,
65     )
66     .await?;
67
68     form_set(&mut login, "username", username);
69     form_set(&mut login, "password", password);
70
71     client
72         .post("https://cp.istanco.net/dologin.php")
73         .form(&login)
74         .send()
75         .await?;
76
77     let manage_url = format!("https://cp.istanco.net/index.php?m=br_dnsmanager&id={domain_id}");
78
79     let mut manage = form_get(&client, &manage_url, r#"form[name="br-dnsrecord-manager"]"#).await?;
80
81     form_set(&mut manage, "value[]", target_ip.to_string());
82     form_set(&mut manage, "btnSave", "Save Changes".into());
83
84     client.post(&manage_url).form(&manage).send().await?;
85
86     Ok(())
87 }