From f01cba4dc5d94d5228332ae5ed5e449bd9ee49e5 Mon Sep 17 00:00:00 2001 From: Rostislav Raykov Date: Tue, 17 Sep 2019 17:33:35 +0200 Subject: [PATCH] feat: Add helper functions for network requests and caching --- src/file.rs | 19 +++++++++++ src/network.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/file.rs create mode 100644 src/network.rs diff --git a/src/file.rs b/src/file.rs new file mode 100644 index 0000000..42a86df --- /dev/null +++ b/src/file.rs @@ -0,0 +1,19 @@ +use failure::Error; +use std::fs::File; +use std::path::PathBuf; +use std::io::prelude::*; + +pub fn read_cache_file(path: &PathBuf) -> Result { + let mut file = File::open(&path)?; + let mut s = String::new(); + file.read_to_string(&mut s)?; + + Ok(s.clone()) +} + +pub fn write_cache_file(path: &PathBuf, ip: &str) -> Result<(), Error> { + let mut file = File::create(&path)?; + file.write_all(ip.as_bytes())?; + + Ok(()) +} \ No newline at end of file diff --git a/src/network.rs b/src/network.rs new file mode 100644 index 0000000..0120257 --- /dev/null +++ b/src/network.rs @@ -0,0 +1,89 @@ +use serde::{Serialize, Deserialize}; +use failure::{Error, format_err}; + +#[derive(Deserialize, Debug)] +struct ListResponse { + success: bool, + errors: Vec, + result: Vec, +} + +#[derive(Deserialize, Debug, PartialEq)] +struct ObjectWithId { + id: String, +} + +#[derive(Serialize, Debug)] +struct UpdateIpData { + id: String, + r#type: String, + name: String, + content: String, +} + +pub fn get_zone_identifier(zone: &str, email: &str, key: &str) -> Result { + let client = reqwest::Client::new(); + let url = format!("https://api.cloudflare.com/client/v4/zones?name={}", zone); + let response: ListResponse = client + .get(&url) + .header("X-Auth-Email", email) + .header("X-Auth-Key", key) + .header("Content-Type", "application/json") + .send()? + .json()?; + + if !response.success { + let err: String = response.errors.iter().map(|s| s.to_owned()).collect(); + return Err(format_err!("API Error: {}", err)); + } + + Ok(response.result[0].id.clone()) +} + +pub fn get_dns_record_id(zone_id: &str, domain: &str, email: &str, key: &str) -> Result { + let client = reqwest::Client::new(); + let url = format!("https://api.cloudflare.com/client/v4/zones/{}/dns_records?name={}", zone_id, domain); + let response: ListResponse = client + .get(&url) + .header("X-Auth-Email", email) + .header("X-Auth-Key", key) + .header("Content-Type", "application/json") + .send()? + .json()?; + + if !response.success { + let err: String = response.errors.iter().map(|s| s.to_owned()).collect(); + return Err(format_err!("API Error: {}", err)); + } + + Ok(response.result[0].id.clone()) +} + +pub fn get_current_ip() -> Result { + Ok(reqwest::Client::new() + .get("http://ipv4.icanhazip.com") + .send()? + .text()?) +} + +pub fn update_ddns(ip: &str, domain: &str, zone_id: &str, record_id: &str, email: &str, key: &str) -> Result<(), Error> { + let client = reqwest::Client::new(); + let url = format!("https://api.cloudflare.com/client/v4/zones/{}/dns_records/{}", zone_id, record_id); + + let update_data = UpdateIpData { + id: zone_id.to_owned(), + r#type: "A".to_owned(), + name: domain.to_owned(), + content: ip.to_owned(), + }; + + client + .put(&url) + .header("X-Auth-Email", email) + .header("X-Auth-Key", key) + .header("Content-Type", "application/json") + .json(&update_data) + .send()?; + + Ok(()) +} \ No newline at end of file