add guestbook and moderation

This commit is contained in:
2026-09-17 07:30:38 +07:00
parent d1b83fdc33
commit ea9abae554
7 changed files with 1196 additions and 58 deletions
+81 -4
View File
@@ -5,14 +5,15 @@ use nostr_sdk::prelude::{Event, Keys, PublicKey, Timestamp, UnsignedEvent};
use serde::{Deserialize, Serialize};
use crate::derive::{
community_id_of, control_group_key, control_signer_group_key, verify_community_id,
banlist_locator, community_id_of, control_group_key, control_signer_group_key, grant_locator,
verify_community_id,
};
use crate::edition::{
AuthorityCitation, EditionFields, EditionMeta, EntityHead, Floors, ParsedEdition,
build_edition, fold_head, parse_edition, vsk,
};
use crate::roles::{
AuthorityEdition, CommunityRoles, Permissions, Roster, citation_ok, fold_roster,
AuthorityEdition, CommunityRoles, Grant, Permissions, Role, Roster, citation_ok, fold_roster,
};
use crate::stream::{KIND_WRAP, SealForm, build_seal, open_wrap_at, wrap_seal_with};
use crate::{ChannelId, CommunityId, Epoch, Extra, GroupKey, random_32};
@@ -220,6 +221,7 @@ impl ControlWriter {
community_id: &CommunityId,
metadata: &CommunityMetadata,
head: Option<&EntityHead>,
citation: Option<AuthorityCitation>,
at_secs: u64,
) -> Result<(Event, EntityHead)> {
let content = encode_metadata(metadata)?;
@@ -231,7 +233,7 @@ impl ControlWriter {
entity: *community_id.as_bytes(),
content: &content,
head,
citation: None,
citation,
},
at_secs,
)
@@ -243,6 +245,7 @@ impl ControlWriter {
channel: &ChannelId,
metadata: &ChannelMetadata,
head: Option<&EntityHead>,
citation: Option<AuthorityCitation>,
at_secs: u64,
) -> Result<(Event, EntityHead)> {
let content = serde_json::to_string(metadata)?;
@@ -254,7 +257,79 @@ impl ControlWriter {
entity: *channel.as_bytes(),
content: &content,
head,
citation: None,
citation,
},
at_secs,
)
}
pub fn set_role(
&self,
keys: &Keys,
role: &Role,
head: Option<&EntityHead>,
citation: Option<AuthorityCitation>,
at_secs: u64,
) -> Result<(Event, EntityHead)> {
let content = role.to_content()?;
self.publish(
keys,
Edition {
subkind: vsk::ROLE,
entity: *role.role_id.as_bytes(),
content: &content,
head,
citation,
},
at_secs,
)
}
pub fn set_grant(
&self,
keys: &Keys,
community_id: &CommunityId,
grant: &Grant,
head: Option<&EntityHead>,
citation: Option<AuthorityCitation>,
at_secs: u64,
) -> Result<(Event, EntityHead)> {
let content = grant.to_content()?;
self.publish(
keys,
Edition {
subkind: vsk::GRANT,
entity: grant_locator(community_id, &grant.member.to_bytes()),
content: &content,
head,
citation,
},
at_secs,
)
}
pub fn set_banlist(
&self,
keys: &Keys,
community_id: &CommunityId,
banned: &BTreeSet<PublicKey>,
head: Option<&EntityHead>,
citation: Option<AuthorityCitation>,
at_secs: u64,
) -> Result<(Event, EntityHead)> {
let entries: Vec<String> = banned.iter().map(PublicKey::to_hex).collect();
let content = serde_json::to_string(&entries)?;
self.publish(
keys,
Edition {
subkind: vsk::BANLIST,
entity: banlist_locator(community_id),
content: &content,
head,
citation,
},
at_secs,
)
@@ -600,6 +675,7 @@ mod tests {
..metadata("coop two")
},
Some(community_head),
None,
AT + 1,
)
.expect("publishes");
@@ -613,6 +689,7 @@ mod tests {
..ChannelMetadata::default()
},
Some(channel_head),
None,
AT + 2,
)
.expect("publishes");