From 42dbe1e6c536ec553d80d6227d0d27e368e5cd60 Mon Sep 17 00:00:00 2001 From: Asthowen Date: Thu, 28 Aug 2025 15:43:50 +0200 Subject: [PATCH] feat: add public-ip support --- Cargo.lock | 82 +++++++++++++++++---------------- Cargo.toml | 6 +-- src/config/deserialize.rs | 33 ++++++++++++++ src/config/mod.rs | 30 ++++++++++++ src/main.rs | 2 + src/system/battery.rs | 3 +- src/system/disk.rs | 3 +- src/system/disks.rs | 3 +- src/system/host.rs | 5 +- src/system/memory.rs | 3 +- src/system/mod.rs | 15 ++++++ src/system/networks.rs | 3 +- src/system/product.rs | 3 +- src/system/public_ip.rs | 96 +++++++++++++++++++++++++++++++++++++++ src/system/uptime.rs | 3 +- src/util/mod.rs | 2 + 16 files changed, 232 insertions(+), 60 deletions(-) create mode 100644 src/system/public_ip.rs diff --git a/Cargo.lock b/Cargo.lock index a844a15..19dd68d 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,10 +17,10 @@ dependencies = [ "csscolorparser", "dirs", "image", - "minreq", "rayon", "serde", "serde_json", + "socket2", "starship-battery", "strip-ansi-escapes", "supports-unicode", @@ -188,9 +188,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cc" -version = "1.2.29" +version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ "jobserver", "libc", @@ -263,9 +263,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -491,9 +491,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.4" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" +checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85" [[package]] name = "half" @@ -644,9 +644,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.4" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ "bitflags 2.9.1", "libc", @@ -730,15 +730,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "minreq" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84885312a86831bff4a3cb04a1e54a3f698407e3274c83249313f194d3e0b678" -dependencies = [ - "log", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1156,18 +1147,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags 2.9.1", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", @@ -1176,9 +1167,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.51" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a457e416a0f90d246a4c3288bd7a25b2304ca727f253f95be383dd17af56be8f" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" dependencies = [ "bytemuck", ] @@ -1198,15 +1189,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1249,9 +1240,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ "itoa", "memchr", @@ -1301,6 +1292,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "starship-battery" version = "0.10.2" @@ -1356,9 +1357,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.36.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aab138f5c1bb35231de19049060a87977ad23e04f2303e953bc5c2947ac7dec4" +checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d" dependencies = [ "libc", "memchr", @@ -1396,7 +1397,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.7", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -1687,7 +1688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ "env_home", - "rustix 1.0.7", + "rustix 1.0.8", "winsafe", ] @@ -1849,7 +1850,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.3", ] [[package]] @@ -1870,10 +1871,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -1991,9 +1993,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -2050,9 +2052,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" +checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 9fd0439..818d48b 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,11 +33,11 @@ strip-ansi-escapes = "0.2.1" starship-battery = "0.10.2" supports-unicode = "3.0.0" csscolorparser = "0.7.2" -serde_json = "1.0.140" +serde_json = "1.0.142" sys-locale = "0.3.2" -sysinfo = "0.36.0" +sysinfo = "0.36.1" bitcode = "0.6.6" -minreq = "2.14.0" +socket2 = "0.6.0" rayon = "1.10.0" which = "8.0.0" dirs = "6.0.0" diff --git a/src/config/deserialize.rs b/src/config/deserialize.rs index aaf4396..e875565 100644 --- a/src/config/deserialize.rs +++ b/src/config/deserialize.rs @@ -23,6 +23,8 @@ struct InfoConfig<'a> { disks: Option>, #[serde(default, borrow)] networks: Option>, + #[serde(default, borrow)] + public_ip: Option>, } #[derive(Debug, Deserialize)] @@ -47,6 +49,22 @@ struct NetworksInfoConfig<'a> { ignore_loopback: Option, } +#[derive(Debug, Deserialize)] +struct PublicIpInfoConfig<'a> { + #[serde(default, borrow)] + ipv4_domain: Option<&'a str>, + #[serde(default)] + ipv4_port: Option, + #[serde(default, borrow)] + ipv4_path: Option<&'a str>, + #[serde(default, borrow)] + ipv6_domain: Option<&'a str>, + #[serde(default)] + ipv6_port: Option, + #[serde(default, borrow)] + ipv6_path: Option<&'a str>, +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "snake_case")] enum ColorBlockStyle<'a> { @@ -243,6 +261,21 @@ impl<'de: 'static> serde::Deserialize<'de> for super::Config { ignore_loopback: networks.ignore_loopback.unwrap_or(true), }) .unwrap_or_default(), + public_ip: info + .public_ip + .map(|public_ip| super::PublicIpInfoConfig { + ipv4_domain: public_ip + .ipv4_domain + .unwrap_or(super::DEFAULT_IPV4_DOMAIN), + ipv4_port: public_ip.ipv4_port.unwrap_or(super::DEFAULT_IPV4_PORT), + ipv4_path: public_ip.ipv4_path.unwrap_or(super::DEFAULT_IPV4_PATH), + ipv6_domain: public_ip + .ipv6_domain + .unwrap_or(super::DEFAULT_IPV6_DOMAIN), + ipv6_port: public_ip.ipv6_port.unwrap_or(super::DEFAULT_IPV6_PORT), + ipv6_path: public_ip.ipv6_path.unwrap_or(super::DEFAULT_IPV6_PATH), + }) + .unwrap_or_default(), }) .unwrap_or_default(), }) diff --git a/src/config/mod.rs b/src/config/mod.rs index 3662fca..043df60 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -17,6 +17,12 @@ const FALLBACK_COLOR: Option = Some(ColorWrapper::Rgb { g: 255, b: 255, }); +const DEFAULT_IPV4_DOMAIN: &str = "ipinfo.io"; +const DEFAULT_IPV4_PORT: u16 = 80; +const DEFAULT_IPV4_PATH: &str = "/ip"; +const DEFAULT_IPV6_DOMAIN: &str = "v6.ipinfo.io"; +const DEFAULT_IPV6_PORT: u16 = 80; +const DEFAULT_IPV6_PATH: &str = "/ip"; #[derive(Debug, Decode, Encode)] pub struct Config { @@ -32,6 +38,7 @@ pub struct Config { pub struct InfoConfig<'a> { pub disks: DisksInfoConfig<'a>, pub networks: NetworksInfoConfig<'a>, + pub public_ip: PublicIpInfoConfig<'a>, } #[derive(Debug, Decode, Encode)] @@ -49,6 +56,16 @@ pub struct NetworksInfoConfig<'a> { pub ignore_loopback: bool, } +#[derive(Debug, Decode, Encode)] +pub struct PublicIpInfoConfig<'a> { + pub ipv4_domain: &'a str, + pub ipv4_port: u16, + pub ipv4_path: &'a str, + pub ipv6_domain: &'a str, + pub ipv6_port: u16, + pub ipv6_path: &'a str, +} + impl<'a> Default for DisksInfoConfig<'a> { fn default() -> Self { Self { @@ -72,6 +89,19 @@ impl<'a> Default for NetworksInfoConfig<'a> { } } +impl<'a> Default for PublicIpInfoConfig<'a> { + fn default() -> Self { + Self { + ipv4_domain: DEFAULT_IPV4_DOMAIN, + ipv4_port: DEFAULT_IPV4_PORT, + ipv4_path: DEFAULT_IPV4_PATH, + ipv6_domain: DEFAULT_IPV6_DOMAIN, + ipv6_port: DEFAULT_IPV6_PORT, + ipv6_path: DEFAULT_IPV6_PATH, + } + } +} + #[derive(Debug, Decode, Encode)] pub struct ColorOption { pub header: Option, diff --git a/src/main.rs b/src/main.rs index dbe47c5..cdbd8bd 100755 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ use afetch::system::memory::get_memory; use afetch::system::motherboard::get_motherboard; use afetch::system::networks::get_networks; use afetch::system::product::get_product; +use afetch::system::public_ip::get_public_ip; use afetch::system::uptime::get_uptime; use afetch::system::{InfoGroup, InfoKind, InfoResult}; use afetch::translations::get_language; @@ -47,6 +48,7 @@ fn main() -> Result<(), FetchInfoError> { InfoKind::Motherboard => get_motherboard(language_func, fields, &config), InfoKind::Networks => get_networks(language_func, fields, &config), InfoKind::Product => get_product(language_func, fields, &config), + InfoKind::PublicIp => get_public_ip(language_func, fields, &config), InfoKind::Uptime => get_uptime(language_func, fields, &config), }, ) diff --git a/src/system/battery.rs b/src/system/battery.rs index ed7c58c..feba234 100644 --- a/src/system/battery.rs +++ b/src/system/battery.rs @@ -2,8 +2,7 @@ use crate::config::Config; use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; -use crate::util::ToOptionString; -use crate::util::format_time; +use crate::util::{ToOptionString, format_time}; use starship_battery::units::time::second; pub fn get_battery( diff --git a/src/system/disk.rs b/src/system/disk.rs index 8f9f242..429934a 100644 --- a/src/system/disk.rs +++ b/src/system/disk.rs @@ -3,8 +3,7 @@ use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::disks::ignore_disk; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; -use crate::util::ToOptionString; -use crate::util::convert_to_readable_unity; +use crate::util::{ToOptionString, convert_to_readable_unity}; use sysinfo::Disks; pub fn get_disk( diff --git a/src/system/disks.rs b/src/system/disks.rs index 6d02ace..a4b9193 100644 --- a/src/system/disks.rs +++ b/src/system/disks.rs @@ -2,8 +2,7 @@ use crate::config::Config; use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; -use crate::util::ToOptionString; -use crate::util::convert_to_readable_unity; +use crate::util::{ToOptionString, convert_to_readable_unity}; use sysinfo::{DiskRefreshKind, Disks}; pub fn get_disks( diff --git a/src/system/host.rs b/src/system/host.rs index 5f5d58e..eb5b912 100644 --- a/src/system/host.rs +++ b/src/system/host.rs @@ -3,8 +3,7 @@ use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; use crate::util::ToOptionString; -use whoami::fallible::hostname; -use whoami::username; +use whoami::fallible::{hostname, username}; pub fn get_hostname( _languages_func: fn(&str) -> &str, @@ -15,7 +14,7 @@ pub fn get_hostname( values: filtered_values!( fields, [ - (InfoField::Username, username()), + (InfoField::Username, username().ok()), (InfoField::Hostname, hostname().ok()), ] ), diff --git a/src/system/memory.rs b/src/system/memory.rs index 1137deb..22c1b36 100644 --- a/src/system/memory.rs +++ b/src/system/memory.rs @@ -2,8 +2,7 @@ use crate::config::Config; use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; -use crate::util::ToOptionString; -use crate::util::convert_to_readable_unity; +use crate::util::{ToOptionString, convert_to_readable_unity}; use sysinfo::{MemoryRefreshKind, RefreshKind, System}; pub fn get_memory( diff --git a/src/system/mod.rs b/src/system/mod.rs index 09ae1f1..36dc3bb 100755 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -14,6 +14,7 @@ pub mod memory; pub mod motherboard; pub mod networks; pub mod product; +pub mod public_ip; pub mod uptime; pub type InfoFunction = @@ -33,6 +34,7 @@ pub enum InfoKind { Motherboard, Networks, Product, + PublicIp, Uptime, } @@ -131,6 +133,11 @@ impl InfoKind { InfoField::ProductVendorName, InfoField::ProductVersion, ], + Self::PublicIp => &[ + InfoField::PublicIpAny, + InfoField::PublicIpv4, + InfoField::PublicIpv6, + ], Self::Uptime => &[InfoField::Uptime], } } @@ -148,6 +155,7 @@ impl InfoKind { Self::Motherboard => "{motherboard_name} {motherboard_version}", Self::Networks => "{network_prefer_first_ipv4}", Self::Product => "{product_name} {product_version}", + Self::PublicIp => "{public_ip_any}", Self::Uptime => "{uptime}", } } @@ -165,6 +173,7 @@ impl InfoKind { Self::Motherboard => "motherboard", Self::Networks => "networks", Self::Product => "host", + Self::PublicIp => "public-ip", Self::Uptime => "uptime", } } @@ -247,6 +256,9 @@ pub enum InfoField { ProductUuid, ProductVendorName, ProductVersion, + PublicIpAny, + PublicIpv4, + PublicIpv6, Uptime, Username, } @@ -329,6 +341,9 @@ impl InfoField { Self::ProductUuid => "product_uuid", Self::ProductVendorName => "product_vendor_name", Self::ProductVersion => "product_version", + Self::PublicIpAny => "public_ip_any", + Self::PublicIpv4 => "public_ipv4", + Self::PublicIpv6 => "public_ipv6", Self::Uptime => "uptime", Self::Username => "username", } diff --git a/src/system/networks.rs b/src/system/networks.rs index f10894c..811aa37 100644 --- a/src/system/networks.rs +++ b/src/system/networks.rs @@ -2,8 +2,7 @@ use crate::config::Config; use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; -use crate::util::ToOptionString; -use crate::util::convert_to_readable_unity; +use crate::util::{ToOptionString, convert_to_readable_unity}; use std::net::IpAddr; use sysinfo::Networks; diff --git a/src/system/product.rs b/src/system/product.rs index 1b4d7eb..77b549f 100644 --- a/src/system/product.rs +++ b/src/system/product.rs @@ -1,8 +1,7 @@ use crate::config::Config; use crate::error::FetchInfoError; use crate::filtered_values; -use crate::system::InfoValue; -use crate::system::{InfoField, InfoGroup, InfoResult}; +use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; use crate::util::ToOptionString; use sysinfo::Product; diff --git a/src/system/public_ip.rs b/src/system/public_ip.rs new file mode 100644 index 0000000..23aa5c6 --- /dev/null +++ b/src/system/public_ip.rs @@ -0,0 +1,96 @@ +use crate::config::Config; +use crate::error::FetchInfoError; +use crate::filtered_values; +use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; +use crate::util::{PROJECT_VERSION, ToOptionString}; +use socket2::{Domain, Protocol, Socket, Type}; +use std::io::{Read, Write}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; +use std::time::Duration; + +const IPV4: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)); +const IPV6: IpAddr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); +const TIMEOUT: Duration = Duration::from_secs(5); + +pub fn get_public_ip( + _languages_func: fn(&str) -> &str, + fields: &[InfoField], + config: &Config, +) -> Result { + let ipv4 = + if fields.contains(&InfoField::PublicIpv4) || fields.contains(&InfoField::PublicIpAny) { + http_get_request( + config.parameters.public_ip.ipv4_domain, + config.parameters.public_ip.ipv4_port, + config.parameters.public_ip.ipv4_path, + IPV4, + ) + } else { + None + }; + let ipv6 = if fields.contains(&InfoField::PublicIpv6) + || (fields.contains(&InfoField::PublicIpAny) && ipv4.is_none()) + { + http_get_request( + config.parameters.public_ip.ipv6_domain, + config.parameters.public_ip.ipv6_port, + config.parameters.public_ip.ipv6_path, + IPV6, + ) + } else { + None + }; + + Ok(InfoResult::Single(InfoGroup { + values: filtered_values!( + fields, + [ + (InfoField::PublicIpAny, ipv4.as_deref().or(ipv6.as_deref())), + (InfoField::PublicIpv4, ipv4), + (InfoField::PublicIpv6, ipv6), + ] + ), + })) +} + +fn http_get_request(domain: &str, port: u16, path: &str, ip: IpAddr) -> Option { + let local_addr = SocketAddr::new(ip, 0); + let addresses = (domain, port).to_socket_addrs().ok()?; + for address in addresses { + let socket = match Socket::new( + if address.is_ipv4() { + Domain::IPV4 + } else { + Domain::IPV6 + }, + Type::STREAM, + Some(Protocol::TCP), + ) { + Ok(socket) => socket, + Err(_) => continue, + }; + + if socket.bind(&local_addr.into()).is_err() || socket.connect(&address.into()).is_err() { + continue; + } + + let mut stream: std::net::TcpStream = socket.into(); + stream.set_read_timeout(Some(TIMEOUT)).ok(); + stream.set_write_timeout(Some(TIMEOUT)).ok(); + + let request = format!( + "GET {path} HTTP/1.1\r\nHost: {domain}\r\nUser-Agent: AFetch/{PROJECT_VERSION}\r\nAccept: */*\r\nConnection: close\r\n\r\n" + ); + stream.write_all(request.as_bytes()).ok()?; + + let mut buffer = Vec::new(); + stream.read_to_end(&mut buffer).ok()?; + + let response = String::from_utf8_lossy(&buffer); + if let Some(body_start) = response.find("\r\n\r\n") { + return Some(response[(body_start + 4)..].trim().to_owned()); + } + } + + None +} diff --git a/src/system/uptime.rs b/src/system/uptime.rs index 58bb850..063c36e 100644 --- a/src/system/uptime.rs +++ b/src/system/uptime.rs @@ -2,8 +2,7 @@ use crate::config::Config; use crate::error::FetchInfoError; use crate::filtered_values; use crate::system::{InfoField, InfoGroup, InfoResult, InfoValue}; -use crate::util::ToOptionString; -use crate::util::format_time; +use crate::util::{ToOptionString, format_time}; use sysinfo::System; pub fn get_uptime( diff --git a/src/util/mod.rs b/src/util/mod.rs index e6acc90..dfbac39 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -14,6 +14,8 @@ use unicode_segmentation::UnicodeSegmentation; #[cfg(feature = "image")] use viuer::Config as ViuerConfig; +pub const PROJECT_VERSION: &str = env!("CARGO_PKG_VERSION"); + const fn div_mod(dividend: u64, divisor: u64) -> (u64, u64) { (dividend / divisor, dividend % divisor) }