From 5d02ad6b893f9059044914c115d77cf9d8e589c3 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Thu, 8 Jan 2026 11:20:35 +0000 Subject: refactor: replace hardcoded Kind constants with rust-nostr variants - Replace KIND_REPOSITORY_ANNOUNCEMENT with Kind::GitRepoAnnouncement - Replace KIND_REPOSITORY_STATE with Kind::RepoState - Replace KIND_PR with Kind::GitPullRequest - Replace KIND_PR_UPDATE with Kind::GitPullRequestUpdate - Replace KIND_USER_GRASP_LIST with Kind::GitUserGraspList - Replace KIND_PATCH with Kind::GitPatch - Replace KIND_ISSUE with Kind::GitIssue - Replace KIND_COMMENT with Kind::Comment - Replace all Kind::Custom(30617|30618|1617|1618|1619|1621|1111|10317) patterns - Remove all hardcoded KIND_* constants from events.rs - Update all match statements to use Kind enum directly - Update all filter builders to use Kind variants - Update all test helpers and assertions Benefits: - Type safety: compiler prevents wrong kind numbers - Readability: Kind::GitRepoAnnouncement is self-documenting - Maintainability: single source of truth (rust-nostr) - IDE support: full autocompletion and refactoring - Standards: aligns with rust-nostr best practices Files modified: 21 Constants removed: 9 Patterns replaced: 100+ Tests passing: 222/222 --- src/git/authorization.rs | 32 +++++++++-------------- src/nostr/builder.rs | 17 ++++++------ src/nostr/events.rs | 56 +++++++++++++++++----------------------- src/nostr/policy/announcement.rs | 14 ++++------ src/sync/filters.rs | 6 ++--- src/sync/self_subscriber.rs | 24 ++++++++--------- 6 files changed, 64 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/git/authorization.rs b/src/git/authorization.rs index 7502a52..e174b51 100644 --- a/src/git/authorization.rs +++ b/src/git/authorization.rs @@ -36,11 +36,9 @@ use std::sync::Arc; use tracing::{debug, info, warn}; use crate::nostr::builder::SharedDatabase; -use crate::nostr::events::{ - RepositoryAnnouncement, RepositoryState, KIND_PR, KIND_PR_UPDATE, KIND_REPOSITORY_ANNOUNCEMENT, - KIND_REPOSITORY_STATE, -}; +use crate::nostr::events::{RepositoryAnnouncement, RepositoryState}; use crate::purgatory::Purgatory; +use nostr_sdk::Kind; /// Perform GRASP authorization for a push operation /// @@ -241,10 +239,7 @@ pub async fn fetch_repository_data( identifier: &str, ) -> Result { let filter = Filter::new() - .kinds([ - Kind::from(KIND_REPOSITORY_ANNOUNCEMENT), - Kind::from(KIND_REPOSITORY_STATE), - ]) + .kinds([Kind::GitRepoAnnouncement, Kind::RepoState]) .custom_tag( SingleLetterTag::lowercase(Alphabet::D), identifier.to_string(), @@ -268,11 +263,11 @@ pub async fn fetch_repository_data( let mut states = Vec::new(); for event in events { - if event.kind == Kind::from(KIND_REPOSITORY_ANNOUNCEMENT) { + if event.kind == Kind::GitRepoAnnouncement { if let Ok(announcement) = RepositoryAnnouncement::from_event(event) { announcements.push(announcement); } - } else if event.kind == Kind::from(KIND_REPOSITORY_STATE) { + } else if event.kind == Kind::RepoState { if let Ok(state) = RepositoryState::from_event(event) { states.push(state); } @@ -714,10 +709,7 @@ impl AuthorizationContext { /// This matches the reference implementation's filter logic pub fn create_filter(identifier: &str) -> Filter { Filter::new() - .kinds([ - Kind::from(KIND_REPOSITORY_ANNOUNCEMENT), - Kind::from(KIND_REPOSITORY_STATE), - ]) + .kinds([Kind::GitRepoAnnouncement, Kind::RepoState]) .custom_tag( SingleLetterTag::lowercase(Alphabet::D), identifier.to_string(), @@ -754,7 +746,7 @@ impl AuthorizationContext { for event in &self.events { // Check if it's a repository state event - if event.kind != Kind::from(KIND_REPOSITORY_STATE) { + if event.kind != Kind::RepoState { continue; } @@ -806,7 +798,7 @@ impl AuthorizationContext { for event in &self.events { // Only look at announcements - if event.kind != Kind::from(KIND_REPOSITORY_ANNOUNCEMENT) { + if event.kind != Kind::GitRepoAnnouncement { continue; } @@ -838,7 +830,7 @@ impl AuthorizationContext { pub fn is_state_authorized(&self, state_pubkey: &str, identifier: &str) -> bool { for event in &self.events { // Only look at announcements - if event.kind != Kind::from(KIND_REPOSITORY_ANNOUNCEMENT) { + if event.kind != Kind::GitRepoAnnouncement { continue; } @@ -1093,7 +1085,7 @@ pub async fn get_event_commit_tag( // Query for PR (1618) and PR Update (1619) events with this ID let filter = Filter::new() .ids([*event_id]) - .kinds([Kind::from(KIND_PR), Kind::from(KIND_PR_UPDATE)]); + .kinds([Kind::GitPullRequest, Kind::GitPullRequestUpdate]); let events: Vec = database .query(filter) @@ -1224,7 +1216,7 @@ mod tests { vec!["wss://example.com".to_string()], )); - EventBuilder::new(Kind::from(KIND_REPOSITORY_ANNOUNCEMENT), "Test repo") + EventBuilder::new(Kind::GitRepoAnnouncement, "Test repo") .tags(tags) .sign_with_keys(keys) .unwrap() @@ -1240,7 +1232,7 @@ mod tests { )); } - EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(keys) .unwrap() diff --git a/src/nostr/builder.rs b/src/nostr/builder.rs index 81f7fbb..939ccef 100644 --- a/src/nostr/builder.rs +++ b/src/nostr/builder.rs @@ -12,10 +12,7 @@ use nostr_lmdb::NostrLmdb; use nostr_relay_builder::prelude::*; use crate::config::{Config, DatabaseBackend}; -use crate::nostr::events::{ - RepositoryAnnouncement, KIND_PR, KIND_PR_UPDATE, KIND_REPOSITORY_ANNOUNCEMENT, - KIND_REPOSITORY_STATE, KIND_USER_GRASP_LIST, -}; +use crate::nostr::events::RepositoryAnnouncement; use crate::nostr::policy::{ AnnouncementPolicy, AnnouncementResult, PolicyContext, PrEventPolicy, ReferenceResult, RelatedEventPolicy, StatePolicy, StateResult, @@ -377,11 +374,13 @@ impl WritePolicy for Nip34WritePolicy { // Sync uses localhost:0 as a dummy address let is_synced = addr.ip().is_loopback() && addr.port() == 0; - match event.kind.as_u16() { - KIND_REPOSITORY_ANNOUNCEMENT => self.handle_announcement(event).await, - KIND_REPOSITORY_STATE => self.handle_state(event, is_synced).await, - KIND_PR | KIND_PR_UPDATE => self.handle_pr_event(event, is_synced).await, - KIND_USER_GRASP_LIST => { + match event.kind { + Kind::GitRepoAnnouncement => self.handle_announcement(event).await, + Kind::RepoState => self.handle_state(event, is_synced).await, + Kind::GitPullRequest | Kind::GitPullRequestUpdate => { + self.handle_pr_event(event, is_synced).await + } + Kind::GitUserGraspList => { // Accept all kind 10317 (User Grasp List) events // for better GRASP repository discovery tracing::debug!( diff --git a/src/nostr/events.rs b/src/nostr/events.rs index 1fcb75e..4f7c907 100644 --- a/src/nostr/events.rs +++ b/src/nostr/events.rs @@ -9,20 +9,12 @@ use anyhow::{anyhow, Result}; use nostr_sdk::{Event, Kind, TagKind, ToBech32}; -/// NIP-34 Repository Announcement (kind 30617) -pub const KIND_REPOSITORY_ANNOUNCEMENT: u16 = 30617; - -/// NIP-34 Repository State Announcement (kind 30618) -pub const KIND_REPOSITORY_STATE: u16 = 30618; - -/// NIP-34 Pull Request (kind 1618) - has `c` tag for commit -pub const KIND_PR: u16 = 1618; - -/// NIP-34 Pull Request Update (kind 1619) - has `c` tag for commit -pub const KIND_PR_UPDATE: u16 = 1619; - -/// User Grasp List (kind 10317) - user's personal list of GRASP repositories -pub const KIND_USER_GRASP_LIST: u16 = 10317; +// NOTE: Using rust-nostr Kind variants instead of hardcoded constants: +// - KIND_REPOSITORY_ANNOUNCEMENT -> Kind::GitRepoAnnouncement (30617) +// - KIND_REPOSITORY_STATE -> Kind::RepoState (30618) +// - KIND_PR -> Kind::GitPullRequest (1618) +// - KIND_PR_UPDATE -> Kind::GitPullRequestUpdate (1619) +// - KIND_USER_GRASP_LIST -> Kind::GitUserGraspList (10317) /// Repository announcement details extracted from NIP-34 event #[derive(Debug, Clone)] @@ -40,10 +32,10 @@ pub struct RepositoryAnnouncement { impl RepositoryAnnouncement { /// Parse a repository announcement from a NIP-34 kind 30617 event pub fn from_event(event: Event) -> Result { - if event.kind != Kind::from(KIND_REPOSITORY_ANNOUNCEMENT) { + if event.kind != Kind::GitRepoAnnouncement { return Err(anyhow!( "Invalid event kind: expected {}, got {}", - KIND_REPOSITORY_ANNOUNCEMENT, + Kind::GitRepoAnnouncement, event.kind )); } @@ -197,10 +189,10 @@ pub struct TagState { impl RepositoryState { /// Parse a repository state from a NIP-34 kind 30618 event pub fn from_event(event: Event) -> Result { - if event.kind != Kind::from(KIND_REPOSITORY_STATE) { + if event.kind != Kind::RepoState { return Err(anyhow!( "Invalid event kind: expected {}, got {}", - KIND_REPOSITORY_STATE, + Kind::RepoState, event.kind )); } @@ -346,10 +338,10 @@ impl RepositoryState { /// Returns Ok(()) if valid, Err with reason if invalid. pub fn validate_announcement(event: &Event, domain: &str) -> Result<()> { // Must be kind 30617 - if event.kind != Kind::from(KIND_REPOSITORY_ANNOUNCEMENT) { + if event.kind != Kind::GitRepoAnnouncement { return Err(anyhow!( "Invalid kind: expected {}", - KIND_REPOSITORY_ANNOUNCEMENT + Kind::GitRepoAnnouncement )); } @@ -381,8 +373,8 @@ pub fn validate_announcement(event: &Event, domain: &str) -> Result<()> { /// Returns Ok(()) if valid, Err with reason if invalid. pub fn validate_state(event: &Event) -> Result<()> { // Must be kind 30618 - if event.kind != Kind::from(KIND_REPOSITORY_STATE) { - return Err(anyhow!("Invalid kind: expected {}", KIND_REPOSITORY_STATE)); + if event.kind != Kind::RepoState { + return Err(anyhow!("Invalid kind: expected {}", Kind::RepoState)); } // Must have identifier @@ -433,7 +425,7 @@ mod tests { )); } - EventBuilder::new(Kind::from(KIND_REPOSITORY_ANNOUNCEMENT), "Test repository") + EventBuilder::new(Kind::GitRepoAnnouncement, "Test repository") .tags(tags) .sign_with_keys(keys) .unwrap() @@ -454,7 +446,7 @@ mod tests { )); } - EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(keys) .unwrap() @@ -483,7 +475,7 @@ mod tests { #[test] fn test_parse_announcement_missing_identifier() { let keys = create_test_keys(); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_ANNOUNCEMENT), "Test repository") + let event = EventBuilder::new(Kind::GitRepoAnnouncement, "Test repository") .sign_with_keys(&keys) .unwrap(); @@ -579,7 +571,7 @@ mod tests { #[test] fn test_validate_state_missing_identifier() { let keys = create_test_keys(); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + let event = EventBuilder::new(Kind::RepoState, "") .sign_with_keys(&keys) .unwrap(); @@ -614,7 +606,7 @@ mod tests { vec![maintainer_keys.public_key().to_hex()], )); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_ANNOUNCEMENT), "Test repository") + let event = EventBuilder::new(Kind::GitRepoAnnouncement, "Test repository") .tags(tags) .sign_with_keys(&keys) .unwrap(); @@ -649,7 +641,7 @@ mod tests { vec!["e5f6g7h8".to_string()], )); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + let event = EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(&keys) .unwrap(); @@ -683,7 +675,7 @@ mod tests { vec!["ref: refs/heads/main".to_string()], )); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + let event = EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(&keys) .unwrap(); @@ -716,7 +708,7 @@ mod tests { vec!["refs/heads/develop".to_string()], )); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + let event = EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(&keys) .unwrap(); @@ -740,7 +732,7 @@ mod tests { ), ]; - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + let event = EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(&keys) .unwrap(); @@ -773,7 +765,7 @@ mod tests { vec!["refs/heads/develop".to_string()], )); - let event = EventBuilder::new(Kind::from(KIND_REPOSITORY_STATE), "") + let event = EventBuilder::new(Kind::RepoState, "") .tags(tags) .sign_with_keys(&keys) .unwrap(); diff --git a/src/nostr/policy/announcement.rs b/src/nostr/policy/announcement.rs index 353738b..61840fb 100644 --- a/src/nostr/policy/announcement.rs +++ b/src/nostr/policy/announcement.rs @@ -5,9 +5,7 @@ use nostr_relay_builder::prelude::{Alphabet, Event, Filter, Kind, PublicKey, SingleLetterTag}; use super::PolicyContext; -use crate::nostr::events::{ - validate_announcement, RepositoryAnnouncement, KIND_REPOSITORY_ANNOUNCEMENT, -}; +use crate::nostr::events::{validate_announcement, RepositoryAnnouncement}; /// Result of announcement policy evaluation #[derive(Debug)] @@ -121,12 +119,10 @@ impl AnnouncementPolicy { author: &PublicKey, ) -> Result { // Query all announcements with this identifier that are already in the database - let filter = Filter::new() - .kind(Kind::from(KIND_REPOSITORY_ANNOUNCEMENT)) - .custom_tag( - SingleLetterTag::lowercase(Alphabet::D), - identifier.to_string(), - ); + let filter = Filter::new().kind(Kind::GitRepoAnnouncement).custom_tag( + SingleLetterTag::lowercase(Alphabet::D), + identifier.to_string(), + ); let announcements: Vec = match self.ctx.database.query(filter).await { Ok(events) => events.into_iter().collect(), diff --git a/src/sync/filters.rs b/src/sync/filters.rs index dddc49c..c4e20e7 100644 --- a/src/sync/filters.rs +++ b/src/sync/filters.rs @@ -20,9 +20,9 @@ use nostr_sdk::prelude::*; /// Note: 10317 (User Grasp List) is synced for better GRASP discovery. pub fn build_announcement_filter(since: Option) -> Filter { let filter = Filter::new().kinds([ - Kind::Custom(30617), // Repository announcements - Kind::Custom(30618), // Maintainer lists - Kind::Custom(10317), // User Grasp List + Kind::GitRepoAnnouncement, // Repository announcements + Kind::RepoState, // Repository state + Kind::GitUserGraspList, // User Grasp List ]); match since { diff --git a/src/sync/self_subscriber.rs b/src/sync/self_subscriber.rs index 09e3b56..9f6fa70 100644 --- a/src/sync/self_subscriber.rs +++ b/src/sync/self_subscriber.rs @@ -149,7 +149,7 @@ impl SelfSubscriber { match notification { Ok(RelayPoolNotification::Event { event, .. }) => { // Only process 30617 events that list our relay - if event.kind == Kind::Custom(30617) { + if event.kind == Kind::GitRepoAnnouncement { if !self.lists_our_relay(&event) { return LoopControl::Continue; } @@ -236,7 +236,7 @@ impl SelfSubscriber { /// Format: 30617:pubkey:identifier fn extract_repo_id(event: &Event) -> Option { // For kind 30617, extract d tag and build addressable ref - if event.kind == Kind::Custom(30617) { + if event.kind == Kind::GitRepoAnnouncement { for tag in event.tags.iter() { let tag_vec = tag.as_slice(); if tag_vec.len() >= 2 && tag_vec[0] == "d" { @@ -296,21 +296,21 @@ impl SelfSubscriber { ); Filter::new() .kinds(vec![ - Kind::Custom(30617), // Repository Announcements - Kind::Custom(1617), // Patches - Kind::Custom(1621), // Issues - Kind::Custom(1618), // Pull Requests - Kind::Custom(10317), // User Grasp List + Kind::GitRepoAnnouncement, // Repository Announcements + Kind::GitPatch, // Patches + Kind::GitIssue, // Issues + Kind::GitPullRequest, // Pull Requests + Kind::GitUserGraspList, // User Grasp List ]) .since(since) } else { // First connection - no since filter Filter::new().kinds(vec![ - Kind::Custom(30617), // Repository Announcements - Kind::Custom(1617), // Patches - Kind::Custom(1621), // Issues - Kind::Custom(1618), // Pull Requests - Kind::Custom(10317), // User Grasp List + Kind::GitRepoAnnouncement, // Repository Announcements + Kind::GitPatch, // Patches + Kind::GitIssue, // Issues + Kind::GitPullRequest, // Pull Requests + Kind::GitUserGraspList, // User Grasp List ]) }; -- cgit v1.2.3