From 27a60d3ac2a4fb0338a6350215f2dcbb6afac724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Barmore-Gen=C3=A7?= Date: Wed, 1 Feb 2023 23:19:57 -0500 Subject: [PATCH] Add new IP source "seeip" (#90) --- example.toml | 5 ++-- src/config.rs | 1 + src/ip_source/Readme.md | 2 +- src/ip_source/mod.rs | 1 + src/ip_source/seeip.rs | 53 +++++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 ++ 6 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 src/ip_source/seeip.rs diff --git a/example.toml b/example.toml index 7b10121..070f262 100644 --- a/example.toml +++ b/example.toml @@ -19,8 +19,9 @@ ttl = 300 # Ipify is used by default. If you want to change it, uncomment the one you want # to use. # -# ip_source = "Ipify" -# ip_source = "Icanhazip" +#ip_source = "Ipify" # An open source and public service. https://github.com/rdegges/ipify-api +#ip_source = "Icanhazip" # A free service, currently run by Cloudflare. https://major.io/2021/06/06/a-new-future-for-icanhazip/ +#ip_source = "SeeIP" # A free service, run by UNVIO, LLC. https://seeip.org/ # For every domain or subdomain you want to update, create an entry below. diff --git a/src/config.rs b/src/config.rs index b804bcb..2cfbc20 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,6 +25,7 @@ fn default_ttl() -> u32 { pub enum IPSourceName { Ipify, Icanhazip, + SeeIP, } impl Default for IPSourceName { diff --git a/src/ip_source/Readme.md b/src/ip_source/Readme.md index 2b641ea..9e44ae7 100644 --- a/src/ip_source/Readme.md +++ b/src/ip_source/Readme.md @@ -2,5 +2,5 @@ The IP sources. These are APIs that we can query to get the IP address of the current service. The tests under this directory are all marked to be skipped, the tests hit the -actual APIs and can be flakey in CI. Make sure to run the tests manually if you +actual APIs and can be flaky in CI. Make sure to run the tests manually if you have to modify the code. diff --git a/src/ip_source/mod.rs b/src/ip_source/mod.rs index 7dcf7c5..fe39cc1 100644 --- a/src/ip_source/mod.rs +++ b/src/ip_source/mod.rs @@ -1,3 +1,4 @@ pub(crate) mod icanhazip; pub(crate) mod ip_source; pub(crate) mod ipify; +pub(crate) mod seeip; diff --git a/src/ip_source/seeip.rs b/src/ip_source/seeip.rs new file mode 100644 index 0000000..9945e96 --- /dev/null +++ b/src/ip_source/seeip.rs @@ -0,0 +1,53 @@ +use async_trait::async_trait; + +use super::ip_source::IPSource; + +pub(crate) struct IPSourceSeeIP; + +async fn get_ip(api_url: &str) -> anyhow::Result { + let response = reqwest::get(api_url).await?; + let text = response.text().await?; + Ok(text) +} + +#[async_trait] +impl IPSource for IPSourceSeeIP { + async fn get_ipv4(&self) -> anyhow::Result { + get_ip("https://ip4.seeip.org").await + } + async fn get_ipv6(&self) -> anyhow::Result { + get_ip("https://ip6.seeip.org").await + } +} + +#[cfg(test)] +mod tests { + use regex::Regex; + + use super::IPSource; + use super::IPSourceSeeIP; + + #[tokio::test] + #[ignore] + async fn ipv4_test() { + let ipv4 = IPSourceSeeIP + .get_ipv4() + .await + .expect("Failed to get the IP address"); + assert!(Regex::new(r"^\d+[.]\d+[.]\d+[.]\d+$") + .unwrap() + .is_match(ipv4.as_str())) + } + + #[tokio::test] + #[ignore] + async fn ipv6_test() { + let ipv6 = IPSourceSeeIP + .get_ipv6() + .await + .expect("Failed to get the IP address"); + assert!(Regex::new(r"^([0-9a-fA-F]*:){7}[0-9a-fA-F]*$") + .unwrap() + .is_match(ipv6.as_str())) + } +} diff --git a/src/main.rs b/src/main.rs index 2625df4..4ff6e08 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use crate::ip_source::{ip_source::IPSource, ipify::IPSourceIpify}; use clap::Parser; use config::IPSourceName; use ip_source::icanhazip::IPSourceIcanhazip; +use ip_source::seeip::IPSourceSeeIP; use opts::Opts; use reqwest::{header, Client, ClientBuilder, StatusCode}; use serde::Serialize; @@ -158,6 +159,7 @@ async fn main() -> anyhow::Result<()> { let ip_source: Box = match conf.ip_source { IPSourceName::Ipify => Box::new(IPSourceIpify), IPSourceName::Icanhazip => Box::new(IPSourceIcanhazip), + IPSourceName::SeeIP => Box::new(IPSourceSeeIP), }; config::validate_config(&conf).die_with(|error| format!("Invalid config: {}", error)); run("https://api.gandi.net", &ip_source, &conf, &opts).await?;