From 99acbc739d1e03581f523564d66fc6a963c4cf28 Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Wed, 8 Apr 2026 19:01:12 -0700 Subject: [PATCH 1/8] domain services one one page --- src/domain_services/{cloudflare => }/README.md | 0 src/domain_services/{cloudflare/mod.rs => cloudflare.rs} | 0 src/domain_services/{dyndns2/mod.rs => dyndns2.rs} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/domain_services/{cloudflare => }/README.md (100%) rename src/domain_services/{cloudflare/mod.rs => cloudflare.rs} (100%) rename src/domain_services/{dyndns2/mod.rs => dyndns2.rs} (100%) diff --git a/src/domain_services/cloudflare/README.md b/src/domain_services/README.md similarity index 100% rename from src/domain_services/cloudflare/README.md rename to src/domain_services/README.md diff --git a/src/domain_services/cloudflare/mod.rs b/src/domain_services/cloudflare.rs similarity index 100% rename from src/domain_services/cloudflare/mod.rs rename to src/domain_services/cloudflare.rs diff --git a/src/domain_services/dyndns2/mod.rs b/src/domain_services/dyndns2.rs similarity index 100% rename from src/domain_services/dyndns2/mod.rs rename to src/domain_services/dyndns2.rs From dc1825c3eca0489ad4b133ff7ce6c77a1e8d0cda Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Wed, 8 Apr 2026 19:21:31 -0700 Subject: [PATCH 2/8] move all domain services to the same directory, config import is a code smell --- Cargo.toml | 6 +++--- src/domain_services/cloudflare.rs | 16 +++++++++++++++- src/domain_services/dyndns2.rs | 11 ++++++++++- src/domain_services/mod.rs | 9 +++++++++ src/ip_services/mod.rs | 3 ++- src/toolkit/config.rs | 4 ++-- src/toolkit/domain_services/cloudflare.rs | 17 ----------------- src/toolkit/domain_services/dyndns2.rs | 9 --------- src/toolkit/domain_services/mod.rs | 22 ---------------------- src/toolkit/ip_services.rs | 1 - src/toolkit/mod.rs | 2 -- 11 files changed, 41 insertions(+), 59 deletions(-) delete mode 100644 src/toolkit/domain_services/cloudflare.rs delete mode 100644 src/toolkit/domain_services/dyndns2.rs delete mode 100644 src/toolkit/domain_services/mod.rs delete mode 100644 src/toolkit/ip_services.rs diff --git a/Cargo.toml b/Cargo.toml index 281ad06..4f30bb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "update_dns_records" -version = "0.1.0" +version = "0.2.0" edition = "2021" [dependencies] @@ -8,12 +8,12 @@ serde_json = "1" bytes = "1" serde = { version = "1.0", features = ["derive"] } tokio = { version = "1", features = ["full"] } -tokio-native-tls = { version = "0.3.1" } +tokio-native-tls = { version = "0.3" } hyper-util = { version = "0.1", features = ["full"] } native-tls = "0.2" hyper = { version = "1", features = ["full"] } http-body-util = "0.1" -rand = "0.8.5" +rand = "0.8" base64 = { version = "0.21" } [features] diff --git a/src/domain_services/cloudflare.rs b/src/domain_services/cloudflare.rs index 8f52b3e..188a6ee 100644 --- a/src/domain_services/cloudflare.rs +++ b/src/domain_services/cloudflare.rs @@ -12,10 +12,24 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::toolkit::config::Config; -use crate::toolkit::domain_services::cloudflare::Cloudflare; +// use crate::toolkit::domain_services::cloudflare::Cloudflare; use crate::toolkit::requests::{request_http1_tls_response, ResponseJson}; use crate::toolkit::results::{DomainResult, UpdateIpResults}; +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct Cloudflare { + pub api_token: String, + pub comment: Option, + pub dns_record_id: String, + pub email: String, + pub name: String, + pub proxied: Option, + pub r#type: String, + pub tags: Option>, + pub ttl: Option, + pub zone_id: String, +} + #[derive(Clone, Serialize, Debug)] pub struct CloudflareRequestBody { pub content: String, diff --git a/src/domain_services/dyndns2.rs b/src/domain_services/dyndns2.rs index 358c214..359c5ab 100644 --- a/src/domain_services/dyndns2.rs +++ b/src/domain_services/dyndns2.rs @@ -12,12 +12,21 @@ use bytes::Bytes; use http_body_util::Full; use hyper::Request; use std::collections::HashMap; +use serde::{Deserialize, Serialize}; use crate::toolkit::config::Config; -use crate::toolkit::domain_services::dyndns2::Dyndns2; +// use crate::toolkit::domain_services::dyndns2::Dyndns2; use crate::toolkit::requests::{request_http1_tls_response, ResponseJson}; use crate::toolkit::results::{DomainResult, UpdateIpResults}; +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct Dyndns2 { + pub hostname: String, + pub password: String, + pub service_uri: String, + pub username: String, +} + const CLIENT_HEADER_VALUE: &str = "hyper/1.0 rust-client"; // must return results diff --git a/src/domain_services/mod.rs b/src/domain_services/mod.rs index 43a03d2..d8e0c4b 100644 --- a/src/domain_services/mod.rs +++ b/src/domain_services/mod.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use serde::{Deserialize, Serialize}; use crate::toolkit::config::Config; use crate::toolkit::results::{DomainResult, IpServiceResult, UpdateIpResults}; @@ -8,6 +9,14 @@ mod cloudflare; #[cfg(feature = "dyndns2")] mod dyndns2; +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct DomainServices { + #[cfg(feature = "cloudflare")] + pub cloudflare: Option>, + #[cfg(feature = "dyndns2")] + pub dyndns2: Option>, +} + pub async fn update_domains( config: &Config, prev_results: &Result, diff --git a/src/ip_services/mod.rs b/src/ip_services/mod.rs index 7c6ccd2..fd4374d 100644 --- a/src/ip_services/mod.rs +++ b/src/ip_services/mod.rs @@ -1,11 +1,12 @@ use rand::{thread_rng, Rng}; use crate::toolkit::config::Config; -use crate::toolkit::ip_services::IpServices; use crate::toolkit::results::{IpServiceResult, UpdateIpResults}; mod address_as_body; +pub type IpServices = Vec<(String, String)>; + pub async fn fetch_service_results( config: &Config, prev_results: &Result, diff --git a/src/toolkit/config.rs b/src/toolkit/config.rs index f6ab0f8..9eade44 100644 --- a/src/toolkit/config.rs +++ b/src/toolkit/config.rs @@ -3,8 +3,8 @@ use serde_json; use std::path; use tokio::fs; -use crate::toolkit::domain_services::DomainServices; -use crate::toolkit::ip_services::IpServices; +use crate::ip_services::IpServices; +use crate::domain_services::DomainServices; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Config { diff --git a/src/toolkit/domain_services/cloudflare.rs b/src/toolkit/domain_services/cloudflare.rs deleted file mode 100644 index 6974b8c..0000000 --- a/src/toolkit/domain_services/cloudflare.rs +++ /dev/null @@ -1,17 +0,0 @@ -use serde::{Deserialize, Serialize}; - -// following type is based on: -// https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-update-dns-record -#[derive(Clone, Serialize, Deserialize, Debug)] -pub struct Cloudflare { - pub api_token: String, - pub comment: Option, - pub dns_record_id: String, - pub email: String, - pub name: String, - pub proxied: Option, - pub r#type: String, - pub tags: Option>, - pub ttl: Option, - pub zone_id: String, -} diff --git a/src/toolkit/domain_services/dyndns2.rs b/src/toolkit/domain_services/dyndns2.rs deleted file mode 100644 index 3795593..0000000 --- a/src/toolkit/domain_services/dyndns2.rs +++ /dev/null @@ -1,9 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Serialize, Deserialize, Debug)] -pub struct Dyndns2 { - pub hostname: String, - pub password: String, - pub service_uri: String, - pub username: String, -} diff --git a/src/toolkit/domain_services/mod.rs b/src/toolkit/domain_services/mod.rs deleted file mode 100644 index c59c3d5..0000000 --- a/src/toolkit/domain_services/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -use serde::{Deserialize, Serialize}; - -// add domain services here -// beware of hydra - -#[cfg(feature = "cloudflare")] -pub mod cloudflare; -#[cfg(feature = "dyndns2")] -pub mod dyndns2; - -#[cfg(feature = "cloudflare")] -use cloudflare::Cloudflare; -#[cfg(feature = "dyndns2")] -use dyndns2::Dyndns2; - -#[derive(Clone, Serialize, Deserialize, Debug)] -pub struct DomainServices { - #[cfg(feature = "cloudflare")] - pub cloudflare: Option>, - #[cfg(feature = "dyndns2")] - pub dyndns2: Option>, -} diff --git a/src/toolkit/ip_services.rs b/src/toolkit/ip_services.rs deleted file mode 100644 index 92a8968..0000000 --- a/src/toolkit/ip_services.rs +++ /dev/null @@ -1 +0,0 @@ -pub type IpServices = Vec<(String, String)>; diff --git a/src/toolkit/mod.rs b/src/toolkit/mod.rs index f9d9637..5abe783 100644 --- a/src/toolkit/mod.rs +++ b/src/toolkit/mod.rs @@ -1,5 +1,3 @@ pub mod config; -pub mod domain_services; -pub mod ip_services; pub mod requests; pub mod results; From 6752dad5a1fe0082872104290b15a96ba22172a8 Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Thu, 9 Apr 2026 15:42:44 -0700 Subject: [PATCH 3/8] too much crossover with config module --- .DS_Store | Bin 0 -> 6148 bytes src/{toolkit => }/config.rs | 2 +- src/domain_services/README.md | 13 ------------- src/domain_services/cloudflare.rs | 19 ++++++++----------- src/domain_services/dyndns2.rs | 14 ++++++-------- src/domain_services/mod.rs | 24 ++++++++++++++++++------ src/ip_services/address_as_body.rs | 2 +- src/ip_services/mod.rs | 7 +++---- src/main.rs | 17 +++++++++-------- src/{toolkit => }/requests.rs | 0 src/{toolkit => }/results.rs | 11 +++++------ src/toolkit/mod.rs | 3 --- 12 files changed, 51 insertions(+), 61 deletions(-) create mode 100644 .DS_Store rename src/{toolkit => }/config.rs (100%) delete mode 100644 src/domain_services/README.md rename src/{toolkit => }/requests.rs (100%) rename src/{toolkit => }/results.rs (87%) delete mode 100644 src/toolkit/mod.rs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..11236f1c97ff89c2e91743ea98b00234516879fb GIT binary patch literal 6148 zcmeHKyGjE=6g^{7L~K%8PHkZb_yJ2uIi`l_>YZ%(>5b z9N3v10BO~gOJELQ#wM6V84+=hhK@X0FzFcQctnF2?5lQUphI-Y+K*AA!V(wwvi|$a zu4!vV&v3&%?U>VGffjdo!!!3-(|T2WVx*$~fmsW5)Js||tu3`Zqg!V07?-M2$N6d2 zE1z{_O@~NdtSJ}>27-ZL;14puJ6mLSViQ>Fo4pO-CvWqYnmx zfguAEGv{*uZ}`cKKJtepVFd%hz&~RkP1o1!6*uK~>$mO6U7Oi%*+e9-7llH7@Do5o g&XH3MT0D!+yuz_Jlu^X5<;3_AP(q>$27ZBocl0_gWB>pF literal 0 HcmV?d00001 diff --git a/src/toolkit/config.rs b/src/config.rs similarity index 100% rename from src/toolkit/config.rs rename to src/config.rs index 9eade44..4facf16 100644 --- a/src/toolkit/config.rs +++ b/src/config.rs @@ -3,8 +3,8 @@ use serde_json; use std::path; use tokio::fs; -use crate::ip_services::IpServices; use crate::domain_services::DomainServices; +use crate::ip_services::IpServices; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Config { diff --git a/src/domain_services/README.md b/src/domain_services/README.md deleted file mode 100644 index 4c32409..0000000 --- a/src/domain_services/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Cloudflare - -## DNS Records - -List DNS records at cloudflare. -```sh -curl --request GET \ - --url https://api.cloudflare.com/client/v4/zones//dns_records \ - --header 'Content-Type: application/json' \ - --header 'X-Auth-Email: ' \ - --header 'Authorization: Bearer ' -``` - diff --git a/src/domain_services/cloudflare.rs b/src/domain_services/cloudflare.rs index 188a6ee..7603b39 100644 --- a/src/domain_services/cloudflare.rs +++ b/src/domain_services/cloudflare.rs @@ -11,23 +11,22 @@ use hyper::Request; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use crate::toolkit::config::Config; -// use crate::toolkit::domain_services::cloudflare::Cloudflare; -use crate::toolkit::requests::{request_http1_tls_response, ResponseJson}; -use crate::toolkit::results::{DomainResult, UpdateIpResults}; +use crate::domain_services::DomainServices; +use crate::requests::{request_http1_tls_response, ResponseJson}; +use crate::results::{DomainResult, UpdateIpResults}; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Cloudflare { pub api_token: String, - pub comment: Option, pub dns_record_id: String, pub email: String, pub name: String, - pub proxied: Option, pub r#type: String, + pub zone_id: String, + pub comment: Option, + pub proxied: Option, pub tags: Option>, pub ttl: Option, - pub zone_id: String, } #[derive(Clone, Serialize, Debug)] @@ -51,12 +50,12 @@ pub struct CloudflareMinimalResponseBody { } pub async fn update_domains( - config: &Config, + domain_services: &DomainServices, prev_results: &Result, domain_results: &mut HashMap, ip_address: &str, ) { - let domains = match &config.domain_services.cloudflare { + let domains = match domain_services.cloudflare { Some(domains) => domains, _ => return, }; @@ -79,9 +78,7 @@ pub async fn update_domains( } } - // build domain result domain_result = build_domain_result(&domain, ip_address).await; - // write over previous entry domain_results.insert(hostname, domain_result); } } diff --git a/src/domain_services/dyndns2.rs b/src/domain_services/dyndns2.rs index 359c5ab..7110d20 100644 --- a/src/domain_services/dyndns2.rs +++ b/src/domain_services/dyndns2.rs @@ -11,13 +11,12 @@ use base64::{engine::general_purpose, Engine as _}; use bytes::Bytes; use http_body_util::Full; use hyper::Request; -use std::collections::HashMap; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; -use crate::toolkit::config::Config; -// use crate::toolkit::domain_services::dyndns2::Dyndns2; -use crate::toolkit::requests::{request_http1_tls_response, ResponseJson}; -use crate::toolkit::results::{DomainResult, UpdateIpResults}; +use crate::domain_services::DomainServices; +use crate::requests::{request_http1_tls_response, ResponseJson}; +use crate::results::{DomainResult, UpdateIpResults}; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Dyndns2 { @@ -29,14 +28,13 @@ pub struct Dyndns2 { const CLIENT_HEADER_VALUE: &str = "hyper/1.0 rust-client"; -// must return results pub async fn update_domains( - config: &Config, + domain_services: &DomainServices, prev_results: &Result, domain_results: &mut HashMap, ip_address: &str, ) { - let domains = match &config.domain_services.dyndns2 { + let domains = match domain_services.dyndns2 { Some(domains) => domains, _ => return, }; diff --git a/src/domain_services/mod.rs b/src/domain_services/mod.rs index d8e0c4b..151f104 100644 --- a/src/domain_services/mod.rs +++ b/src/domain_services/mod.rs @@ -1,8 +1,8 @@ -use std::collections::HashMap; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; -use crate::toolkit::config::Config; -use crate::toolkit::results::{DomainResult, IpServiceResult, UpdateIpResults}; +use crate::config::Config; +use crate::results::{DomainResult, IpServiceResult, UpdateIpResults}; #[cfg(feature = "cloudflare")] mod cloudflare; @@ -18,7 +18,7 @@ pub struct DomainServices { } pub async fn update_domains( - config: &Config, + domain_services: &DomainServices, prev_results: &Result, ip_service_result: &IpServiceResult, ) -> Result, String> { @@ -30,10 +30,22 @@ pub async fn update_domains( let mut domain_results = HashMap::::new(); #[cfg(feature = "dyndns2")] - dyndns2::update_domains(config, prev_results, &mut domain_results, &ip_address).await; + dyndns2::update_domains( + domain_services, + prev_results, + &mut domain_results, + &ip_address, + ) + .await; #[cfg(feature = "cloudflare")] - cloudflare::update_domains(config, prev_results, &mut domain_results, &ip_address).await; + cloudflare::update_domains( + domain_services, + prev_results, + &mut domain_results, + &ip_address, + ) + .await; Ok(domain_results) } diff --git a/src/ip_services/address_as_body.rs b/src/ip_services/address_as_body.rs index 1f90f2e..951e9af 100644 --- a/src/ip_services/address_as_body.rs +++ b/src/ip_services/address_as_body.rs @@ -3,7 +3,7 @@ use http_body_util::Full; use hyper::Request; use std::net; -use crate::toolkit::requests::{get_host_and_authority, request_http1_tls_response, ResponseJson}; +use crate::requests::{get_host_and_authority, request_http1_tls_response, ResponseJson}; pub async fn request_address_as_body(service: &str) -> Result { let request = match create_request_with_empty_body(service) { diff --git a/src/ip_services/mod.rs b/src/ip_services/mod.rs index fd4374d..1c0df14 100644 --- a/src/ip_services/mod.rs +++ b/src/ip_services/mod.rs @@ -1,14 +1,13 @@ use rand::{thread_rng, Rng}; -use crate::toolkit::config::Config; -use crate::toolkit::results::{IpServiceResult, UpdateIpResults}; +use crate::results::{IpServiceResult, UpdateIpResults}; mod address_as_body; pub type IpServices = Vec<(String, String)>; pub async fn fetch_service_results( - config: &Config, + ip_services: &IpServices, prev_results: &Result, ) -> Result { let service = match prev_results { @@ -16,7 +15,7 @@ pub async fn fetch_service_results( _ => "previous-results-do-not-exist", }; - let (ip_service, response_type) = match get_random_ip_service(&config.ip_services, service) { + let (ip_service, response_type) = match get_random_ip_service(ip_services, service) { Some(r) => r, _ => return Err("failed to find ip service".to_string()), }; diff --git a/src/main.rs b/src/main.rs index 5c09ac7..8b74d06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,9 @@ use std::{env, path}; +mod config; mod domain_services; mod ip_services; -mod toolkit; - -use crate::toolkit::{config, results}; +mod results; #[tokio::main] async fn main() -> Result<(), String> { @@ -22,13 +21,15 @@ async fn main() -> Result<(), String> { let prev_results = results::read_results_from_disk(&config).await; - let ip_service_result = match ip_services::fetch_service_results(&config, &prev_results).await { - Ok(ip_result) => ip_result, - Err(e) => return Err(e), - }; + let ip_service_result = + match ip_services::fetch_service_results(&config.ip_services, &prev_results).await { + Ok(ip_result) => ip_result, + Err(e) => return Err(e), + }; let domain_service_results = - domain_services::update_domains(&config, &prev_results, &ip_service_result).await; + domain_services::update_domains(&config.domain_services, &prev_results, &ip_service_result) + .await; results::write_results_to_disk(&config, ip_service_result, domain_service_results).await } diff --git a/src/toolkit/requests.rs b/src/requests.rs similarity index 100% rename from src/toolkit/requests.rs rename to src/requests.rs diff --git a/src/toolkit/results.rs b/src/results.rs similarity index 87% rename from src/toolkit/results.rs rename to src/results.rs index df7073d..5ed7c42 100644 --- a/src/toolkit/results.rs +++ b/src/results.rs @@ -2,8 +2,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use tokio::fs; -use crate::toolkit::config::Config; -use crate::toolkit::requests::ResponseJson; +use crate::requests::ResponseJson; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct IpServiceResult { @@ -63,8 +62,8 @@ impl UpdateIpResults { } } -pub async fn read_results_from_disk(config: &Config) -> Result { - let json_as_str = match fs::read_to_string(&config.results_filepath).await { +pub async fn read_results_from_disk(results_filepath: &PathBuf) -> Result { + let json_as_str = match fs::read_to_string(results_filepath).await { Ok(json_str) => json_str, Err(e) => return Err(e.to_string()), }; @@ -76,7 +75,7 @@ pub async fn read_results_from_disk(config: &Config) -> Result, String>, ) -> Result<(), String> { @@ -90,7 +89,7 @@ pub async fn write_results_to_disk( Err(e) => return Err(e.to_string()), }; - if let Err(e) = fs::write(&config.results_filepath, json_str).await { + if let Err(e) = fs::write(results_filepath, json_str).await { return Err(e.to_string()); }; diff --git a/src/toolkit/mod.rs b/src/toolkit/mod.rs deleted file mode 100644 index 5abe783..0000000 --- a/src/toolkit/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod config; -pub mod requests; -pub mod results; From cb4f4e2e4ef1c7315e42fed7752a1afe423c100b Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Thu, 9 Apr 2026 15:50:28 -0700 Subject: [PATCH 4/8] ResponseDetails because responses are not always json --- src/domain_services/cloudflare.rs | 6 +++--- src/domain_services/dyndns2.rs | 6 +++--- src/domain_services/mod.rs | 1 - src/ip_services/address_as_body.rs | 6 +++--- src/main.rs | 10 ++++++++-- src/requests.rs | 16 ++++++++++------ src/results.rs | 7 ++++--- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/domain_services/cloudflare.rs b/src/domain_services/cloudflare.rs index 7603b39..e966128 100644 --- a/src/domain_services/cloudflare.rs +++ b/src/domain_services/cloudflare.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::domain_services::DomainServices; -use crate::requests::{request_http1_tls_response, ResponseJson}; +use crate::requests::{request_http1_tls_response, ResponseDetails}; use crate::results::{DomainResult, UpdateIpResults}; #[derive(Clone, Serialize, Deserialize, Debug)] @@ -55,7 +55,7 @@ pub async fn update_domains( domain_results: &mut HashMap, ip_address: &str, ) { - let domains = match domain_services.cloudflare { + let domains = match &domain_services.cloudflare { Some(domains) => domains, _ => return, }; @@ -110,7 +110,7 @@ async fn build_domain_result(domain: &Cloudflare, ip_address: &str) -> DomainRes domain_result } -fn verify_resposne(res: &ResponseJson) -> bool { +fn verify_resposne(res: &ResponseDetails) -> bool { if res.status_code != 200 { return false; } diff --git a/src/domain_services/dyndns2.rs b/src/domain_services/dyndns2.rs index 7110d20..209663e 100644 --- a/src/domain_services/dyndns2.rs +++ b/src/domain_services/dyndns2.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::domain_services::DomainServices; -use crate::requests::{request_http1_tls_response, ResponseJson}; +use crate::requests::{request_http1_tls_response, ResponseDetails}; use crate::results::{DomainResult, UpdateIpResults}; #[derive(Clone, Serialize, Deserialize, Debug)] @@ -34,7 +34,7 @@ pub async fn update_domains( domain_results: &mut HashMap, ip_address: &str, ) { - let domains = match domain_services.dyndns2 { + let domains = match &domain_services.dyndns2 { Some(domains) => domains, _ => return, }; @@ -89,7 +89,7 @@ async fn build_domain_result(domain: &Dyndns2, ip_address: &str) -> DomainResult domain_result } -fn verify_resposne(res: &ResponseJson) -> bool { +fn verify_resposne(res: &ResponseDetails) -> bool { if res.status_code < 200 || res.status_code >= 300 { return false; } diff --git a/src/domain_services/mod.rs b/src/domain_services/mod.rs index 151f104..d0a8087 100644 --- a/src/domain_services/mod.rs +++ b/src/domain_services/mod.rs @@ -1,7 +1,6 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use crate::config::Config; use crate::results::{DomainResult, IpServiceResult, UpdateIpResults}; #[cfg(feature = "cloudflare")] diff --git a/src/ip_services/address_as_body.rs b/src/ip_services/address_as_body.rs index 951e9af..fe0913b 100644 --- a/src/ip_services/address_as_body.rs +++ b/src/ip_services/address_as_body.rs @@ -3,9 +3,9 @@ use http_body_util::Full; use hyper::Request; use std::net; -use crate::requests::{get_host_and_authority, request_http1_tls_response, ResponseJson}; +use crate::requests::{get_host_and_authority, request_http1_tls_response, ResponseDetails}; -pub async fn request_address_as_body(service: &str) -> Result { +pub async fn request_address_as_body(service: &str) -> Result { let request = match create_request_with_empty_body(service) { Ok(req) => req, Err(e) => return Err(e), @@ -17,7 +17,7 @@ pub async fn request_address_as_body(service: &str) -> Result Result { +pub async fn get_ip_address_from_body(response_json: &ResponseDetails) -> Result { if response_json.status_code != 200 { return Err("response_json was not okay".to_string()); } diff --git a/src/main.rs b/src/main.rs index 8b74d06..003fd2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::{env, path}; mod config; mod domain_services; mod ip_services; +mod requests; mod results; #[tokio::main] @@ -19,7 +20,7 @@ async fn main() -> Result<(), String> { Err(e) => return Err(e), }; - let prev_results = results::read_results_from_disk(&config).await; + let prev_results = results::read_results_from_disk(&config.results_filepath).await; let ip_service_result = match ip_services::fetch_service_results(&config.ip_services, &prev_results).await { @@ -31,5 +32,10 @@ async fn main() -> Result<(), String> { domain_services::update_domains(&config.domain_services, &prev_results, &ip_service_result) .await; - results::write_results_to_disk(&config, ip_service_result, domain_service_results).await + results::write_results_to_disk( + &config.results_filepath, + ip_service_result, + domain_service_results, + ) + .await } diff --git a/src/requests.rs b/src/requests.rs index df40c39..18ad8fb 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -10,12 +10,16 @@ use std::io; use tokio::net::TcpStream; #[derive(Clone, Serialize, Deserialize, Debug)] -pub struct ResponseJson { +pub struct ResponseDetails { pub status_code: u16, + // content type + // content encoding pub body: String, } -pub async fn request_http1_tls_response(req: Request>) -> Result { +pub async fn request_http1_tls_response( + req: Request>, +) -> Result { let (host, authority) = match get_host_and_authority(&req.uri()) { Some(stream) => stream, _ => return Err("failed to get authority from uri".to_string()), @@ -65,8 +69,6 @@ pub fn get_host_and_authority(uri: &Uri) -> Option<(&str, String)> { Some((host, authority)) } -// this has multiple "types" of errors -// signal that it is an inappropriate grouping? async fn create_tls_stream( host: &str, addr: &str, @@ -91,7 +93,9 @@ async fn create_tls_stream( Ok(tls_stream) } -async fn convert_response_to_json_struct(res: Response) -> Result { +async fn convert_response_to_json_struct( + res: Response, +) -> Result { let status = res.status().as_u16(); let body_str = match response_body_to_string(res).await { @@ -99,7 +103,7 @@ async fn convert_response_to_json_struct(res: Response) -> Result return Err(e), }; - Ok(ResponseJson { + Ok(ResponseDetails { status_code: status, body: body_str, }) diff --git a/src/results.rs b/src/results.rs index 5ed7c42..e20d380 100644 --- a/src/results.rs +++ b/src/results.rs @@ -1,14 +1,15 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use std::path::PathBuf; use tokio::fs; -use crate::requests::ResponseJson; +use crate::requests::ResponseDetails; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct IpServiceResult { pub service: String, pub ip_address: Option, - pub response: Option, + pub response: Option, } impl IpServiceResult { @@ -25,7 +26,7 @@ impl IpServiceResult { pub struct DomainResult { pub hostname: String, pub ip_address: Option, - pub response: Option, + pub response: Option, pub errors: Vec, } From c7b9a63d58f433db8213dd8e7675a6603280f274 Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Thu, 9 Apr 2026 16:03:45 -0700 Subject: [PATCH 5/8] put request in ip_services into requests, it's generic enough --- src/ip_services/address_as_body.rs | 30 +++--------------------------- src/requests.rs | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/ip_services/address_as_body.rs b/src/ip_services/address_as_body.rs index fe0913b..1ddcdac 100644 --- a/src/ip_services/address_as_body.rs +++ b/src/ip_services/address_as_body.rs @@ -1,9 +1,8 @@ -use bytes::Bytes; -use http_body_util::Full; -use hyper::Request; use std::net; -use crate::requests::{get_host_and_authority, request_http1_tls_response, ResponseDetails}; +use crate::requests::{ + create_request_with_empty_body, request_http1_tls_response, ResponseDetails, +}; pub async fn request_address_as_body(service: &str) -> Result { let request = match create_request_with_empty_body(service) { @@ -30,26 +29,3 @@ pub async fn get_ip_address_from_body(response_json: &ResponseDetails) -> Result Ok(ip_address) } - -fn create_request_with_empty_body(url_string: &str) -> Result>, String> { - let uri = match hyper::Uri::try_from(url_string) { - Ok(u) => u, - Err(e) => return Err(e.to_string()), - }; - - let (_, authority) = match get_host_and_authority(&uri) { - Some(u) => u.clone(), - _ => return Err("authority not found in url".to_string()), - }; - - let req = match Request::builder() - .uri(uri) - .header(hyper::header::HOST, authority.as_str()) - .body(Full::new(bytes::Bytes::new())) - { - Ok(r) => r, - Err(e) => return Err(e.to_string()), - }; - - Ok(req) -} diff --git a/src/requests.rs b/src/requests.rs index 18ad8fb..d559858 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -123,3 +123,26 @@ async fn response_body_to_string(response: Response) -> Result Result>, String> { + let uri = match hyper::Uri::try_from(url_string) { + Ok(u) => u, + Err(e) => return Err(e.to_string()), + }; + + let (_, authority) = match get_host_and_authority(&uri) { + Some(u) => u.clone(), + _ => return Err("authority not found in url".to_string()), + }; + + let req = match Request::builder() + .uri(uri) + .header(hyper::header::HOST, authority.as_str()) + .body(Full::new(bytes::Bytes::new())) + { + Ok(r) => r, + Err(e) => return Err(e.to_string()), + }; + + Ok(req) +} From e6d34b7f230568029bbf66d1c6ea5dc4ae084f6d Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Fri, 10 Apr 2026 01:00:30 -0700 Subject: [PATCH 6/8] add to gitignore --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 2 ++ 2 files changed, 2 insertions(+) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 11236f1c97ff89c2e91743ea98b00234516879fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyGjE=6g^{7L~K%8PHkZb_yJ2uIi`l_>YZ%(>5b z9N3v10BO~gOJELQ#wM6V84+=hhK@X0FzFcQctnF2?5lQUphI-Y+K*AA!V(wwvi|$a zu4!vV&v3&%?U>VGffjdo!!!3-(|T2WVx*$~fmsW5)Js||tu3`Zqg!V07?-M2$N6d2 zE1z{_O@~NdtSJ}>27-ZL;14puJ6mLSViQ>Fo4pO-CvWqYnmx zfguAEGv{*uZ}`cKKJtepVFd%hz&~RkP1o1!6*uK~>$mO6U7Oi%*+e9-7llH7@Do5o g&XH3MT0D!+yuz_Jlu^X5<;3_AP(q>$27ZBocl0_gWB>pF diff --git a/.gitignore b/.gitignore index aab3793..71cead5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ Cargo.lock *.json !*.example.json *.env + +.DS_Store From 8d0954f00605ff928f6c9f4a91e01d49457bec77 Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Fri, 10 Apr 2026 01:43:32 -0700 Subject: [PATCH 7/8] format --- src/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config.rs b/src/config.rs index 4facf16..6d834af 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,3 +42,4 @@ pub async fn from_path(file_path: &path::Path) -> Result { Ok(config) } + \ No newline at end of file From b63b0acde6024cf60ebb2ddc01dcb5db8d453a56 Mon Sep 17 00:00:00 2001 From: Taylor Vann Date: Fri, 10 Apr 2026 02:06:34 -0700 Subject: [PATCH 8/8] update dependencies --- Cargo.toml | 10 +++++----- LICENSE | 2 +- src/config.rs | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4f30bb8..f5432ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,17 +4,17 @@ version = "0.2.0" edition = "2021" [dependencies] -serde_json = "1" -bytes = "1" +serde_json = "1.0" +bytes = "1.11" serde = { version = "1.0", features = ["derive"] } -tokio = { version = "1", features = ["full"] } +tokio = { version = "1.51", features = ["full"] } tokio-native-tls = { version = "0.3" } hyper-util = { version = "0.1", features = ["full"] } native-tls = "0.2" -hyper = { version = "1", features = ["full"] } +hyper = { version = "1.9", features = ["full"] } http-body-util = "0.1" rand = "0.8" -base64 = { version = "0.21" } +base64 = { version = "0.22" } [features] default = ["cloudflare", "dyndns2"] diff --git a/LICENSE b/LICENSE index 5376ba3..3f3cce2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2024, W-lfpup +Copyright (c) 2024, Taylor Vann Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/config.rs b/src/config.rs index 6d834af..4facf16 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,4 +42,3 @@ pub async fn from_path(file_path: &path::Path) -> Result { Ok(config) } - \ No newline at end of file