File size: 2,627 Bytes
1295969
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Mirror uploads: Internet Archive + BBS (both non-blocking).
use shared::master_pattern::RarityTier;
use tracing::{info, instrument, warn};

#[instrument]
pub async fn push_all(
    cid: &shared::types::BtfsCid,
    isrc: &str,
    title: &str,
    band: u8,
) -> anyhow::Result<()> {
    let (ia, bbs) = tokio::join!(
        push_internet_archive(cid, isrc, title, band),
        push_bbs(cid, isrc, title, band),
    );
    if let Err(e) = ia {
        warn!(err=%e, "IA mirror failed");
    }
    if let Err(e) = bbs {
        warn!(err=%e, "BBS mirror failed");
    }
    Ok(())
}

async fn push_internet_archive(
    cid: &shared::types::BtfsCid,
    isrc: &str,
    title: &str,
    band: u8,
) -> anyhow::Result<()> {
    let access = std::env::var("ARCHIVE_ACCESS_KEY").unwrap_or_default();
    if access.is_empty() {
        warn!("ARCHIVE_ACCESS_KEY not set — skipping IA");
        return Ok(());
    }
    let tier = RarityTier::from_band(band);
    let identifier = format!("retrosync-{}", isrc.replace('/', "-").to_lowercase());
    let url = format!("https://s3.us.archive.org/{identifier}/{identifier}.meta.json");
    let meta = serde_json::json!({ "title": title, "isrc": isrc, "btfs_cid": cid.0,
                                          "band": band, "rarity": tier.as_str() });
    let secret = std::env::var("ARCHIVE_SECRET_KEY").unwrap_or_default();
    let resp = reqwest::Client::new()
        .put(&url)
        .header("Authorization", format!("LOW {access}:{secret}"))
        .header("x-archive-auto-make-bucket", "1")
        .header("x-archive-meta-title", title)
        .header("x-archive-meta-mediatype", "audio")
        .header("Content-Type", "application/json")
        .body(meta.to_string())
        .send()
        .await?;
    if resp.status().is_success() {
        info!(isrc=%isrc, "Mirrored to IA");
    }
    Ok(())
}

async fn push_bbs(
    cid: &shared::types::BtfsCid,
    isrc: &str,
    title: &str,
    band: u8,
) -> anyhow::Result<()> {
    let url = std::env::var("MIRROR_BBS_URL").unwrap_or_default();
    if url.is_empty() {
        return Ok(());
    }
    let tier = RarityTier::from_band(band);
    let payload = serde_json::json!({
        "type": "track_announce", "isrc": isrc, "title": title,
        "btfs_cid": cid.0, "band": band, "rarity": tier.as_str(),
        "timestamp": chrono::Utc::now().to_rfc3339(),
    });
    reqwest::Client::builder()
        .timeout(std::time::Duration::from_secs(15))
        .build()?
        .post(&url)
        .json(&payload)
        .send()
        .await?;
    info!(isrc=%isrc, "Announced to BBS");
    Ok(())
}