Compare commits

...

4 commits

10 changed files with 70 additions and 10 deletions

2
Cargo.lock generated
View file

@ -652,7 +652,7 @@ dependencies = [
[[package]] [[package]]
name = "gandi-live-dns" name = "gandi-live-dns"
version = "1.6.0" version = "1.7.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View file

@ -1,11 +1,11 @@
[package] [package]
name = "gandi-live-dns" name = "gandi-live-dns"
description = "Automatically updates your IP address in Gandi's Live DNS. Makes it possible to use Gandi as a dynamic DNS system." description = "Automatically updates your IP address in Gandi's Live DNS. Makes it possible to use Gandi as a dynamic DNS system."
version = "1.6.0" version = "1.7.0"
edition = "2021" edition = "2021"
authors = ["Kaan Barmore-Genç <kaan@bgenc.net>"] authors = ["Kaan Barmore-Genç <kaan@bgenc.net>"]
license = "MIT" license = "MIT"
readme = "Readme.md" readme = "README.md"
repository = "https://github.com/SeriousBug/gandi-live-dns-rust" repository = "https://github.com/SeriousBug/gandi-live-dns-rust"
[profile.release] [profile.release]

View file

@ -161,7 +161,8 @@ Docker with `docker login`. Then follow these steps:
- Create a release on Github - Create a release on Github
- Make sure to create a tag for the release version on `master` - Make sure to create a tag for the release version on `master`
- Upload the binary archives to the Github release - Upload the binary archives to the Github release
- Update the AUR version manually - Update the AUR version
- Run `cargo publish` to update the crates.io version
## Alternatives ## Alternatives

View file

@ -19,8 +19,9 @@ ttl = 300
# Ipify is used by default. If you want to change it, uncomment the one you want # Ipify is used by default. If you want to change it, uncomment the one you want
# to use. # to use.
# #
# ip_source = "Ipify" #ip_source = "Ipify" # An open source and public service. https://github.com/rdegges/ipify-api
# ip_source = "Icanhazip" #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. # For every domain or subdomain you want to update, create an entry below.

View file

@ -3,9 +3,7 @@
# Make sure `cross` is installed. # Make sure `cross` is installed.
# You'll also need `sed`, a relatively recent version of `tar`, and `7z`. # You'll also need `sed`, a relatively recent version of `tar`, and `7z`.
# #
# This script runs does `sudo docker` to build and push the release to docker. DOCKER="docker"
# If you have rootless docker set up, remove sudo from this variable.
DOCKER="sudo docker"
# #
shopt -s extglob shopt -s extglob
# Trap errors and interrupts # Trap errors and interrupts
@ -49,6 +47,9 @@ VERSION=$(sed -nr 's/^version *= *"([0-9.]+)"/\1/p' Cargo.toml | head --lines=1)
# Make the builds # Make the builds
for target in "${!TARGETS[@]}"; do for target in "${!TARGETS[@]}"; do
echo Building "${target}" echo Building "${target}"
# Keeping the cached builds seem to be breaking things when going between targets
# This wouldn't be a problem if these were running in a matrix on the CI...
rm -rf target/release/
cross build -j $(($(nproc) / 2)) --release --target "${target}" cross build -j $(($(nproc) / 2)) --release --target "${target}"
if [[ "${target}" =~ .*"windows".* ]]; then if [[ "${target}" =~ .*"windows".* ]]; then
zip -j "gandi-live-dns.${VERSION}.${TARGETS[${target}]}.zip" target/"${target}"/release/gandi-live-dns.exe 1>/dev/null zip -j "gandi-live-dns.${VERSION}.${TARGETS[${target}]}.zip" target/"${target}"/release/gandi-live-dns.exe 1>/dev/null

View file

@ -25,6 +25,7 @@ fn default_ttl() -> u32 {
pub enum IPSourceName { pub enum IPSourceName {
Ipify, Ipify,
Icanhazip, Icanhazip,
SeeIP,
} }
impl Default for IPSourceName { impl Default for IPSourceName {

View file

@ -2,5 +2,5 @@ The IP sources. These are APIs that we can query to get the IP address of the
current service. current service.
The tests under this directory are all marked to be skipped, the tests hit the 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. have to modify the code.

View file

@ -1,3 +1,4 @@
pub(crate) mod icanhazip; pub(crate) mod icanhazip;
pub(crate) mod ip_source; pub(crate) mod ip_source;
pub(crate) mod ipify; pub(crate) mod ipify;
pub(crate) mod seeip;

53
src/ip_source/seeip.rs Normal file
View file

@ -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<String> {
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<String> {
get_ip("https://ip4.seeip.org").await
}
async fn get_ipv6(&self) -> anyhow::Result<String> {
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()))
}
}

View file

@ -4,6 +4,7 @@ use crate::ip_source::{ip_source::IPSource, ipify::IPSourceIpify};
use clap::Parser; use clap::Parser;
use config::IPSourceName; use config::IPSourceName;
use ip_source::icanhazip::IPSourceIcanhazip; use ip_source::icanhazip::IPSourceIcanhazip;
use ip_source::seeip::IPSourceSeeIP;
use opts::Opts; use opts::Opts;
use reqwest::{header, Client, ClientBuilder, StatusCode}; use reqwest::{header, Client, ClientBuilder, StatusCode};
use serde::Serialize; use serde::Serialize;
@ -158,6 +159,7 @@ async fn main() -> anyhow::Result<()> {
let ip_source: Box<dyn IPSource> = match conf.ip_source { let ip_source: Box<dyn IPSource> = match conf.ip_source {
IPSourceName::Ipify => Box::new(IPSourceIpify), IPSourceName::Ipify => Box::new(IPSourceIpify),
IPSourceName::Icanhazip => Box::new(IPSourceIcanhazip), IPSourceName::Icanhazip => Box::new(IPSourceIcanhazip),
IPSourceName::SeeIP => Box::new(IPSourceSeeIP),
}; };
config::validate_config(&conf).die_with(|error| format!("Invalid config: {}", error)); config::validate_config(&conf).die_with(|error| format!("Invalid config: {}", error));
run("https://api.gandi.net", &ip_source, &conf, &opts).await?; run("https://api.gandi.net", &ip_source, &conf, &opts).await?;