Add the ability to detect software from semver build metadata

This commit is contained in:
CenTdemeern1 2025-01-13 07:31:48 +01:00
parent 8e6a2d20b4
commit 84639fa3b5
5 changed files with 64 additions and 10 deletions

7
Cargo.lock generated
View file

@ -281,6 +281,7 @@ version = "0.1.0"
dependencies = [
"reqwest",
"rocket",
"semver",
"serde",
"serde_json",
"url",
@ -1537,6 +1538,12 @@ dependencies = [
"libc",
]
[[package]]
name = "semver"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
[[package]]
name = "serde"
version = "1.0.217"

View file

@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
reqwest = "0.12.12"
rocket = { version = "0.5.1", features = ["json"] }
semver = "1.0.24"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.135"
url = "2.5.4"

View file

@ -88,6 +88,31 @@
],
"forkOf": "mastodon"
},
"glitch-soc": {
"name": "Mastodon Glitch Edition",
"nodeinfoName": "mastodon",
"buildMetadata": "glitch",
"aliases": [
"glitch"
],
"groups": [
"mastodon-compliant",
"mastodon-compliant-api"
],
"forkOf": "mastodon"
},
"chuckya": {
"name": "Chuckya",
"nodeinfoName": "mastodon",
"buildMetadata": "chuckya",
"aliases": [
"chuckya"
],
"groups": [
"mastodon-compliant"
],
"forkOf": "mastodon"
},
"misskey": {
"name": "Misskey",
"nodeinfoName": "misskey",

View file

@ -53,6 +53,7 @@ struct NodeInfo {
#[derive(Deserialize)]
struct NodeInfoSoftware {
name: String,
version: String,
}
#[derive(Deserialize)]
@ -105,8 +106,11 @@ pub async fn instance_info(secure: bool, host: &str) -> Option<Json<InstanceInfo
.await
.ok()?;
let nodeinfo: NodeInfo = serde_json::from_str(&response).ok()?;
let software = KNOWN_SOFTWARE_NODEINFO_NAMES
.get(&nodeinfo.software.name)?
let (software_name, fork_map) = KNOWN_SOFTWARE_NODEINFO_NAMES.get(&nodeinfo.software.name)?;
let software = semver::Version::parse(&nodeinfo.software.version)
.ok()
.and_then(|v| fork_map.get(v.build.as_str()))
.unwrap_or(software_name)
.to_owned();
Some(Json(InstanceInfo {
name: name

View file

@ -9,14 +9,16 @@ pub static KNOWN_SOFTWARE: LazyLock<KnownSoftware> =
LazyLock::new(|| serde_json::from_str(include_str!("../known-software.json")).unwrap());
pub static KNOWN_SOFTWARE_NAMES: LazyLock<HashMap<String, String>> =
LazyLock::new(|| KNOWN_SOFTWARE.get_name_map());
pub static KNOWN_SOFTWARE_NODEINFO_NAMES: LazyLock<HashMap<String, String>> =
LazyLock::new(|| KNOWN_SOFTWARE.get_nodeinfo_name_map());
pub static KNOWN_SOFTWARE_NODEINFO_NAMES: LazyLock<
HashMap<String, (String, HashMap<String, String>)>,
> = LazyLock::new(|| KNOWN_SOFTWARE.get_nodeinfo_name_map());
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Software {
name: String,
nodeinfo_name: String,
build_metadata: Option<String>,
aliases: HashSet<String>,
groups: HashSet<String>,
fork_of: Option<String>,
@ -50,13 +52,28 @@ impl KnownSoftware {
map
}
fn get_nodeinfo_name_map(&self) -> HashMap<String, String> {
let mut map = HashMap::new();
fn get_nodeinfo_name_map(&self) -> HashMap<String, (String, HashMap<String, String>)> {
let mut map: HashMap<String, (String, HashMap<String, String>)> = HashMap::new();
self.software.iter().for_each(|(name, software)| {
assert_eq!(
map.insert(software.nodeinfo_name.to_owned(), name.to_owned()),
None
);
if let Some((mut_name, mut_map)) = map.get_mut(&software.nodeinfo_name) {
if let Some(build_metadata) = &software.build_metadata {
assert_eq!(
mut_map.insert(build_metadata.to_owned(), name.to_owned()),
None
);
} else {
*mut_name = name.to_owned();
}
} else {
let mut build_metadata_map = HashMap::new();
if let Some(build_metadata) = &software.build_metadata {
build_metadata_map.insert(build_metadata.to_owned(), name.to_owned());
}
map.insert(
software.nodeinfo_name.to_owned(),
(name.to_owned(), build_metadata_map),
);
}
});
map
}