mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Re-work relays again
This commit is contained in:
parent
25511fdde4
commit
12506c015b
18
ROADMAP.md
18
ROADMAP.md
@ -1,13 +1,11 @@
|
||||
# Current
|
||||
|
||||
- [ ] Review 10002 usage https://github.com/nostr-protocol/nips/blob/master/65.md
|
||||
- [ ] Make feeds page customizable. This could potentially use the "lists" NIP
|
||||
- nevent1qqspjcqw2hu5gfcpkrjhs0aqvxuzjgtp50l375mcqjfpmk48cg5hevgpr3mhxue69uhkummnw3ez6un9d3shjtnhd3m8xtnnwpskxegpzamhxue69uhkummnw3ezuendwsh8w6t69e3xj7spramhxue69uhkummnw3ez6un9d3shjtnwdahxxefwv93kzer9d4usz9rhwden5te0wfjkccte9ejxzmt4wvhxjmcpr9mhxue69uhkummnw3ezuer9d3hjuum0ve68wctjv5n8hwfg
|
||||
- [ ] Click through on relays page to view a feed for only that relay.
|
||||
- [ ] Custom views should combine pubkeys, relays, event ids, and topics
|
||||
|
||||
- [ ] Remove relays from people, pull from routes only
|
||||
- [ ] Fix anon/new user experience
|
||||
- [ ] Clicking stuff that would publish kicks you to the login page, we should open a modal instead.
|
||||
- [ ] Separate user info and relays so we can still select/figure out relays for anons
|
||||
- [ ] Separate petnames out as well so anons can follow people
|
||||
- [ ] Initial user load doesn't have any relays, cache user or wait for people db to be loaded
|
||||
- [ ] Fix bugs on bugsnag
|
||||
|
||||
@ -26,14 +24,21 @@
|
||||
- nevent1qqsyyxtrhpsqeqaqgucd6uzpyh8eq2hkfgr0yzr7ku7tgyl5cn9jw5qpz3mhxue69uhhyetvv9ujumn0wd68ytnzvuq3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7l564wx
|
||||
- [ ] Search by nip05 alias
|
||||
- nevent1qqsdt4ux9c0zvd6hzpwnzznjsmd7a337mpxdspu9wd4fq8drvqejdmqpz3mhxue69uhhyetvv9ujuerpd46hxtnfduqs6amnwvaz7tmwdaejumr0dsffemjp
|
||||
- [ ] Show options on note detail for retrieving replies
|
||||
- Replies from user's network
|
||||
- All replies from author's + user's read relays, including spam
|
||||
|
||||
# Missions
|
||||
|
||||
- [ ] Are write relays the only ones that matter? User read relays only matter for global feed, or where there's no relay hints available. But if relays are navigable, this is unnecessary.
|
||||
- [ ] Make feeds page customizable. This could potentially use the "lists" NIP
|
||||
- nevent1qqspjcqw2hu5gfcpkrjhs0aqvxuzjgtp50l375mcqjfpmk48cg5hevgpr3mhxue69uhkummnw3ez6un9d3shjtnhd3m8xtnnwpskxegpzamhxue69uhkummnw3ezuendwsh8w6t69e3xj7spramhxue69uhkummnw3ez6un9d3shjtnwdahxxefwv93kzer9d4usz9rhwden5te0wfjkccte9ejxzmt4wvhxjmcpr9mhxue69uhkummnw3ezuer9d3hjuum0ve68wctjv5n8hwfg
|
||||
- [ ] Click through on relays page to view a feed for only that relay.
|
||||
- [ ] Custom views should combine pubkeys, relays, event ids, and topics
|
||||
- [ ] Topics/hashtag views
|
||||
- [ ] Support paid relays
|
||||
- atlas.nostr.land
|
||||
- eden.nostr.land
|
||||
- [ ] Re-license using https://polyformproject.org/
|
||||
- [ ] Image uploads
|
||||
- Default will charge via lightning and have a tos, others can self-host and skip that.
|
||||
- Add banner field to profile
|
||||
@ -55,6 +60,7 @@
|
||||
|
||||
# Maintenance
|
||||
|
||||
- [ ] Keep track of all relays an event was seen on
|
||||
- [ ] Don't waste space caching rooms, load those lazily
|
||||
- [ ] Normalize relay urls (lowercase, strip trailing slash)
|
||||
- [ ] Use nip 56 for reporting
|
||||
|
@ -13,7 +13,8 @@
|
||||
import {displayPerson, isLike} from 'src/util/nostr'
|
||||
import {timedelta, shuffle, now, sleep} from 'src/util/misc'
|
||||
import cmd from 'src/agent/cmd'
|
||||
import {user, getUserRelays} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getUserRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import keys from 'src/agent/keys'
|
||||
import network from 'src/agent/network'
|
||||
@ -100,7 +101,7 @@
|
||||
|
||||
const alertSlowConnections = () => {
|
||||
// Only notify about relays the user is actually subscribed to
|
||||
const relayUrls = pluck('url', getUserRelays('read'))
|
||||
const relayUrls = pluck('url', getUserRelays())
|
||||
|
||||
// Prune connections we haven't used in a while
|
||||
pool.getConnections()
|
||||
|
@ -4,7 +4,7 @@ import {get} from 'svelte/store'
|
||||
import {first} from "hurdak/lib/hurdak"
|
||||
import {log} from 'src/util/logger'
|
||||
import {roomAttrs, displayPerson} from 'src/util/nostr'
|
||||
import {getBestRelay} from 'src/agent/helpers'
|
||||
import {getPubkeyWriteRelays, getRelayForPersonHint} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
import keys from 'src/agent/keys'
|
||||
@ -36,7 +36,7 @@ const createDirectMessage = (relays, pubkey, content) =>
|
||||
const createNote = (relays, content, mentions = [], topics = []) => {
|
||||
mentions = mentions.map(pubkey => {
|
||||
const name = displayPerson(database.getPersonWithFallback(pubkey))
|
||||
const {url} = getBestRelay(pubkey, 'write')
|
||||
const [{url}] = getPubkeyWriteRelays(pubkey)
|
||||
|
||||
return ["p", pubkey, url, name]
|
||||
})
|
||||
@ -47,7 +47,7 @@ const createNote = (relays, content, mentions = [], topics = []) => {
|
||||
}
|
||||
|
||||
const createReaction = (relays, note, content) => {
|
||||
const {url} = getBestRelay(note.pubkey, 'write')
|
||||
const {url} = getRelayForPersonHint(note.pubkey, note)
|
||||
const tags = uniqBy(
|
||||
join(':'),
|
||||
note.tags
|
||||
@ -60,10 +60,14 @@ const createReaction = (relays, note, content) => {
|
||||
}
|
||||
|
||||
const createReply = (relays, note, content, mentions = [], topics = []) => {
|
||||
mentions = mentions.map(pubkey => ["p", pubkey, prop('url', getBestRelay(pubkey))])
|
||||
topics = topics.map(t => ["t", t])
|
||||
mentions = mentions.map(pubkey => {
|
||||
const [{url}] = getRelayForPersonHint(pubkey, note)
|
||||
|
||||
const {url} = getBestRelay(note.pubkey, 'write')
|
||||
return ["p", pubkey, url]
|
||||
})
|
||||
|
||||
const [{url}] = getRelayForPersonHint(note.pubkey, note)
|
||||
const tags = uniqBy(
|
||||
join(':'),
|
||||
note.tags
|
||||
|
@ -1,11 +1,9 @@
|
||||
import type {Person, MyEvent} from 'src/util/types'
|
||||
import type {Person} from 'src/util/types'
|
||||
import type {Readable} from 'svelte/store'
|
||||
import {isEmpty, pick, identity, sortBy, uniq, reject, groupBy, last, propEq, uniqBy, prop} from 'ramda'
|
||||
import {first, ensurePlural} from 'hurdak/lib/hurdak'
|
||||
import {uniq, last} from 'ramda'
|
||||
import {derived, get} from 'svelte/store'
|
||||
import {Tags} from 'src/util/nostr'
|
||||
import {now, timedelta} from 'src/util/misc'
|
||||
import defaults from 'src/agent/defaults'
|
||||
import database from 'src/agent/database'
|
||||
import keys from 'src/agent/keys'
|
||||
|
||||
@ -33,50 +31,10 @@ export const getMuffle = () => {
|
||||
}
|
||||
|
||||
export const getFollows = pubkey =>
|
||||
database.getPersonWithFallback(pubkey).petnames || defaults.petnames
|
||||
Tags.wrap(database.getPersonWithFallback(pubkey).petnames).type("p").values().all()
|
||||
|
||||
export const getPersonRelays = (person, mode = 'all') => {
|
||||
const relays = isEmpty(person?.relays || []) ? defaults.relays : person.relays
|
||||
|
||||
return reject(propEq(mode, '!'), relays)
|
||||
}
|
||||
|
||||
export const getUserRelays = (mode = 'all') =>
|
||||
getPersonRelays(get(user), mode)
|
||||
|
||||
export const getPubkeyRelays = (pubkey, mode = 'all') =>
|
||||
getPersonRelays(database.people.get(pubkey), mode)
|
||||
|
||||
export const getTopRelays = (pubkeys, mode = 'all') => {
|
||||
const routes = database.routes.all({mode, pubkey: pubkeys})
|
||||
const routesByPubkey = groupBy(prop('pubkey'), routes)
|
||||
const selectRoute = k => first(sortBy(prop('score'), routesByPubkey[k] || []))
|
||||
|
||||
return uniqBy(prop('url'), pubkeys.map(selectRoute).filter(identity)).map(pick(['url']))
|
||||
}
|
||||
|
||||
export const getBestRelay = (pubkey, mode = 'all') =>
|
||||
first(getTopRelays([pubkey], mode).concat(getPubkeyRelays(pubkey, mode)))
|
||||
|
||||
export const getAllEventRelays = events => {
|
||||
return uniqBy(
|
||||
prop('url'),
|
||||
ensurePlural(events)
|
||||
.flatMap(event =>
|
||||
getPubkeyRelays(event.pubkey, 'write')
|
||||
.concat(Tags.from(event).relays())
|
||||
.concat({url: event.seen_on})
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export const getTopEventRelays = (events: Array<MyEvent>, mode = 'all') =>
|
||||
uniqBy(
|
||||
prop('url'),
|
||||
ensurePlural(events)
|
||||
.flatMap(e => [getBestRelay(e.pubkey, mode), {url: e.seen_on}])
|
||||
.filter(identity)
|
||||
)
|
||||
export const getNetwork = pubkey =>
|
||||
uniq(getFollows(pubkey).flatMap(getFollows))
|
||||
|
||||
export const getStalePubkeys = pubkeys => {
|
||||
// If we're not reloading, only get pubkeys we don't already know about
|
||||
|
@ -1,8 +1,12 @@
|
||||
import {uniq, uniqBy, prop, map, propEq, indexBy, pluck} from 'ramda'
|
||||
import {findReply, personKinds, findReplyId, Tags} from 'src/util/nostr'
|
||||
import {personKinds, findReplyId} from 'src/util/nostr'
|
||||
import {chunk} from 'hurdak/lib/hurdak'
|
||||
import {batch} from 'src/util/misc'
|
||||
import {getStalePubkeys, getTopEventRelays} from 'src/agent/helpers'
|
||||
import {getStalePubkeys} from 'src/agent/helpers'
|
||||
import {
|
||||
getRelaysForEventParent, getAllPubkeyWriteRelays, aggregateScores,
|
||||
getUserNetworkWriteRelays,
|
||||
} from 'src/agent/relays'
|
||||
import pool from 'src/agent/pool'
|
||||
import keys from 'src/agent/keys'
|
||||
import sync from 'src/agent/sync'
|
||||
@ -57,7 +61,7 @@ const listenUntilEose = (relays, filter, onEvents, {shouldProcess = true}: any =
|
||||
}) as Promise<void>
|
||||
}
|
||||
|
||||
const loadPeople = (relays, pubkeys, {kinds = personKinds, force = false, ...opts} = {}) => {
|
||||
const loadPeople = (pubkeys, {kinds = personKinds, force = false, ...opts} = {}) => {
|
||||
pubkeys = uniq(pubkeys)
|
||||
|
||||
// If we're not reloading, only get pubkeys we don't already know about
|
||||
@ -65,25 +69,27 @@ const loadPeople = (relays, pubkeys, {kinds = personKinds, force = false, ...opt
|
||||
pubkeys = getStalePubkeys(pubkeys)
|
||||
}
|
||||
|
||||
return pubkeys.length > 0
|
||||
? load(relays, {kinds, authors: pubkeys}, opts)
|
||||
: Promise.resolve([])
|
||||
}
|
||||
|
||||
const loadParents = (relays, notes) => {
|
||||
const parentIds = new Set(Tags.wrap(notes.map(findReply)).values().all())
|
||||
|
||||
if (parentIds.size === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
return load(
|
||||
relays.concat(getTopEventRelays(notes, 'read')),
|
||||
{kinds: [1], ids: Array.from(parentIds)}
|
||||
getAllPubkeyWriteRelays(pubkeys).slice(0, 10),
|
||||
{kinds, authors: pubkeys},
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
const streamContext = ({relays, notes, updateNotes, depth = 0}) => {
|
||||
const loadParents = notes => {
|
||||
const notesWithParent = notes.filter(findReplyId)
|
||||
const relays = aggregateScores(notesWithParent.map(getRelaysForEventParent))
|
||||
|
||||
return load(relays, {kinds: [1], ids: notesWithParent.map(findReplyId)})
|
||||
}
|
||||
|
||||
const streamContext = ({notes, updateNotes, depth = 0}) => {
|
||||
// We could also use getRelaysForEventChildren for a more complete view of replies,
|
||||
// but it's also more likely to include spam. Checking our user's social graph
|
||||
// avoids this problem. TODO: review this, maybe add note authors's graphs to this
|
||||
// as well.
|
||||
const relays = getUserNetworkWriteRelays()
|
||||
|
||||
// Some relays reject very large filters, send multiple
|
||||
chunk(256, notes).forEach(chunk => {
|
||||
const authors = getStalePubkeys(pluck('pubkey', chunk))
|
||||
@ -99,7 +105,7 @@ const streamContext = ({relays, notes, updateNotes, depth = 0}) => {
|
||||
|
||||
// Recur if we need to
|
||||
if (depth > 0) {
|
||||
streamContext({relays, notes: events, updateNotes, depth: depth - 1})
|
||||
streamContext({notes: events, updateNotes, depth: depth - 1})
|
||||
}
|
||||
|
||||
const annotate = ({replies = [], reactions = [], children = [], ...note}) => {
|
||||
|
152
src/agent/relays.ts
Normal file
152
src/agent/relays.ts
Normal file
@ -0,0 +1,152 @@
|
||||
import {get} from 'svelte/store'
|
||||
import {sortBy, uniq, uniqBy, prop, pluck} from 'ramda'
|
||||
import {createMapOf, first} from 'hurdak/lib/hurdak'
|
||||
import {Tags} from 'src/util/nostr'
|
||||
import {getFollows} from 'src/agent/helpers'
|
||||
import database from 'src/agent/database'
|
||||
import keys from 'src/agent/keys'
|
||||
|
||||
// From Mike Dilger:
|
||||
// 1) Other people's write relays — pull events from people you follow,
|
||||
// including their contact lists
|
||||
// 2) Other people's read relays — push events that tag them (replies or just tagging).
|
||||
// However, these may be authenticated, use with caution
|
||||
// 3) Your write relays —- write events you post to your microblog feed for the
|
||||
// world to see. ALSO write your contact list. ALSO read back your own contact list.
|
||||
// 4) Your read relays —- read events that tag you. ALSO both write and read
|
||||
// client-private data like client configuration events or anything that the world
|
||||
// doesn't need to see.
|
||||
// 5) Advertise relays — write and read back your own relay list
|
||||
|
||||
|
||||
// Pubkey relays
|
||||
|
||||
export const getPubkeyRelays = pubkey => {
|
||||
const person = database.getPersonWithFallback(pubkey)
|
||||
|
||||
return scoreRelays(pubkey, person.relays || [])
|
||||
}
|
||||
|
||||
export const getPubkeyReadRelays = pubkey =>
|
||||
getPubkeyRelays(pubkey).filter(r => r.read !== '!')
|
||||
|
||||
export const getPubkeyWriteRelays = pubkey =>
|
||||
getPubkeyRelays(pubkey).filter(r => r.write !== '!')
|
||||
|
||||
// Multiple pubkeys
|
||||
|
||||
export const getAllPubkeyRelays = pubkeys =>
|
||||
aggregateScores(pubkeys.map(getPubkeyRelays))
|
||||
|
||||
export const getAllPubkeyReadRelays = pubkeys =>
|
||||
aggregateScores(pubkeys.map(getPubkeyReadRelays))
|
||||
|
||||
export const getAllPubkeyWriteRelays = pubkeys =>
|
||||
aggregateScores(pubkeys.map(getPubkeyWriteRelays))
|
||||
|
||||
// Current user
|
||||
|
||||
export const getUserRelays = () => getPubkeyRelays(get(keys.pubkey))
|
||||
export const getUserReadRelays = () => getPubkeyReadRelays(get(keys.pubkey))
|
||||
export const getUserWriteRelays = () => getPubkeyWriteRelays(get(keys.pubkey))
|
||||
|
||||
// Network relays
|
||||
|
||||
export const getNetworkWriteRelays = pubkey => {
|
||||
const follows = Tags.wrap(getFollows(pubkey)).values().all()
|
||||
const others = Tags.wrap(follows.flatMap(getFollows)).values().all()
|
||||
|
||||
return getAllPubkeyWriteRelays(uniq(follows.concat(others)))
|
||||
}
|
||||
|
||||
// User's network relays
|
||||
|
||||
export const getUserNetworkWriteRelays = () => getNetworkWriteRelays(get(keys.pubkey))
|
||||
|
||||
// Event-related special cases
|
||||
|
||||
// If we're looking for an event's parent, tags are the most reliable hint,
|
||||
// but we can also look at where other people in the thread write to.
|
||||
export const getRelaysForEventParent = event => {
|
||||
const tags = Tags.from(event)
|
||||
const relays = tags.relays()
|
||||
const pubkeys = tags.type("p").values().all()
|
||||
const pubkeyRelays = pubkeys.flatMap(getPubkeyWriteRelays)
|
||||
|
||||
return uniqByUrl(relays.concat(pubkeyRelays).concat(event.seen_on))
|
||||
}
|
||||
|
||||
// If we're looking for an event's children, the read relays the author has
|
||||
// advertised would be the most reliable option, since well-behaved clients
|
||||
// will write replies there. However, this may include spam, so we may want
|
||||
// to read from the current user's network's read relays instead.
|
||||
export const getRelaysForEventChildren = event => {
|
||||
return uniqByUrl(getPubkeyReadRelays(event.pubkey).concat(event.seen_on))
|
||||
}
|
||||
|
||||
export const getRelayForEventHint = event => event.seen_on
|
||||
|
||||
export const getRelayForPersonHint = (pubkey, event) =>
|
||||
first(getPubkeyWriteRelays(pubkey)) || getRelayForEventHint(event)
|
||||
|
||||
// If we're replying or reacting to an event, we want the author to know,
|
||||
// as well as anyone else who is tagged in the original event or the reply.
|
||||
// Get everyone's read relays. We also want to advertise our content to
|
||||
// our followers, so write to our write relays as well.
|
||||
export const getEventPublishRelays = event => {
|
||||
const tags = Tags.from(event)
|
||||
const pubkeys = tags.type("p").values().all()
|
||||
|
||||
return uniqByUrl(
|
||||
pubkeys
|
||||
.concat(event.pubkey)
|
||||
.concat(get(keys.pubkey))
|
||||
.flatMap(getPubkeyReadRelays)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Utils
|
||||
|
||||
const uniqByUrl = uniqBy(prop('url'))
|
||||
const sortByScore = sortBy(r => -r.score)
|
||||
|
||||
const scoreRelays = (pubkey, relays) => {
|
||||
const routes = database.routes.all({pubkey, url: pluck('url', relays)})
|
||||
const scores = createMapOf('url', 'score', routes)
|
||||
|
||||
return uniqByUrl(sortByScore(relays.map(r => ({...r, score: scores[r.url] || 0}))))
|
||||
}
|
||||
|
||||
export const aggregateScores = relayGroups => {
|
||||
const scores = {} as Record<string, {
|
||||
score: number,
|
||||
count: number,
|
||||
weight?: number,
|
||||
weightedScore?: number
|
||||
}>
|
||||
|
||||
for (const relays of relayGroups) {
|
||||
for (const relay of relays) {
|
||||
const {url, score} = relay
|
||||
|
||||
if (!scores[url]) {
|
||||
scores[url] = {score: 0, count: 0}
|
||||
}
|
||||
|
||||
scores[url].score += score
|
||||
scores[url].count += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Use the log-sum-exp and a weighted sum
|
||||
for (const score of Object.values(scores)) {
|
||||
score.weight = Math.log(relayGroups.length / score.count)
|
||||
score.weightedScore = score.weight + Math.log1p(Math.exp(score.score - score.count))
|
||||
}
|
||||
|
||||
return sortByScore(
|
||||
Object.entries(scores)
|
||||
.map(([url, {weightedScore}]) => ({url, score: weightedScore}))
|
||||
)
|
||||
}
|
@ -5,6 +5,7 @@ import {synced, timedelta, now} from 'src/util/misc'
|
||||
import {isAlert, findReplyId} from 'src/util/nostr'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
import {getUserReadRelays} from 'src/agent/relays'
|
||||
import {asDisplayEvent, mergeParents} from 'src/app'
|
||||
|
||||
let listener
|
||||
@ -12,11 +13,11 @@ let listener
|
||||
const mostRecentAlert = synced("app/alerts/mostRecentAlert", 0)
|
||||
const lastCheckedAlerts = synced("app/alerts/lastCheckedAlerts", 0)
|
||||
|
||||
const onChunk = async (relays, pubkey, events) => {
|
||||
const onChunk = async (pubkey, events) => {
|
||||
events = events.filter(e => isAlert(e, pubkey))
|
||||
|
||||
if (events.length > 0) {
|
||||
const parents = await network.loadParents(relays, events)
|
||||
const parents = await network.loadParents(events)
|
||||
const [likes, notes] = partition(propEq('kind', 7), events)
|
||||
const annotatedNotes = mergeParents(notes.concat(parents).map(asDisplayEvent))
|
||||
const likesByParent = groupBy(findReplyId, likes)
|
||||
@ -30,31 +31,29 @@ const onChunk = async (relays, pubkey, events) => {
|
||||
}
|
||||
}
|
||||
|
||||
const load = async (relays, pubkey) => {
|
||||
const load = async pubkey => {
|
||||
// Include an offset so we don't miss alerts on one relay but not another
|
||||
const since = get(mostRecentAlert) - timedelta(30, 'days')
|
||||
|
||||
// Crank the threshold up since we can afford for this to be slow
|
||||
const events = await network.load(
|
||||
relays,
|
||||
getUserReadRelays(),
|
||||
{kinds: [1, 7], '#p': [pubkey], since, limit: 1000},
|
||||
{threshold: 0.9}
|
||||
)
|
||||
|
||||
onChunk(relays, pubkey, events)
|
||||
onChunk(pubkey, events)
|
||||
}
|
||||
|
||||
const listen = async (relays, pubkey) => {
|
||||
const listen = async pubkey => {
|
||||
if (listener) {
|
||||
listener.unsub()
|
||||
}
|
||||
|
||||
listener = await network.listen(
|
||||
relays,
|
||||
getUserReadRelays(),
|
||||
{kinds: [1, 7], '#p': [pubkey], since: now()},
|
||||
events => {
|
||||
onChunk(relays, pubkey, events)
|
||||
}
|
||||
events => onChunk(pubkey, events)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ import {createMap, ellipsize} from 'hurdak/lib/hurdak'
|
||||
import {get} from 'svelte/store'
|
||||
import {renderContent} from 'src/util/html'
|
||||
import {Tags, displayPerson, findReplyId} from 'src/util/nostr'
|
||||
import {user, getUserRelays, getFollows} from 'src/agent/helpers'
|
||||
import {user, getNetwork} from 'src/agent/helpers'
|
||||
import {getUserWriteRelays} from 'src/agent/relays'
|
||||
import defaults from 'src/agent/defaults'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
@ -17,17 +18,13 @@ import {toast, routes, modal, settings, logUsage} from 'src/app/ui'
|
||||
|
||||
export {toast, modal, settings, alerts, messages, logUsage}
|
||||
|
||||
export const loadAppData = pubkey => {
|
||||
const relays = getUserRelays('read')
|
||||
const follows = Tags.wrap(getFollows(pubkey))
|
||||
|
||||
return Promise.all([
|
||||
alerts.load(relays, pubkey),
|
||||
alerts.listen(relays, pubkey),
|
||||
messages.listen(relays, pubkey),
|
||||
network.loadPeople(follows.relays(), follows.values().all()),
|
||||
export const loadAppData = pubkey =>
|
||||
Promise.all([
|
||||
alerts.load(pubkey),
|
||||
alerts.listen(pubkey),
|
||||
messages.listen(pubkey),
|
||||
network.loadPeople(getNetwork(pubkey)),
|
||||
])
|
||||
}
|
||||
|
||||
export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: string}) => {
|
||||
if (privkey) {
|
||||
@ -38,12 +35,12 @@ export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: strin
|
||||
|
||||
modal.set({type: 'message', message: "Loading your profile data...", spinner: true})
|
||||
|
||||
// Load our user so we can populate network and show profile info
|
||||
await network.loadPeople([pubkey])
|
||||
|
||||
// Load network and start listening, but don't wait for it
|
||||
loadAppData(pubkey)
|
||||
|
||||
// Load our user so we can populate network and show profile info
|
||||
await network.loadPeople(getUserRelays('read'), [pubkey])
|
||||
|
||||
// Not ideal, but the network tab depends on the user's social network being
|
||||
// loaded, so put them on global when they first log in so we're not slowing
|
||||
// down users' first run experience too much
|
||||
@ -76,7 +73,7 @@ export const removeRelay = async url => {
|
||||
defaults.relays = modify(defaults.relays)
|
||||
|
||||
if (person) {
|
||||
await cmd.setRelays(getUserRelays('write'), modify(person.relays || []))
|
||||
await cmd.setRelays(getUserWriteRelays(), modify(person.relays || []))
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +85,7 @@ export const setRelayWriteCondition = async (url, write) => {
|
||||
defaults.relays = modify(defaults.relays)
|
||||
|
||||
if (person) {
|
||||
await cmd.setRelays(getUserRelays('write'), modify(person.relays || []))
|
||||
await cmd.setRelays(getUserWriteRelays(), modify(person.relays || []))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import {pluck, reject} from 'ramda'
|
||||
import {get} from 'svelte/store'
|
||||
import {synced, now, timedelta} from 'src/util/misc'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getUserReadRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
|
||||
@ -11,13 +12,13 @@ const since = now() - timedelta(30, 'days')
|
||||
const mostRecentByPubkey = synced('app/messages/mostRecentByPubkey', {})
|
||||
const lastCheckedByPubkey = synced('app/messages/lastCheckedByPubkey', {})
|
||||
|
||||
const listen = async (relays, pubkey) => {
|
||||
const listen = async pubkey => {
|
||||
if (listener) {
|
||||
listener.unsub()
|
||||
}
|
||||
|
||||
listener = await network.listen(
|
||||
relays,
|
||||
getUserReadRelays(),
|
||||
[{kinds: [4], authors: [pubkey], since},
|
||||
{kinds: [4], '#p': [pubkey], since}],
|
||||
async events => {
|
||||
@ -27,7 +28,7 @@ const listen = async (relays, pubkey) => {
|
||||
const messages = reject(e => e.pubkey === e.recipient, await database.messages.all())
|
||||
|
||||
if (messages.length > 0) {
|
||||
await network.loadPeople(relays, pluck('pubkey', messages))
|
||||
await network.loadPeople(pluck('pubkey', messages))
|
||||
|
||||
mostRecentByPubkey.update(o => {
|
||||
for (const {pubkey, created_at} of messages) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
import {slide} from 'svelte/transition'
|
||||
import {navigate} from 'svelte-routing'
|
||||
import {quantify} from 'hurdak/lib/hurdak'
|
||||
import {Tags, findReply, findRoot, findReplyId, displayPerson, isLike} from "src/util/nostr"
|
||||
import {Tags, findReply, findRoot, findRootId, findReplyId, displayPerson, isLike} from "src/util/nostr"
|
||||
import {extractUrls} from "src/util/html"
|
||||
import ImageCircle from 'src/partials/ImageCircle.svelte'
|
||||
import Preview from 'src/partials/Preview.svelte'
|
||||
@ -16,7 +16,8 @@
|
||||
import {formatTimestamp, stringToColor} from 'src/util/misc'
|
||||
import Compose from "src/partials/Compose.svelte"
|
||||
import Card from "src/partials/Card.svelte"
|
||||
import {user, getTopEventRelays, getAllEventRelays} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getEventPublishRelays, getRelaysForEventParent} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import cmd from 'src/agent/cmd'
|
||||
import {routes} from 'src/app/ui'
|
||||
@ -62,22 +63,20 @@
|
||||
const target = e.target as HTMLElement
|
||||
|
||||
if (interactive && !['I'].includes(target.tagName) && !target.closest('a')) {
|
||||
modal.set({type: 'note/detail', note, relays: getTopEventRelays(note)})
|
||||
modal.set({type: 'note/detail', note})
|
||||
}
|
||||
}
|
||||
|
||||
const goToParent = async () => {
|
||||
const [id, url] = findReply(note).slice(1)
|
||||
const relays = getTopEventRelays(note).concat({url})
|
||||
const relays = getRelaysForEventParent(note)
|
||||
|
||||
modal.set({type: 'note/detail', note: {id}, relays})
|
||||
modal.set({type: 'note/detail', note: {id: findReplyId(note)}, relays})
|
||||
}
|
||||
|
||||
const goToRoot = async () => {
|
||||
const [id, url] = findRoot(note).slice(1)
|
||||
const relays = getTopEventRelays(note).concat({url})
|
||||
const relays = getRelaysForEventParent(note)
|
||||
|
||||
modal.set({type: 'note/detail', note: {id}, relays})
|
||||
modal.set({type: 'note/detail', note: {id: findRootId(note)}, relays})
|
||||
}
|
||||
|
||||
const showActiveRelays = () => {
|
||||
@ -89,7 +88,7 @@
|
||||
return navigate('/login')
|
||||
}
|
||||
|
||||
const relays = getTopEventRelays(note)
|
||||
const relays = getEventPublishRelays(note)
|
||||
const [event] = cmd.createReaction(relays, note, content)
|
||||
|
||||
if (content === '+') {
|
||||
@ -102,7 +101,7 @@
|
||||
}
|
||||
|
||||
const deleteReaction = e => {
|
||||
cmd.deleteEvent(getAllEventRelays(note), [e.id])
|
||||
cmd.deleteEvent(getEventPublishRelays(note), [e.id])
|
||||
|
||||
if (e.content === '+') {
|
||||
likes = reject(propEq('pubkey', $user.pubkey), likes)
|
||||
@ -136,7 +135,7 @@
|
||||
if (content) {
|
||||
mentions = uniq(mentions.concat(replyMentions))
|
||||
|
||||
const relays = getTopEventRelays(note)
|
||||
const relays = getEventPublishRelays(note)
|
||||
const [event] = cmd.createReply(relays, note, content, mentions, topics)
|
||||
|
||||
toast.show("info", {
|
||||
@ -218,10 +217,7 @@
|
||||
{/if}
|
||||
</Anchor>
|
||||
<Anchor
|
||||
href={"/" + nip19.neventEncode({
|
||||
id: note.id,
|
||||
relays: pluck('url', getTopEventRelays(note).slice(0, 5)),
|
||||
})}
|
||||
href={"/" + nip19.neventEncode({id: note.id, relays: [note.seen_on.url]})}
|
||||
class="text-sm text-light"
|
||||
type="unstyled">
|
||||
{formatTimestamp(note.created_at)}
|
||||
|
@ -32,13 +32,12 @@
|
||||
prop('id'),
|
||||
newNotes
|
||||
.filter(propEq('kind', 1))
|
||||
.concat(await network.loadParents(relays, newNotes))
|
||||
.concat(await network.loadParents(newNotes))
|
||||
.map(mergeRight({replies: [], reactions: [], children: []}))
|
||||
)
|
||||
|
||||
// Stream in additional data
|
||||
network.streamContext({
|
||||
relays,
|
||||
notes: combined,
|
||||
updateNotes: cb => {
|
||||
notes = cb(notes)
|
||||
|
@ -5,7 +5,7 @@
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import NoteDetail from 'src/views/NoteDetail.svelte'
|
||||
import Person from 'src/routes/Person.svelte'
|
||||
import {getUserRelays} from 'src/agent/helpers'
|
||||
import {getUserReadRelays} from 'src/agent/relays'
|
||||
|
||||
export let entity
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
onMount(() => {
|
||||
try {
|
||||
({type, data} = nip19.decode(entity) as {type: string, data: any})
|
||||
relays = (data.relays || []).map(objOf('url')).concat(getUserRelays())
|
||||
relays = (data.relays || []).map(objOf('url')).concat(getUserReadRelays())
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
|
@ -4,9 +4,10 @@
|
||||
import {nip19} from 'nostr-tools'
|
||||
import {navigate} from "svelte-routing"
|
||||
import {fuzzy} from "src/util/misc"
|
||||
import {getUserRelays, getTopRelays, user} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import network from 'src/agent/network'
|
||||
import database from 'src/agent/database'
|
||||
import {getUserReadRelays} from 'src/agent/relays'
|
||||
import {modal, messages} from 'src/app'
|
||||
import Room from "src/partials/Room.svelte"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
@ -24,7 +25,7 @@
|
||||
const messages = await database.messages.all()
|
||||
const pubkeys = without([$user.pubkey], uniq(messages.flatMap(m => [m.pubkey, m.recipient])))
|
||||
|
||||
await network.loadPeople(getTopRelays(pubkeys, 'write'), pubkeys)
|
||||
await network.loadPeople(pubkeys)
|
||||
|
||||
return sortBy(k => -(mostRecentByPubkey[k] || 0), pubkeys)
|
||||
.map(k => ({type: 'npub', id: k, ...database.getPersonWithFallback(k)}))
|
||||
@ -58,7 +59,7 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const sub = network.listen(getUserRelays('read'), [{kinds: [40, 41]}])
|
||||
const sub = network.listen(getUserReadRelays(), [{kinds: [40, 41]}])
|
||||
|
||||
return () => {
|
||||
sub.then(s => {
|
||||
|
@ -3,7 +3,8 @@
|
||||
import {nip19} from 'nostr-tools'
|
||||
import {now} from 'src/util/misc'
|
||||
import Channel from 'src/partials/Channel.svelte'
|
||||
import {getTopEventRelays, user} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getRelaysForEventChildren} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
import {modal} from 'src/app'
|
||||
@ -15,7 +16,7 @@
|
||||
const room = database.watch('rooms', rooms => rooms.get(roomId))
|
||||
|
||||
const listenForMessages = async cb => {
|
||||
const relays = getTopEventRelays($room)
|
||||
const relays = getRelaysForEventChildren($room)
|
||||
|
||||
return network.listen(
|
||||
relays,
|
||||
@ -33,7 +34,7 @@
|
||||
}
|
||||
|
||||
const loadMessages = async ({until, limit}) => {
|
||||
const relays = getTopEventRelays($room)
|
||||
const relays = getRelaysForEventChildren($room)
|
||||
const events = await network.load(relays, {kinds: [42], '#e': [roomId], until, limit})
|
||||
|
||||
if (events.length) {
|
||||
@ -48,7 +49,7 @@
|
||||
}
|
||||
|
||||
const sendMessage = content =>
|
||||
cmd.createChatMessage(getTopEventRelays($room), roomId, content)
|
||||
cmd.createChatMessage(getRelaysForEventChildren($room), roomId, content)
|
||||
</script>
|
||||
|
||||
<Channel
|
||||
|
@ -4,13 +4,14 @@
|
||||
import {personKinds} from 'src/util/nostr'
|
||||
import {now} from 'src/util/misc'
|
||||
import Channel from 'src/partials/Channel.svelte'
|
||||
import {getUserRelays, getPubkeyRelays, user} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getAllPubkeyRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
import keys from 'src/agent/keys'
|
||||
import {messages} from 'src/app'
|
||||
import {routes} from 'src/app/ui'
|
||||
import cmd from 'src/agent/cmd'
|
||||
import {routes} from 'src/app/ui'
|
||||
import {messages} from 'src/app'
|
||||
|
||||
export let entity
|
||||
|
||||
@ -20,7 +21,7 @@
|
||||
|
||||
messages.lastCheckedByPubkey.update($obj => ({...$obj, [pubkey]: now()}))
|
||||
|
||||
const getRelays = () => getUserRelays('write').concat(getPubkeyRelays(pubkey, 'write'))
|
||||
const getRelays = () => getAllPubkeyRelays([pubkey, $user.pubkey]).slice(0, 3)
|
||||
|
||||
const decryptMessages = async events => {
|
||||
// Gotta do it in serial because of extension limitations
|
||||
|
@ -16,7 +16,8 @@
|
||||
import Notes from "src/views/person/Notes.svelte"
|
||||
import Likes from "src/views/person/Likes.svelte"
|
||||
import Relays from "src/views/person/Relays.svelte"
|
||||
import {getPubkeyRelays, getUserRelays, user} from "src/agent/helpers"
|
||||
import {user} from "src/agent/helpers"
|
||||
import {getPubkeyWriteRelays, getUserWriteRelays} from "src/agent/relays"
|
||||
import network from "src/agent/network"
|
||||
import keys from "src/agent/keys"
|
||||
import database from "src/agent/database"
|
||||
@ -43,10 +44,10 @@
|
||||
log('Person', npub, person)
|
||||
|
||||
// Add all the relays we know the person uses
|
||||
relays = relays.concat(getPubkeyRelays(pubkey))
|
||||
relays = relays.concat(getPubkeyWriteRelays(pubkey))
|
||||
|
||||
// Refresh our person if needed
|
||||
network.loadPeople(relays, [pubkey]).then(() => {
|
||||
network.loadPeople([pubkey]).then(() => {
|
||||
person = database.getPersonWithFallback(pubkey)
|
||||
loading = false
|
||||
})
|
||||
@ -90,13 +91,13 @@
|
||||
const tag = ["p", pubkey, relays[0].url, person.name || ""]
|
||||
const petnames = reject(t => t[1] === pubkey, $user.petnames).concat([tag])
|
||||
|
||||
cmd.setPetnames(getUserRelays('write'), petnames)
|
||||
cmd.setPetnames(getUserWriteRelays(), petnames)
|
||||
}
|
||||
|
||||
const unfollow = async () => {
|
||||
const petnames = reject(t => t[1] === pubkey, $user.petnames)
|
||||
|
||||
cmd.setPetnames(getUserRelays('write'), petnames)
|
||||
cmd.setPetnames(getUserWriteRelays(), petnames)
|
||||
}
|
||||
|
||||
const openAdvanced = () => {
|
||||
|
@ -11,7 +11,8 @@
|
||||
import Button from "src/partials/Button.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import {user, getUserRelays} from "src/agent/helpers"
|
||||
import {user} from "src/agent/helpers"
|
||||
import {getUserWriteRelays} from 'src/agent/relays'
|
||||
import cmd from "src/agent/cmd"
|
||||
import {toast} from "src/app"
|
||||
import {routes} from "src/app/ui"
|
||||
@ -46,7 +47,7 @@
|
||||
const submit = async event => {
|
||||
event.preventDefault()
|
||||
|
||||
cmd.updateUser(getUserRelays('write'), values)
|
||||
cmd.updateUser(getUserWriteRelays(), values)
|
||||
|
||||
navigate(routes.person($user.pubkey, 'profile'))
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Textarea from "src/partials/Textarea.svelte"
|
||||
import Button from "src/partials/Button.svelte"
|
||||
import {getUserRelays} from 'src/agent/helpers'
|
||||
import {getUserWriteRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import cmd from "src/agent/cmd"
|
||||
import {toast, modal} from "src/app"
|
||||
@ -37,8 +37,8 @@
|
||||
toast.show("error", "Please enter a name for your room.")
|
||||
} else {
|
||||
const [event] = room.id
|
||||
? cmd.updateRoom(getUserRelays('write'), room)
|
||||
: cmd.createRoom(getUserRelays('write'), room)
|
||||
? cmd.updateRoom(getUserWriteRelays(), room)
|
||||
: cmd.createRoom(getUserWriteRelays(), room)
|
||||
|
||||
await database.rooms.patch({id: room.id || event.id, joined: true})
|
||||
|
||||
|
@ -13,7 +13,8 @@
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Heading from 'src/partials/Heading.svelte'
|
||||
import {user, getUserRelays} from "src/agent/helpers"
|
||||
import {user} from "src/agent/helpers"
|
||||
import {getUserWriteRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import cmd from "src/agent/cmd"
|
||||
import {toast, modal} from "src/app"
|
||||
@ -21,7 +22,7 @@
|
||||
export let pubkey = null
|
||||
|
||||
let input = null
|
||||
let relays = getUserRelays('write')
|
||||
let relays = getUserWriteRelays()
|
||||
let showSettings = false
|
||||
let q = ''
|
||||
let search
|
||||
|
@ -4,7 +4,6 @@
|
||||
import {fly} from 'svelte/transition'
|
||||
import {first} from 'hurdak/lib/hurdak'
|
||||
import {log} from 'src/util/logger'
|
||||
import {getAllEventRelays} from 'src/agent/helpers'
|
||||
import network from 'src/agent/network'
|
||||
import Note from 'src/partials/Note.svelte'
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
@ -17,8 +16,6 @@
|
||||
let loading = true
|
||||
|
||||
onMount(async () => {
|
||||
relays = relays.concat(getAllEventRelays(note))
|
||||
|
||||
if (!note.pubkey) {
|
||||
note = first(await network.load(relays, {ids: [note.id]}))
|
||||
}
|
||||
@ -27,7 +24,6 @@
|
||||
log('NoteDetail', nip19.noteEncode(note.id), note)
|
||||
|
||||
network.streamContext({
|
||||
relays,
|
||||
depth: 10,
|
||||
notes: [note],
|
||||
updateNotes: cb => {
|
||||
|
@ -1,13 +1,13 @@
|
||||
<script type="ts">
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
||||
import {getUserRelays, getTopRelays} from 'src/agent/helpers'
|
||||
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
|
||||
export let pubkeys
|
||||
|
||||
const relays = getUserRelays('read').concat(getTopRelays(pubkeys, 'write'))
|
||||
const relays = getAllPubkeyWriteRelays(pubkeys)
|
||||
const people = database.watch('people', people => people.all({pubkey: pubkeys}))
|
||||
|
||||
network.loadPeople(relays, pubkeys)
|
||||
|
@ -5,7 +5,8 @@
|
||||
import Button from "src/partials/Button.svelte"
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import SelectButton from "src/partials/SelectButton.svelte"
|
||||
import {user, getUserRelays} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getUserWriteRelays} from 'src/agent/relays'
|
||||
import cmd from 'src/agent/cmd'
|
||||
import {modal} from 'src/app'
|
||||
|
||||
@ -28,7 +29,7 @@
|
||||
.concat([["p", $modal.person.pubkey, muffleValue.toString()]])
|
||||
.filter(t => last(t) !== "1")
|
||||
|
||||
cmd.muffle(getUserRelays('write'), muffleTags)
|
||||
cmd.muffle(getUserWriteRelays(), muffleTags)
|
||||
|
||||
history.back()
|
||||
}
|
||||
|
@ -6,11 +6,11 @@
|
||||
import {onMount} from 'svelte'
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import Input from 'src/partials/Input.svelte'
|
||||
import {getBestRelay} from 'src/agent/helpers'
|
||||
import {getPubkeyWriteRelays} from 'src/agent/relays'
|
||||
import {modal, toast} from 'src/app'
|
||||
|
||||
const {pubkey} = $modal.person
|
||||
const relays = [prop('url', getBestRelay(pubkey))]
|
||||
const relays = [prop('url', getPubkeyWriteRelays(pubkey))]
|
||||
const nprofile = nip19.nprofileEncode({pubkey, relays})
|
||||
|
||||
let canvas
|
||||
|
@ -3,7 +3,8 @@
|
||||
import {personKinds} from "src/util/nostr"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
||||
import {user, getUserRelays} from 'src/agent/helpers'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import {getUserReadRelays} from 'src/agent/relays'
|
||||
import database from 'src/agent/database'
|
||||
import network from 'src/agent/network'
|
||||
|
||||
@ -18,7 +19,7 @@
|
||||
})
|
||||
|
||||
// Prime our database, in case we don't have any people stored yet
|
||||
network.listenUntilEose(getUserRelays(), {kinds: personKinds, limit: 300})
|
||||
network.listenUntilEose(getUserReadRelays(), {kinds: personKinds, limit: 300})
|
||||
</script>
|
||||
|
||||
<Input bind:value={q} placeholder="Search for people">
|
||||
|
@ -1,16 +1,15 @@
|
||||
<script>
|
||||
import {uniq} from 'ramda'
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {shuffle} from 'src/util/misc'
|
||||
import {Tags} from 'src/util/nostr'
|
||||
import {user, getTopRelays, getFollows} from 'src/agent/helpers'
|
||||
import {user, getFollows, getNetwork} from 'src/agent/helpers'
|
||||
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
||||
|
||||
// Get first- and second-order follows. shuffle and slice network so we're not
|
||||
// sending too many pubkeys. This will also result in some variety.
|
||||
const follows = shuffle(Tags.wrap(getFollows($user?.pubkey)).values().all())
|
||||
const others = shuffle(Tags.wrap(follows.flatMap(getFollows)).values().all()).slice(0, 50)
|
||||
const authors = uniq(follows.concat(others)).slice(0, 100)
|
||||
const relays = getTopRelays(authors, 'write')
|
||||
const follows = getFollows($user?.pubkey)
|
||||
const network = getNetwork($user?.pubkey)
|
||||
const authors = uniq(follows.concat(network)).slice(0, 100)
|
||||
const relays = getAllPubkeyWriteRelays(authors)
|
||||
const filter = {kinds: [1, 7], authors}
|
||||
</script>
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
<script>
|
||||
import {uniq} from 'ramda'
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {shuffle} from 'src/util/misc'
|
||||
import {isLike, Tags} from 'src/util/nostr'
|
||||
import {user, getTopRelays, getFollows} from 'src/agent/helpers'
|
||||
import {isLike} from 'src/util/nostr'
|
||||
import {user, getFollows, getNetwork} from 'src/agent/helpers'
|
||||
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
||||
|
||||
// Get first- and second-order follows. shuffle and slice network so we're not
|
||||
// sending too many pubkeys. This will also result in some variety.
|
||||
const follows = shuffle(Tags.wrap(getFollows($user?.pubkey)).values().all())
|
||||
const others = shuffle(Tags.wrap(follows.flatMap(getFollows)).values().all()).slice(0, 50)
|
||||
const authors = uniq(follows.concat(others)).slice(0, 100)
|
||||
const relays = getTopRelays(authors, 'write')
|
||||
const follows = getFollows($user?.pubkey)
|
||||
const network = getNetwork($user?.pubkey)
|
||||
const authors = uniq(follows.concat(network)).slice(0, 100)
|
||||
const relays = getAllPubkeyWriteRelays(authors)
|
||||
const filter = {kinds: [1, 7], authors}
|
||||
|
||||
const shouldDisplay = note => {
|
||||
|
@ -1,24 +0,0 @@
|
||||
<script>
|
||||
import {uniq} from 'ramda'
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {shuffle} from 'src/util/misc'
|
||||
import {isLike, Tags} from 'src/util/nostr'
|
||||
import {user, getTopRelays, getFollows} from 'src/agent/helpers'
|
||||
|
||||
// Get first- and second-order follows. shuffle and slice network so we're not
|
||||
// sending too many pubkeys. This will also result in some variety.
|
||||
const follows = shuffle(Tags.wrap(getFollows($user?.pubkey)).values().all())
|
||||
const others = shuffle(Tags.wrap(follows.flatMap(getFollows)).values().all()).slice(0, 50)
|
||||
const authors = uniq(follows.concat(others)).slice(0, 100)
|
||||
const relays = getTopRelays(authors, 'write')
|
||||
const filter = {kinds: [1, 7], authors}
|
||||
|
||||
const shouldDisplay = note => {
|
||||
return (
|
||||
note.reactions.filter(isLike).length > 2
|
||||
|| note.replies.length > 2
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Notes {relays} {filter} {shouldDisplay} />
|
@ -1,10 +1,10 @@
|
||||
<script>
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {getPubkeyRelays} from 'src/agent/helpers'
|
||||
import {getPubkeyWriteRelays} from 'src/agent/relays'
|
||||
|
||||
export let pubkey
|
||||
|
||||
const relays = getPubkeyRelays(pubkey, 'write')
|
||||
const relays = getPubkeyWriteRelays(pubkey)
|
||||
const filter = {kinds: [7], authors: [pubkey]}
|
||||
</script>
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {getPubkeyRelays} from 'src/agent/helpers'
|
||||
import {getPubkeyWriteRelays} from 'src/agent/relays'
|
||||
|
||||
export let pubkey
|
||||
|
||||
const relays = getPubkeyRelays(pubkey, 'write')
|
||||
const relays = getPubkeyWriteRelays(pubkey)
|
||||
const filter = {kinds: [1], authors: [pubkey]}
|
||||
</script>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user