-
-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
nostr: add
nip22::extract_root
and nip22:extract_parent
Closes #677 Signed-off-by: Yuki Kishimoto <yukikishimoto@protonmail.com>
- Loading branch information
Showing
4 changed files
with
163 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// Copyright (c) 2022-2023 Yuki Kishimoto | ||
// Copyright (c) 2023-2024 Rust Nostr Developers | ||
// Distributed under the MIT software license | ||
|
||
//! NIP22: Comment | ||
//! | ||
//! <https://github.com/nostr-protocol/nips/blob/master/22.md> | ||
use crate::nips::nip01::Coordinate; | ||
use crate::nips::nip73::ExternalContentId; | ||
use crate::{Event, EventId, Kind, PublicKey, RelayUrl, TagKind, TagStandard, Url}; | ||
|
||
/// Borrowed comment extracted data | ||
pub enum Comment<'a> { | ||
/// Event | ||
Event { | ||
/// Event ID | ||
id: &'a EventId, | ||
/// Relay hint | ||
relay_hint: Option<&'a RelayUrl>, | ||
/// Public key hint | ||
pubkey_hint: Option<&'a PublicKey>, | ||
/// Kind | ||
kind: Option<&'a Kind>, | ||
}, | ||
/// Coordinate | ||
Coordinate { | ||
/// Coordinate | ||
address: &'a Coordinate, | ||
/// Relay hint | ||
relay_hint: Option<&'a RelayUrl>, | ||
/// Kind | ||
kind: Option<&'a Kind>, | ||
}, | ||
/// External content | ||
External { | ||
/// Content | ||
content: &'a ExternalContentId, | ||
/// Web hint | ||
hint: Option<&'a Url>, | ||
/// Kind | ||
/// | ||
/// This isn't properly defined yet but it will surely be needed in the future. It could i.e. be a root domain | ||
kind: Option<&'a Kind>, | ||
}, | ||
} | ||
|
||
/// Extract NIP22 root data | ||
pub fn extract_root(event: &Event) -> Option<Comment> { | ||
extract_data(event, true) | ||
} | ||
|
||
/// Extract NIP22 parent data | ||
pub fn extract_parent(event: &Event) -> Option<Comment> { | ||
extract_data(event, false) | ||
} | ||
|
||
fn extract_data(event: &Event, is_root: bool) -> Option<Comment> { | ||
if event.kind != Kind::Comment { | ||
return None; | ||
} | ||
|
||
let kind: Option<&Kind> = extract_kind(event, is_root); | ||
let pubkey_hint: Option<&PublicKey> = extract_public_key(event, is_root); | ||
|
||
// Try to extract event | ||
if let Some((event_id, relay_hint)) = extract_event(event, is_root) { | ||
return Some(Comment::Event { | ||
id: event_id, | ||
relay_hint, | ||
pubkey_hint, | ||
kind, | ||
}); | ||
} | ||
|
||
// Try to extract coordinate | ||
if let Some((address, relay_hint)) = extract_coordinate(event, is_root) { | ||
return Some(Comment::Coordinate { | ||
address, | ||
relay_hint, | ||
kind, | ||
}); | ||
} | ||
|
||
if let Some((content, hint)) = extract_external(event, is_root) { | ||
return Some(Comment::External { | ||
content, | ||
hint, | ||
kind, | ||
}); | ||
} | ||
|
||
None | ||
} | ||
|
||
fn check_return<T>(val: T, is_root: bool, uppercase: bool) -> Option<T> { | ||
if (is_root && uppercase) || (!is_root && !uppercase) { | ||
return Some(val); | ||
} | ||
|
||
None | ||
} | ||
|
||
fn extract_kind(event: &Event, is_root: bool) -> Option<&Kind> { | ||
let tag = event.tags.find_standardized(TagKind::k())?; | ||
match tag { | ||
TagStandard::Kind { kind, uppercase } => check_return(kind, is_root, *uppercase), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn extract_public_key(event: &Event, is_root: bool) -> Option<&PublicKey> { | ||
let tag = event.tags.find_standardized(TagKind::p())?; | ||
match tag { | ||
TagStandard::PublicKey { | ||
public_key, | ||
uppercase, | ||
.. | ||
} => check_return(public_key, is_root, *uppercase), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn extract_event(event: &Event, is_root: bool) -> Option<(&EventId, Option<&RelayUrl>)> { | ||
let tag = event.tags.find_standardized(TagKind::e())?; | ||
match tag { | ||
TagStandard::Event { | ||
event_id, | ||
relay_url, | ||
uppercase, | ||
.. | ||
} => check_return((event_id, relay_url.as_ref()), is_root, *uppercase), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn extract_coordinate(event: &Event, is_root: bool) -> Option<(&Coordinate, Option<&RelayUrl>)> { | ||
let tag = event.tags.find_standardized(TagKind::a())?; | ||
match tag { | ||
TagStandard::Coordinate { | ||
coordinate, | ||
relay_url, | ||
uppercase, | ||
.. | ||
} => check_return((coordinate, relay_url.as_ref()), is_root, *uppercase), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn extract_external(event: &Event, is_root: bool) -> Option<(&ExternalContentId, Option<&Url>)> { | ||
let tag = event.tags.find_standardized(TagKind::i())?; | ||
match tag { | ||
TagStandard::ExternalContent { | ||
content, | ||
hint, | ||
uppercase, | ||
} => check_return((content, hint.as_ref()), is_root, *uppercase), | ||
_ => None, | ||
} | ||
} |