From dd1b44132199aa72c2b699e1160fbe6b885f0ef6 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 3 Dec 2025 16:15:55 +0000 Subject: landing page: display relay inforamtion document --- src/http/landing.rs | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/http/nip11.rs | 8 +--- 2 files changed, 133 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/http/landing.rs b/src/http/landing.rs index c76a7e6..8ab4a68 100644 --- a/src/http/landing.rs +++ b/src/http/landing.rs @@ -398,7 +398,7 @@ fn generate_nip_cards(nip11: &RelayInformationDocument) -> String { if let Some(meta) = metadata.get(nip) { html.push_str(&format!( r#"
-
NIP-{:02} {}
+
NIP-{:02} {}
{}
"#, nip, meta.title, meta.description @@ -407,7 +407,7 @@ fn generate_nip_cards(nip11: &RelayInformationDocument) -> String { // Fallback for unknown NIPs - still show them html.push_str(&format!( r#"
-
NIP-{:02}
+
NIP-{:02}
"#, nip )); @@ -418,6 +418,129 @@ fn generate_nip_cards(nip11: &RelayInformationDocument) -> String { html } +/// Escape HTML special characters +fn escape_html(s: &str) -> String { + s.replace('&', "&") + .replace('<', "<") + .replace('>', ">") + .replace('"', """) + .replace('\'', "'") +} + +/// Generate table rows for NIP-11 relay information +fn generate_relay_info_rows(nip11: &RelayInformationDocument) -> String { + let mut html = String::new(); + + // Follow NIP-11 document order: + // name + html.push_str(&format!( + r#"name{}"#, + escape_html(&nip11.name) + )); + html.push('\n'); + + // description + html.push_str(&format!( + r#"description{}"#, + escape_html(&nip11.description) + )); + html.push('\n'); + + // pubkey (if present) + if let Some(ref pubkey) = nip11.pubkey { + html.push_str(&format!( + r#"pubkey{}"#, + escape_html(pubkey) + )); + html.push('\n'); + } + + // contact (if present) + if let Some(ref contact) = nip11.contact { + html.push_str(&format!( + r#"contact{}"#, + escape_html(contact) + )); + html.push('\n'); + } + + // supported_nips + let nips_str = nip11 + .supported_nips + .iter() + .map(|n| n.to_string()) + .collect::>() + .join(", "); + html.push_str(&format!( + r#"supported_nips{}"#, + nips_str + )); + html.push('\n'); + + // software + html.push_str(&format!( + r#"software{}"#, + escape_html(&nip11.software), + escape_html(&nip11.software) + )); + html.push('\n'); + + // version + html.push_str(&format!( + r#"version{}"#, + escape_html(&nip11.version) + )); + html.push('\n'); + + // icon (if present) + if let Some(ref icon) = nip11.icon { + html.push_str(&format!( + r#"icon{}"#, + escape_html(icon), + escape_html(icon) + )); + html.push('\n'); + } + + // GRASP-01 Extensions: + // supported_grasps + let grasps_str = nip11.supported_grasps.join(", "); + html.push_str(&format!( + r#"supported_grasps{}"#, + escape_html(&grasps_str) + )); + html.push('\n'); + + // repo_acceptance_criteria + html.push_str(&format!( + r#"repo_acceptance_criteria{}"#, + escape_html(&nip11.repo_acceptance_criteria) + )); + html.push('\n'); + + // curation (if present) + if let Some(ref curation) = nip11.curation { + html.push_str(&format!( + r#"curation{}"#, + escape_html(curation) + )); + html.push('\n'); + } + + html +} + +/// Generate the relay icon HTML for the header +fn generate_relay_icon_html(nip11: &RelayInformationDocument) -> String { + match &nip11.icon { + Some(icon_url) => format!( + r#"Relay Icon"#, + escape_html(icon_url) + ), + None => String::new(), + } +} + /// Generate the HTML landing page pub fn get_html(config: &Config) -> String { // Get NIP-11 document for supported NIPs and GRASPs @@ -430,6 +553,8 @@ pub fn get_html(config: &Config) -> String { let hero_tags = generate_hero_tags(&nip11); let grasp_cards = generate_grasp_cards(&nip11); let nip_cards = generate_nip_cards(&nip11); + let relay_info_rows = generate_relay_info_rows(&nip11); + let relay_icon = generate_relay_icon_html(&nip11); format!( include_str!("../../templates/landing.html"), @@ -437,12 +562,16 @@ pub fn get_html(config: &Config) -> String { relay_name = config.relay_name(), relay_description = config.relay_description, version = get_version(), + nip11_version = escape_html(&nip11.version), curation = curation, + repo_acceptance_criteria = escape_html(&nip11.repo_acceptance_criteria), theme_toggle = get_theme_toggle_html(), theme_script = get_theme_script(), hero_tags = hero_tags, grasp_cards = grasp_cards, nip_cards = nip_cards, + relay_info_rows = relay_info_rows, + relay_icon = relay_icon, ) } diff --git a/src/http/nip11.rs b/src/http/nip11.rs index 2a37385..1ed80de 100644 --- a/src/http/nip11.rs +++ b/src/http/nip11.rs @@ -76,11 +76,7 @@ impl RelayInformationDocument { // GRASP-01 Extensions supported_grasps: vec!["GRASP-01".to_string()], - repo_acceptance_criteria: format!( - "Repositories must list this relay ({}) in both 'clone' and 'relays' tags of kind 30617 announcements. \ - All other events must reference accepted repositories or accepted events.", - config.domain - ), + repo_acceptance_criteria: "None".to_string(), curation: None, // Not a curated relay - only SPAM prevention via GRASP-01 policy } } @@ -118,7 +114,7 @@ mod tests { assert!(doc.supported_nips.contains(&34)); assert!(doc.supported_nips.contains(&77)); assert_eq!(doc.supported_grasps, vec!["GRASP-01"]); - assert!(doc.repo_acceptance_criteria.contains("relay.example.com")); + assert!(doc.repo_acceptance_criteria.contains("None")); assert!(doc.curation.is_none()); assert_eq!( doc.icon, -- cgit v1.2.3