let DAMUS const BOOTSTRAP_RELAYS = [ "wss://nostr.rdfriedl.com", "wss://relay.damus.io", "wss://nostr-relay.wlvs.space", "wss://nostr-pub.wellorder.net" ] // TODO autogenerate these constants with a bash script const IMG_EVENT_LIKED = "icon/event-liked.svg"; const IMG_EVENT_LIKE = "icon/event-like.svg"; async function damus_web_init() { init_message_textareas(); let tries = 0; function init() { // only wait for 500ms max const max_wait = 500; const interval = 20; if (window.nostr || tries >= (max_wait/interval)) { console.info("init after", tries); damus_web_init_ready(); return; } tries++; setTimeout(init, interval); } init(); } async function damus_web_init_ready() { const model = new_model() DAMUS = model model.pubkey = await get_pubkey() if (!model.pubkey) return const {RelayPool} = nostrjs const pool = RelayPool(BOOTSTRAP_RELAYS) const ids = { comments: "comments", profiles: "profiles", explore: "explore", refevents: "refevents", account: "account", home: "home", contacts: "contacts", notifications: "notifications", unknowns: "unknowns", dms: "dms", } let err; err = await contacts_load(model); if (err) { window.alert("Unable to load contacts."); } model.ids = ids model.pool = pool model.view_el = document.querySelector("#view") //load_cache(model) view_timeline_apply_mode(model, VM_FRIENDS); document.addEventListener('visibilitychange', () => { update_title(model) }); on_timer_timestamps(); on_timer_invalidations(); pool.on("open", on_pool_open); pool.on("event", on_pool_event); pool.on("notice", on_pool_notice); pool.on("eose", on_pool_eose); pool.on("ok", on_pool_ok); return pool } function on_timer_timestamps() { setTimeout(() => { view_timeline_update_timestamps(); on_timer_timestamps(); }, 60 * 1000); } function on_timer_invalidations() { setTimeout(() => { if (DAMUS.invalidated.length > 0) view_timeline_update(DAMUS); on_timer_invalidations(); }, 1 * 1000); } /* on_pool_open occurs when a relay is opened. It then subscribes for the * relative REQ as needed. */ function on_pool_open(relay) { log_info(`OPEN(${relay.url})`); const model = DAMUS; relay.subscribe(model.ids.account, filter_new_initial(model.pk)); } function on_pool_notice(relay, notice) { log_info(`NOTICE(${relay.url}): ${notice}`); } // on_pool_eose occurs when all storage from a relay has been sent to the // client for a labeled (sub_id) REQ. async function on_pool_eose(relay, sub_id) { const model = DAMUS; const { ids, pool } = model; switch (sub_id) { case ids.home: const events = model_events_arr(model); // TODO filter out events to friends of friends on_eose_comments(ids, model, events, relay) pool.unsubscribe(ids.home, relay); break; case ids.profiles: model.pool.unsubscribe(ids.profiles, relay); on_eose_profiles(ids, model, relay) break; case ids.unknown: pool.unsubscribe(ids.unknowns, relay); break; case ids.account: model.done_init[relay] = true; pool.unsubscribe(ids.account, relay); model_subscribe_defaults(model, relay); break; } } function on_pool_ok(relay) { console.log(`OK(${relay.url})`, arguments); } function on_pool_event(relay, sub_id, ev) { const model = DAMUS; const { ids, pool } = model; if (new Date(ev.created_at * 1000) > new Date()) { // Simply ignore any events that happened in the future. return; } // Process event and apply side effects if (!model.all_events[ev.id]) { model.all_events[ev.id] = ev; model_process_event(model, ev); } } function on_eose_profiles(ids, model, relay) { const prefix = difficulty_to_prefix(model.pow); const fofs = Array.from(model.contacts.friend_of_friends); let pow_filter = {kinds: STANDARD_KINDS, limit: 50}; if (model.pow > 0) pow_filter.ids = [ prefix ]; let explore_filters = [ pow_filter ]; if (fofs.length > 0) explore_filters.push({kinds: STANDARD_KINDS, authors: fofs, limit: 50}); model.pool.subscribe(ids.explore, explore_filters, relay); } function on_eose_comments(ids, model, events, relay) { const pubkeys = events.reduce((s, ev) => { s.add(ev.pubkey); for (const tag of ev.tags) { if (tag.length >= 2 && tag[0] === "p") { if (!model.profile_events[tag[1]]) s.add(tag[1]); } } return s; }, new Set()); // load profiles and noticed chatrooms const authors = Array.from(pubkeys) const profile_filter = { kinds: [KIND_METADATA, KIND_CONTACT], authors: authors }; let filters = []; if (authors.length > 0) filters.push(profile_filter); if (filters.length === 0) { //log_debug("No profiles filters to request...") return } //console.log("subscribe", profiles_id, filter, relay) //log_debug("subscribing to profiles on %s", relay.url) model.pool.subscribe(ids.profiles, filters, relay) }