--- /dev/null
+use ron::{ de::from_reader, ser::to_writer };\r
+use serde::{ Deserialize, Serialize };\r
+use std::{ fs::File, time };\r
+\r
+use crate::error::Result;\r
+\r
+#[derive(Debug, Clone, Deserialize, Serialize)]\r
+pub struct Config {\r
+ pub delay_between_check: time::Duration,\r
+ pub api_key: String,\r
+ pub fqdn: String,\r
+ pub domains: Vec<String>,\r
+ pub ttl: i32\r
+}\r
+\r
+impl Config {\r
+ pub fn default() -> Self {\r
+ Config { delay_between_check: time::Duration::from_secs(120), api_key: String::from(""), fqdn: String::from(""), domains: Vec::new(), ttl: 300 }\r
+ }\r
+\r
+ pub fn read(file_path: &str) -> Result<Config> {\r
+ match File::open(file_path) {\r
+ Ok(file) => from_reader(file).map_err(|e| e.into()),\r
+ // The file doesn't exit -> create it with default values.\r
+ Err(_) => {\r
+ let file = File::create(file_path)?;\r
+ let default_config = Config::default();\r
+ to_writer(file, &default_config)?;\r
+ Ok(default_config)\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
#![cfg_attr(debug_assertions, allow(unused_variables, unused_imports, dead_code))]
-use std::{ fs::File, net::{ IpAddr, Ipv4Addr }, thread, time };
-use ron::{ de::from_reader, ser::to_writer };
-use serde::{ Deserialize, Serialize };
+use std::{ net::{ IpAddr, Ipv4Addr }, thread, time };
use serde_json::{ Value, json };
-// A generic result of type 'T'.
-type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
+mod error;
+mod config;
-#[derive(Debug)]
-struct Error {
- message: String
-}
-
-impl std::fmt::Display for Error {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "Error: {}", &self.message)
- }
-}
-
-impl std::error::Error for Error { }
-
-#[derive(Debug, Clone, Deserialize, Serialize)]
-struct Config {
- delay_between_check: time::Duration,
- api_key: String,
- fqdn: String,
- domains: Vec<String>,
- ttl: i32
-}
-
-impl Config {
- fn default() -> Self {
- Config { delay_between_check: time::Duration::from_secs(120), api_key: String::from(""), fqdn: String::from(""), domains: Vec::new(), ttl: 300 }
- }
-
- fn read(file_path: &str) -> Result<Config> {
- match File::open(file_path) {
- Ok(file) => from_reader(file).map_err(|e| e.into()),
- // The file doesn't exit -> create it with default values.
- Err(_) => {
- let file = File::create(file_path)?;
- let default_config = Config::default();
- to_writer(file, &default_config)?;
- Ok(default_config)
- }
- }
- }
-}
+use crate::error::{ Result, Error };
+use crate::config::Config;
const FILE_CONF: &str = "config.ron";
}
fn get_real_ip() -> Result<Ipv4Addr> {
-
let url = "https://api.ipify.org";
let client = reqwest::blocking::Client::new();
Ok(resp) =>
if resp.status().is_success() {
let content = resp.text().unwrap();
- match content.parse::<IpAddr>() {
+ match content.parse() {
Ok(IpAddr::V4(ip_v4)) => Ok(ip_v4),
_ => Err(Box::new(Error { message: String::from("Can't parse IPv4 from ipify") }))
}
}
}
+fn get_current_record_ip(api_key: &str, name: &str, fqdn: &str) -> Result<Ipv4Addr> {
+ let json_value = request_livedns_gandi(api_key, &format!("domains/{}/records/{}/A", fqdn, name), Method::Get)?;
+
+ match &json_value["rrset_values"][0] {
+ Value::String(ip_str) =>
+ Ok(ip_str.parse()?),
+ _ =>
+ Result::Err(Box::new(Error { message: format!("Unable to extract the IP from the JSON answer: {}", json_value) }))
+ }
+}
+
+fn update_record_ip(api_key: &str, name: &str, fqdn: &str, ip: Ipv4Addr, ttl: i32) -> Result<()> {
+ let json_body =
+ json!(
+ {
+ "rrset_values": [ format!("{}", ip) ],
+ "rrset_ttl": ttl
+ }
+ );
+
+ let json_value = request_livedns_gandi(api_key, &format!("domains/{}/records/{}/A", fqdn, name), Method::Put(json_body.to_string()))?;
+
+ println!("Update response: {}", json_value);
+
+ Ok(())
+}
+
enum Method {
Put(String),
Get
Err(Box::new(Error { message: format!("Error during request: {:?}", error) }))
}
}
-
-fn get_current_record_ip(api_key: &str, name: &str, fqdn: &str) -> Result<Ipv4Addr> {
- let json_value = request_livedns_gandi(api_key, &format!("domains/{}/records/{}/A", fqdn, name), Method::Get)?;
-
- match &json_value["rrset_values"][0] {
- Value::String(ip_str) =>
- Ok(ip_str.parse()?),
- _ =>
- Result::Err(Box::new(Error { message: format!("Unable to extract the IP from the JSON answer: {}", json_value) }))
- }
-}
-
-fn update_record_ip(api_key: &str, name: &str, fqdn: &str, ip: Ipv4Addr, ttl: i32) -> Result<()> {
- let json_body =
- json!(
- {
- "rrset_values": [ format!("{}", ip) ],
- "rrset_ttl": ttl
- }
- );
-
- let json_value = request_livedns_gandi(api_key, &format!("domains/{}/records/{}/A", fqdn, name), Method::Put(json_body.to_string()))?;
-
- println!("Update response: {}", json_value);
-
- Ok(())
-}