1use rand::seq::SliceRandom;
4use std::time::Duration;
5
6pub fn get_public_ip_addr() -> Option<String> {
7 let sources = vec![
8 ("https://icanhazip.com/", false), ("https://api.ip.sb/ip", false), ("https://api.ipsimple.org/ipv4?format=json", true), ("https://api.ipify.org/?format=json", true), ];
13
14 let client = reqwest::blocking::Client::builder()
15 .timeout(Duration::from_secs(3))
16 .build()
17 .unwrap();
18
19 let mut rng = rand::thread_rng();
20 let mut shuffled = sources.clone();
21 shuffled.shuffle(&mut rng);
22
23 for (url, is_json) in shuffled {
24 if let Ok(resp) = client.get(url).send() {
25 if is_json {
26 if let Ok(json) = resp.json::<serde_json::Value>() {
27 if let Some(ip) = json.get("ip").and_then(|v| v.as_str()) {
28 return Some(ip.to_string());
29 }
30 }
31 } else if let Ok(text) = resp.text() {
32 let ip = text.trim().to_string();
33 if !ip.is_empty() {
34 return Some(ip);
35 }
36 }
37 }
38 }
39
40 None
41}