Compare commits
No commits in common. "0eaddf064ebd84ca837b1593795a20781ebc9827" and "09afecf396fe8ddc898349979da84b64e8c40e93" have entirely different histories.
0eaddf064e
...
09afecf396
@ -8,8 +8,6 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::get_current_public_ipv4;
|
|
||||||
|
|
||||||
pub struct CloudflareClient {
|
pub struct CloudflareClient {
|
||||||
client: Client,
|
client: Client,
|
||||||
domains: Vec<Arc<str>>,
|
domains: Vec<Arc<str>>,
|
||||||
@ -17,6 +15,21 @@ pub struct CloudflareClient {
|
|||||||
api_key: Box<str>,
|
api_key: Box<str>,
|
||||||
zone_id: Box<str>,
|
zone_id: Box<str>,
|
||||||
}
|
}
|
||||||
|
// Some external site to check this
|
||||||
|
async fn get_current_public_ipv4(client: &Client) -> Result<Ipv4Addr> {
|
||||||
|
let response = client
|
||||||
|
.get("https://api.ipify.org?format=json")
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?
|
||||||
|
.json::<HashMap<String, String>>()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(response
|
||||||
|
.get("ip")
|
||||||
|
.context("Field 'ip' wasn't found")?
|
||||||
|
.parse()?)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
struct DnsRecord {
|
struct DnsRecord {
|
||||||
@ -32,7 +45,7 @@ struct DnsRecord {
|
|||||||
zone_name: Box<str>,
|
zone_name: Box<str>,
|
||||||
modified_on: Box<str>,
|
modified_on: Box<str>,
|
||||||
created_on: Box<str>,
|
created_on: Box<str>,
|
||||||
meta: HashMap<Box<str>, serde_json::Value>,
|
meta: HashMap<String, serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CloudflareClient {
|
impl CloudflareClient {
|
||||||
@ -58,13 +71,13 @@ impl CloudflareClient {
|
|||||||
if new_ip == self.current_ip {
|
if new_ip == self.current_ip {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.update_dns_records(new_ip).await?;
|
self.update_dns_records(new_ip).await;
|
||||||
self.current_ip = new_ip;
|
self.current_ip = new_ip;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_dns_records(&self, new_ip: Ipv4Addr) -> Result<()> {
|
async fn update_dns_records(&self, new_ip: Ipv4Addr) {
|
||||||
for domain in &self.domains {
|
for domain in &self.domains {
|
||||||
let records = match self.get_dns_records(domain).await {
|
let records = match self.get_dns_records(domain).await {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
@ -91,12 +104,9 @@ impl CloudflareClient {
|
|||||||
"On {}, failed to update {}: '{}' -> '{}': {:?}",
|
"On {}, failed to update {}: '{}' -> '{}': {:?}",
|
||||||
&domain, record.name, record.content, &new_ip_s, &e
|
&domain, record.name, record.content, &new_ip_s, &e
|
||||||
);
|
);
|
||||||
return Err(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_dns_records(&self, domain: &str) -> Result<Vec<DnsRecord>> {
|
async fn get_dns_records(&self, domain: &str) -> Result<Vec<DnsRecord>> {
|
||||||
|
@ -9,52 +9,38 @@ use crate::PROGRAM_NAME;
|
|||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub zone_id: Box<str>,
|
pub cloudflare_zone_id: Box<str>,
|
||||||
pub api_key: Box<str>,
|
pub cloudflare_api_key: Box<str>,
|
||||||
pub domains: Vec<Box<str>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_config_path() -> Result<PathBuf, Vec<PathBuf>> {
|
pub async fn get_config_path() -> Option<PathBuf> {
|
||||||
let mut tried_paths = Vec::with_capacity(2);
|
|
||||||
|
|
||||||
match env::current_dir() {
|
match env::current_dir() {
|
||||||
Ok(current_dir) => {
|
Ok(current_dir) => {
|
||||||
let cwd_config = current_dir.join(format!("{}.toml", PROGRAM_NAME));
|
let cwd_config = current_dir.join(format!("{}.toml", PROGRAM_NAME));
|
||||||
|
if let Ok(meta) = fs::metadata(&cwd_config).await {
|
||||||
let is_valid_path = fs::metadata(&cwd_config)
|
if meta.is_file() {
|
||||||
.await
|
return Some(cwd_config);
|
||||||
.map_or_else(|_| false, |meta| meta.is_file());
|
}
|
||||||
|
|
||||||
if is_valid_path {
|
|
||||||
return Ok(cwd_config);
|
|
||||||
} else {
|
|
||||||
tried_paths.push(cwd_config);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Failed to get current working directory: {:?}", e);
|
warn!("Failed to get current directory {:?}", &e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match dirs::config_dir() {
|
match dirs::config_dir() {
|
||||||
Some(config_dir) => {
|
Some(config_dir) => {
|
||||||
let config_file = config_dir.join(PROGRAM_NAME).join("config.toml");
|
let config_file = config_dir.join(PROGRAM_NAME).join("config.toml");
|
||||||
|
if let Ok(meta) = fs::metadata(&config_file).await {
|
||||||
let is_valid_path = fs::metadata(&config_file)
|
if meta.is_file() {
|
||||||
.await
|
return Some(config_file);
|
||||||
.map_or_else(|_| false, |meta| meta.is_file());
|
|
||||||
if is_valid_path {
|
|
||||||
return Ok(config_file);
|
|
||||||
} else {
|
|
||||||
tried_paths.push(config_file);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
warn!("No configuration directory found.");
|
|
||||||
}
|
}
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(tried_paths)
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read_config(path: &PathBuf) -> anyhow::Result<Config> {
|
pub async fn read_config(path: &PathBuf) -> anyhow::Result<Config> {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
mod cloudflare;
|
mod cloudflare;
|
||||||
mod config;
|
mod config;
|
||||||
mod public_ip;
|
pub use config::{Config, get_config_path, read_config};
|
||||||
pub use config::{get_config_path, read_config, Config};
|
|
||||||
pub use public_ip::get_current_public_ipv4;
|
|
||||||
|
|
||||||
pub const PROGRAM_NAME: &'static str = "dynip-cloudflare";
|
pub const PROGRAM_NAME: &'static str = "dynip-cloudflare";
|
||||||
|
16
src/main.rs
16
src/main.rs
@ -26,19 +26,9 @@ const fn nl_mgrp(group: u32) -> u32 {
|
|||||||
async fn main() {
|
async fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let config_path = match get_config_path().await {
|
let config_path = match get_config_path().await {
|
||||||
Ok(cp) => cp,
|
Some(cp) => cp,
|
||||||
Err(tried_paths) => {
|
None => {
|
||||||
let extra: String = if !tried_paths.is_empty() {
|
error!("Failed to find any config file");
|
||||||
let joined = tried_paths
|
|
||||||
.iter()
|
|
||||||
.filter_map(|path| path.to_str())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ");
|
|
||||||
format!(", tried the paths: '{}'", &joined)
|
|
||||||
} else {
|
|
||||||
String::with_capacity(0)
|
|
||||||
};
|
|
||||||
error!("Failed to find any config file{}", &extra);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
use anyhow::{anyhow, Context, Result};
|
|
||||||
use log::error;
|
|
||||||
use reqwest::Client;
|
|
||||||
use std::{collections::HashMap, net::Ipv4Addr};
|
|
||||||
|
|
||||||
async fn ipify_org(client: &Client) -> Result<Ipv4Addr> {
|
|
||||||
let response = client
|
|
||||||
.get("https://api.ipify.org?format=json")
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.error_for_status()?
|
|
||||||
.json::<HashMap<String, String>>()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(response
|
|
||||||
.get("ip")
|
|
||||||
.context("Field 'ip' wasn't found")?
|
|
||||||
.parse()?)
|
|
||||||
}
|
|
||||||
async fn ifconfig_me(client: &Client) -> Result<Ipv4Addr> {
|
|
||||||
Ok(client
|
|
||||||
.get("https://ifconfig.me")
|
|
||||||
.header("user-agent", "curl/8.8.0")
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.error_for_status()?
|
|
||||||
.text()
|
|
||||||
.await?
|
|
||||||
.parse()?)
|
|
||||||
}
|
|
||||||
pub async fn get_current_public_ipv4(client: &Client) -> Result<Ipv4Addr> {
|
|
||||||
let e_ipify = match ipify_org(client).await {
|
|
||||||
Ok(ipv4) => return Ok(ipv4),
|
|
||||||
Err(e) => {
|
|
||||||
error!("Failed to get ip from ipify.org: {:?}", &e);
|
|
||||||
e
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ifconfig_me(client).await.map_err(|e_ifconfig| {
|
|
||||||
error!("Failed to get ip from ifconfig.me: {:?}", &e_ifconfig);
|
|
||||||
anyhow!("Failed to get ip from ipify.org with error '{:?}', and ifconfig.me with error {:?}", &e_ipify, &e_ifconfig)
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user