Skip to main content

iris_chat_protocol/
lib.rs

1mod direct_messages;
2mod protocol_engine;
3mod storage;
4
5use nostr::UnsignedEvent;
6use nostr::{Event, Keys, PublicKey};
7#[cfg(test)]
8use nostr::{Kind, Timestamp};
9use nostr_double_ratchet::{
10    group_sender_key_message_event, invite_response_event, is_group_roster_fact_event,
11    parse_group_roster_fact_event, parse_group_sender_key_message_event,
12    parse_group_sender_key_message_event_unchecked, project_group_roster_fact_events,
13    GroupEventManager, JsonGroupPayloadCodecV1,
14};
15use nostr_double_ratchet::{
16    AuthorizedDevice, Delivery, DevicePubkey as NdrDevicePubkey, DeviceRecordSnapshot,
17    DeviceRoster, DomainError, Error as NdrError, GroupIncomingEvent, GroupManagerSnapshot,
18    GroupPairwiseCommand, GroupPayloadCodec, GroupPendingFanout, GroupPreparedPublish,
19    GroupPreparedSend, GroupProtocol, GroupSenderKeyHandleResult, GroupSenderKeyMessage,
20    GroupSnapshot, MessageEnvelope, OwnerPubkey as NdrOwnerPubkey, PreparedSend, ProtocolContext,
21    SenderKeyRepairRequest, SessionManager, UserRecordSnapshot,
22};
23use nostr_double_ratchet_pairwise_codec as pairwise_codec;
24use rand::rngs::OsRng;
25use serde::{Deserialize, Serialize};
26use std::collections::{BTreeMap, BTreeSet, HashSet};
27use std::sync::{Arc, Mutex};
28use std::time::{SystemTime, UNIX_EPOCH};
29
30pub use direct_messages::{
31    DirectChatSnapshot, DirectInviteAcceptanceOutcome, DirectMessageCommand, DirectMessageDelivery,
32    DirectMessageService, DirectMessageSnapshot, DirectThreadSnapshot,
33};
34pub use nostr_double_ratchet::{
35    build_group_roster_fact_filter, build_protocol_discovery_filters, group_roster_unsigned_event,
36    invite_unsigned_event, invite_url, is_app_keys_event, parse_invite_event,
37    parse_invite_response_event, parse_invite_url, parse_message_event, AppKeys, DeviceEntry,
38    GroupRosterFact, APP_KEYS_EVENT_KIND, CHAT_MESSAGE_KIND, CHAT_SETTINGS_KIND,
39    GROUP_ROSTER_FACT_KIND, GROUP_ROSTER_FACT_SCHEMA, GROUP_ROSTER_FACT_TYPE,
40    GROUP_SENDER_KEY_MESSAGE_KIND, INVITE_EVENT_KIND, INVITE_LIST_LABEL, INVITE_RESPONSE_KIND,
41    MESSAGE_EVENT_KIND, REACTION_KIND, RECEIPT_KIND,
42};
43pub use nostr_double_ratchet::{
44    Invite, SessionManagerSnapshot, SessionState, UnixSeconds as NdrUnixSeconds,
45};
46pub use protocol_engine::*;
47pub use storage::{
48    DebouncedFileStorage, FileStorageAdapter, InMemoryStorage, SqliteStorageAdapter,
49    StorageAdapter, StorageError, StorageResult,
50};
51
52const GROUP_ROSTER_FACT_EVENT_HISTORY_LIMIT: usize = 256;
53pub const PROTOCOL_SENDER_KEY_REPAIR_RETRY_DELAYS_SECS: [u64; 5] = [10, 30, 60, 60, 60];
54
55fn protocol_sender_key_repair_retry_delay_secs(sent_request_count: u32) -> u64 {
56    let index = sent_request_count
57        .saturating_sub(1)
58        .min((PROTOCOL_SENDER_KEY_REPAIR_RETRY_DELAYS_SECS.len() - 1) as u32)
59        as usize;
60    PROTOCOL_SENDER_KEY_REPAIR_RETRY_DELAYS_SECS[index]
61}
62
63fn protocol_sender_key_repair_next_retry_at(
64    now: NdrUnixSeconds,
65    sent_request_count: u32,
66) -> NdrUnixSeconds {
67    NdrUnixSeconds(
68        now.get()
69            .saturating_add(protocol_sender_key_repair_retry_delay_secs(
70                sent_request_count,
71            )),
72    )
73}
74
75pub type SharedConnection = Arc<Mutex<rusqlite::Connection>>;
76
77#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
78pub struct UnixSeconds(pub u64);
79
80impl UnixSeconds {
81    pub fn get(self) -> u64 {
82        self.0
83    }
84}
85
86fn unix_now() -> UnixSeconds {
87    UnixSeconds(
88        SystemTime::now()
89            .duration_since(UNIX_EPOCH)
90            .unwrap_or_default()
91            .as_secs(),
92    )
93}