iris-chat 0.1.54

Iris Chat command line client and shared encrypted chat core
Documentation
fn filter_has_kind(filters: &[Filter], kind: u32) -> bool {
    filters
        .iter()
        .map(|filter| serde_json::to_value(filter).expect("filter json"))
        .any(|filter| {
            filter
                .get("kinds")
                .and_then(|kinds| kinds.as_array())
                .is_some_and(|kinds| {
                    kinds
                        .iter()
                        .any(|value| value.as_u64() == Some(kind as u64))
                })
        })
}

#[test]
fn device_roster_pending_invite_fetch_skips_message_history() {
    let owner = Keys::generate();
    let device = Keys::generate();
    let message_author = Keys::generate();
    let group_author = Keys::generate();
    let relay = crate::local_relay::TestRelay::start();
    let mut core = logged_in_test_core("device-roster-fetch-metadata-only", &owner, &device);

    let relay_urls = relay_urls_from_strings(&[relay.url().to_string()]);
    core.preferences.nostr_relay_urls = vec![relay.url().to_string()];
    core.logged_in.as_mut().expect("logged in").relay_urls = relay_urls;

    let mut plan = protocol_plan_for_test(
        vec![message_author.public_key()],
        vec![group_author.public_key()],
    );
    plan.roster_authors = vec![owner.public_key().to_hex()];
    core.protocol_subscription_runtime.desired_plan = Some(plan);
    core.debug_log.clear();

    let filters = core.recent_protocol_metadata_filters(UnixSeconds(1_777_159_500));
    assert!(
        !filter_has_kind(&filters, MESSAGE_EVENT_KIND),
        "Devices refresh must not backfill direct messages"
    );
    assert!(
        !filter_has_kind(&filters, GROUP_SENDER_KEY_MESSAGE_KIND),
        "Devices refresh must not backfill group sender-key messages"
    );

    assert!(
        core.fetch_pending_device_invites_for_local_owner(),
        "Devices refresh should still fetch roster/invite metadata"
    );
    assert!(
        core.debug_log.iter().any(|entry| {
            entry.category == "protocol.catch_up.fetch" && entry.detail.contains("messages=false")
        }),
        "Devices refresh must use the metadata-only catch-up path"
    );
}