add control fold and roster

This commit is contained in:
2026-09-16 20:05:51 +07:00
parent d926c1e3ea
commit 4329385abe
8 changed files with 2016 additions and 111 deletions
+47 -11
View File
@@ -5,9 +5,11 @@ use anyhow::{Result, anyhow};
use nostr_sdk::prelude::*;
use serde::{Deserialize, Serialize};
use crate::control::{ChannelMetadata, CommunityGenesis, CommunityMetadata, ROOT_EPOCH};
use crate::control::{
ChannelMetadata, CommunityGenesis, CommunityMetadata, ControlFold, ROOT_EPOCH,
};
use crate::derive::control_signer_group_key;
use crate::edition::{ParsedEdition, vsk};
use crate::edition::{EntityHead, Floors, ParsedEdition, vsk};
use crate::stream::OpenedStream;
use crate::{ChannelId, CommunityId, Epoch};
@@ -45,7 +47,6 @@ pub async fn cache_rumor(
Ok(())
}
/// Read a channel's cached rumors.
pub async fn query_rumors(
database: &dyn NostrDatabase,
channel: &ChannelId,
@@ -89,14 +90,6 @@ pub async fn query_rumors(
Ok(rumors)
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EntityHead {
pub entity: [u8; 32],
pub version: u64,
pub self_hash: [u8; 32],
pub rumor_id: EventId,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ChannelKeyRef {
pub id: ChannelId,
@@ -194,6 +187,49 @@ impl CommunityState {
pub fn identifier(&self) -> String {
state_identifier(&self.id)
}
pub fn floors(&self) -> Floors {
self.heads
.iter()
.map(|head| (head.entity, head.clone()))
.collect()
}
pub fn apply_fold(&mut self, fold: &ControlFold) {
self.heads = fold.floors.values().cloned().collect();
if let Some(community) = &fold.community {
self.relays = community
.relays
.iter()
.filter_map(|relay| RelayUrl::parse(relay).ok())
.collect();
}
for (id, metadata) in &fold.channels {
if metadata.deleted.unwrap_or(false) {
self.channels.retain(|channel| channel.id != *id);
continue;
}
match self.channels.iter_mut().find(|channel| channel.id == *id) {
Some(channel) => {
channel.name = metadata.name.clone();
if !metadata.private {
channel.private = false;
}
}
None if !metadata.private => self.channels.push(ChannelKeyRef {
id: *id,
name: metadata.name.clone(),
private: false,
epoch: self.root_epoch,
}),
None => {}
}
}
}
}
fn state_identifier(id: &CommunityId) -> String {