fetch_ccip/
output.rs

1use chrono::{Datelike, Local, Timelike};
2use ipnet::IpNet;
3use std::collections::BTreeSet;
4use std::fs;
5use std::fs::OpenOptions;
6use std::io::Write;
7use std::path::Path;
8
9/// ソート済みのIPv4/IPv6リストをファイルに書き出すモジュール。
10/// すべてファイル出力で完結している。
11pub fn write_ip_lists_to_files(
12    country_code: &str,
13    ipv4_list: &BTreeSet<IpNet>,
14    ipv6_list: &BTreeSet<IpNet>,
15    // 追記・上書きモードを引数で受け取る
16    mode: &str,
17) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
18    let ipv4_file = format!("IPv4_{}.txt", country_code);
19    let ipv6_file = format!("IPv6_{}.txt", country_code);
20
21    // それぞれ書き込み処理を実行
22    write_single_ip_list(&ipv4_file, ipv4_list, mode)?;
23    write_single_ip_list(&ipv6_file, ipv6_list, mode)?;
24
25    Ok(())
26}
27
28/// 1つのファイルに書き込むヘルパー関数
29/// 書き込み先を変更したい場合は、この関数を差し替えるだけにする設計が可能。
30fn write_single_ip_list<P: AsRef<Path>>(
31    path: P,
32    nets: &BTreeSet<IpNet>,
33    mode: &str,
34) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
35    let now = Local::now();
36    let formatted_header = format!(
37        "# {}年{}月{}日 {}時{}分\n",
38        now.year(),
39        now.month(),
40        now.day(),
41        now.hour(),
42        now.minute()
43    );
44
45    let lines: Vec<String> = nets.iter().map(|net| net.to_string()).collect();
46    let content = format!("{}{}", formatted_header, lines.join("\n"));
47
48    match mode {
49        "append" => {
50            // 追記モードでファイルを開く
51            // 無ければ新規作成
52            let mut file = OpenOptions::new().create(true).append(true).open(&path)?;
53            file.write_all(content.as_bytes())?;
54            println!("[output] Appended IP list to: {}", path.as_ref().display());
55        }
56        _ => {
57            // デフォルトは上書き
58            fs::write(&path, &content)?;
59            println!(
60                "[output] Wrote (overwrite) IP list to: {}",
61                path.as_ref().display()
62            );
63        }
64    }
65
66    Ok(())
67}