aboutsummaryrefslogtreecommitdiff
path: root/src/bots/fdroid/index.rs
blob: 61cc44d65093e0811c4437a83ffcb7fc36bc5e88 (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Types for the F-Droid repository index.

use std::collections::HashMap;

use serde::{Deserialize, Deserializer};

pub(super) const PHONE_DEVICE_TYPE: &str = "phone";
pub(super) const EN_LOCALE: &str = "en-US";

#[derive(Debug, Deserialize)]
pub(super) struct Index {
    pub(super) repo: Repo,
    pub(super) packages: HashMap<String, Package>,
}

#[derive(Debug, Deserialize)]
pub(super) struct Repo {
    pub(super) timestamp: u64,
}

#[derive(Debug, Deserialize)]
pub(super) struct Package {
    pub(super) metadata: Metadata,
    /// Releases keyed by the APK's SHA-256 digest.
    pub(super) versions: HashMap<String, Version>,
}

#[derive(Debug, Deserialize)]
pub(super) struct Version {
    /// Anti-feature explanations keyed first by anti-feature name and then by locale.
    #[serde(default, rename = "antiFeatures")]
    pub(super) anti_features: HashMap<AntiFeature, HashMap<String, String>>,
}

/// An [anti-feature](https://f-droid.org/docs/Anti-Features/).
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(super) enum AntiFeature {
    Ads,
    DisabledAlgorithm,
    KnownVuln,
    NoSourceSince,
    NonFreeAdd,
    NonFreeAssets,
    NonFreeDep,
    NonFreeNet,
    TetheredNet,
    Tracking,
    Other(String),
}

impl<'de> Deserialize<'de> for AntiFeature {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let name = String::deserialize(deserializer)?;
        Ok(match name.as_str() {
            "Ads" => Self::Ads,
            "DisabledAlgorithm" => Self::DisabledAlgorithm,
            "KnownVuln" => Self::KnownVuln,
            "NoSourceSince" => Self::NoSourceSince,
            "NonFreeAdd" => Self::NonFreeAdd,
            "NonFreeAssets" => Self::NonFreeAssets,
            "NonFreeDep" => Self::NonFreeDep,
            "NonFreeNet" => Self::NonFreeNet,
            "TetheredNet" => Self::TetheredNet,
            "Tracking" => Self::Tracking,
            _ => {
                tracing::warn!("observed unknown F-Droid anti-feature {name}");
                Self::Other(name)
            }
        })
    }
}

#[derive(Debug, Deserialize)]
pub(super) struct Metadata {
    pub(super) added: u64,
    /// App names keyed by locale. Every package has an `en-US` name.
    #[serde(default)]
    pub(super) name: HashMap<String, String>,
    /// Short app descriptions keyed by locale.
    #[serde(default)]
    pub(super) summary: HashMap<String, String>,
    /// Screenshots keyed first by device type and then by locale.
    #[serde(default)]
    pub(super) screenshots: HashMap<String, HashMap<String, Vec<Screenshot>>>,
}

#[derive(Debug, Deserialize)]
pub(super) struct Screenshot {
    /// Path to the screenshot relative to the repository address.
    pub(super) name: String,
    /// Screenshot file size in bytes, retained for enforcing upload limits.
    #[allow(dead_code)]
    pub(super) size: u64,
}