mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-19 19:46:42 +00:00
Fix nip 65, remove relays from people, pulling stats from routes table only
This commit is contained in:
parent
12506c015b
commit
130773a90c
@ -7,10 +7,12 @@
|
|||||||
- [ ] Separate user info and relays so we can still select/figure out relays for anons
|
- [ ] 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
|
- [ ] 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
|
- [ ] Initial user load doesn't have any relays, cache user or wait for people db to be loaded
|
||||||
|
- nip07.getRelays, nip05, relay.nostr.band
|
||||||
- [ ] Fix bugs on bugsnag
|
- [ ] Fix bugs on bugsnag
|
||||||
|
|
||||||
# Snacks
|
# Snacks
|
||||||
|
|
||||||
|
- [ ] DM/chat read status in encrypted note
|
||||||
- [ ] Relay recommendations based on follows/followers
|
- [ ] Relay recommendations based on follows/followers
|
||||||
- [ ] Pinned posts ala snort
|
- [ ] Pinned posts ala snort
|
||||||
- [ ] Likes list on note detail. Maybe a sidebar or header for note detail page?
|
- [ ] Likes list on note detail. Maybe a sidebar or header for note detail page?
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
import {displayPerson, isLike} from 'src/util/nostr'
|
import {displayPerson, isLike} from 'src/util/nostr'
|
||||||
import {timedelta, shuffle, now, sleep} from 'src/util/misc'
|
import {timedelta, shuffle, now, sleep} from 'src/util/misc'
|
||||||
import cmd from 'src/agent/cmd'
|
import cmd from 'src/agent/cmd'
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getUserRelays} from 'src/agent/relays'
|
import {getUserRelays} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
|
@ -13,7 +13,17 @@ const updateUser = (relays, updates) =>
|
|||||||
publishEvent(relays, 0, {content: JSON.stringify(updates)})
|
publishEvent(relays, 0, {content: JSON.stringify(updates)})
|
||||||
|
|
||||||
const setRelays = (relays, newRelays) =>
|
const setRelays = (relays, newRelays) =>
|
||||||
publishEvent(relays, 10001, {tags: newRelays.map(r => [r.url, r.read || "", r.write || ""])})
|
publishEvent(relays, 10002, {
|
||||||
|
tags: newRelays.map(r => {
|
||||||
|
const t = ["r", r.url]
|
||||||
|
|
||||||
|
if (!r.write) {
|
||||||
|
t.push('read')
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
const setPetnames = (relays, petnames) =>
|
const setPetnames = (relays, petnames) =>
|
||||||
publishEvent(relays, 3, {tags: petnames})
|
publishEvent(relays, 3, {tags: petnames})
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
import type {Person} from 'src/util/types'
|
|
||||||
import type {Readable} from 'svelte/store'
|
|
||||||
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 database from 'src/agent/database'
|
|
||||||
import keys from 'src/agent/keys'
|
|
||||||
|
|
||||||
export const user = derived(
|
|
||||||
[keys.pubkey, database.people as Readable<any>],
|
|
||||||
([pubkey, $people]) => {
|
|
||||||
if (!pubkey) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($people[pubkey] || {pubkey})
|
|
||||||
}
|
|
||||||
) as Readable<Person>
|
|
||||||
|
|
||||||
export const getMuffle = () => {
|
|
||||||
const $user = get(user) as Person
|
|
||||||
|
|
||||||
if (!$user?.muffle) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const shouldMuffle = t => Math.random() > parseFloat(last(t))
|
|
||||||
|
|
||||||
return Tags.wrap($user.muffle.filter(shouldMuffle)).values().all()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFollows = pubkey =>
|
|
||||||
Tags.wrap(database.getPersonWithFallback(pubkey).petnames).type("p").values().all()
|
|
||||||
|
|
||||||
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
|
|
||||||
return uniq(pubkeys).filter(pubkey => {
|
|
||||||
const p = database.people.get(pubkey)
|
|
||||||
|
|
||||||
return !p || p.updated_at < now() - timedelta(1, 'days')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
|||||||
*
|
*
|
||||||
* cmd
|
* cmd
|
||||||
* -> network
|
* -> network
|
||||||
* -> helpers, pool
|
* -> user, pool
|
||||||
* -> keys
|
* -> keys
|
||||||
* -> sync
|
* -> sync
|
||||||
* -> database
|
* -> database
|
||||||
*
|
*
|
||||||
* In other words, command/network depend on utility functions and the network to
|
* In other words, command/network depend on utility functions and the network to
|
||||||
* do their job. The database sits at the bottom since it's shared between helpers
|
* do their job. The database sits at the bottom since it's shared between user
|
||||||
* which query the database, and network which both queries and updates it.
|
* which query the database, and network which both queries and updates it.
|
||||||
*/
|
*/
|
||||||
|
@ -1,16 +1,25 @@
|
|||||||
import {uniq, uniqBy, prop, map, propEq, indexBy, pluck} from 'ramda'
|
import {uniq, uniqBy, prop, map, propEq, indexBy, pluck} from 'ramda'
|
||||||
import {personKinds, findReplyId} from 'src/util/nostr'
|
import {personKinds, findReplyId} from 'src/util/nostr'
|
||||||
import {chunk} from 'hurdak/lib/hurdak'
|
import {chunk} from 'hurdak/lib/hurdak'
|
||||||
import {batch} from 'src/util/misc'
|
import {batch, timedelta, now} from 'src/util/misc'
|
||||||
import {getStalePubkeys} from 'src/agent/helpers'
|
|
||||||
import {
|
import {
|
||||||
getRelaysForEventParent, getAllPubkeyWriteRelays, aggregateScores,
|
getRelaysForEventParent, getAllPubkeyWriteRelays, aggregateScores,
|
||||||
getUserNetworkWriteRelays,
|
getUserNetworkWriteRelays,
|
||||||
} from 'src/agent/relays'
|
} from 'src/agent/relays'
|
||||||
|
import database from 'src/agent/database'
|
||||||
import pool from 'src/agent/pool'
|
import pool from 'src/agent/pool'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
import sync from 'src/agent/sync'
|
import sync from 'src/agent/sync'
|
||||||
|
|
||||||
|
const getStalePubkeys = pubkeys => {
|
||||||
|
// If we're not reloading, only get pubkeys we don't already know about
|
||||||
|
return uniq(pubkeys).filter(pubkey => {
|
||||||
|
const p = database.people.get(pubkey)
|
||||||
|
|
||||||
|
return !p || p.updated_at < now() - timedelta(1, 'days')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const publish = async (relays, event) => {
|
const publish = async (relays, event) => {
|
||||||
const signedEvent = await keys.sign(event)
|
const signedEvent = await keys.sign(event)
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import {get} from 'svelte/store'
|
import type {Relay} from 'src/util/types'
|
||||||
import {sortBy, uniq, uniqBy, prop, pluck} from 'ramda'
|
import {writable, get} from 'svelte/store'
|
||||||
import {createMapOf, first} from 'hurdak/lib/hurdak'
|
import {pick, map, assoc, sortBy, uniq, uniqBy, prop} from 'ramda'
|
||||||
|
import {first} from 'hurdak/lib/hurdak'
|
||||||
import {Tags} from 'src/util/nostr'
|
import {Tags} from 'src/util/nostr'
|
||||||
import {getFollows} from 'src/agent/helpers'
|
import {getFollows} from 'src/agent/social'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
|
|
||||||
@ -18,25 +19,24 @@ import keys from 'src/agent/keys'
|
|||||||
// doesn't need to see.
|
// doesn't need to see.
|
||||||
// 5) Advertise relays — write and read back your own relay list
|
// 5) Advertise relays — write and read back your own relay list
|
||||||
|
|
||||||
|
export const relays = writable([])
|
||||||
|
|
||||||
// Pubkey relays
|
// Pubkey relays
|
||||||
|
|
||||||
export const getPubkeyRelays = pubkey => {
|
export const getPubkeyRelays = (pubkey, mode = null) => {
|
||||||
const person = database.getPersonWithFallback(pubkey)
|
const filter = mode ? {pubkey, mode} : {pubkey}
|
||||||
|
|
||||||
return scoreRelays(pubkey, person.relays || [])
|
return sortByScore(map(pick(['url', 'score']), database.routes.all(filter)))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getPubkeyReadRelays = pubkey =>
|
export const getPubkeyReadRelays = pubkey => getPubkeyRelays(pubkey, 'read')
|
||||||
getPubkeyRelays(pubkey).filter(r => r.read !== '!')
|
|
||||||
|
|
||||||
export const getPubkeyWriteRelays = pubkey =>
|
export const getPubkeyWriteRelays = pubkey => getPubkeyRelays(pubkey, 'write')
|
||||||
getPubkeyRelays(pubkey).filter(r => r.write !== '!')
|
|
||||||
|
|
||||||
// Multiple pubkeys
|
// Multiple pubkeys
|
||||||
|
|
||||||
export const getAllPubkeyRelays = pubkeys =>
|
export const getAllPubkeyRelays = (pubkeys, mode = null) =>
|
||||||
aggregateScores(pubkeys.map(getPubkeyRelays))
|
aggregateScores(pubkeys.map(pubkey => getPubkeyRelays(pubkey, mode)))
|
||||||
|
|
||||||
export const getAllPubkeyReadRelays = pubkeys =>
|
export const getAllPubkeyReadRelays = pubkeys =>
|
||||||
aggregateScores(pubkeys.map(getPubkeyReadRelays))
|
aggregateScores(pubkeys.map(getPubkeyReadRelays))
|
||||||
@ -46,9 +46,9 @@ export const getAllPubkeyWriteRelays = pubkeys =>
|
|||||||
|
|
||||||
// Current user
|
// Current user
|
||||||
|
|
||||||
export const getUserRelays = () => getPubkeyRelays(get(keys.pubkey))
|
export const getUserRelays = (): Array<Relay> => get(relays).map(assoc('score', 1))
|
||||||
export const getUserReadRelays = () => getPubkeyReadRelays(get(keys.pubkey))
|
export const getUserReadRelays = () => getUserRelays().filter(prop('read'))
|
||||||
export const getUserWriteRelays = () => getPubkeyWriteRelays(get(keys.pubkey))
|
export const getUserWriteRelays = () => getUserRelays().filter(prop('write'))
|
||||||
|
|
||||||
// Network relays
|
// Network relays
|
||||||
|
|
||||||
@ -111,13 +111,6 @@ export const getEventPublishRelays = event => {
|
|||||||
const uniqByUrl = uniqBy(prop('url'))
|
const uniqByUrl = uniqBy(prop('url'))
|
||||||
const sortByScore = sortBy(r => -r.score)
|
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 => {
|
export const aggregateScores = relayGroups => {
|
||||||
const scores = {} as Record<string, {
|
const scores = {} as Record<string, {
|
||||||
score: number,
|
score: number,
|
||||||
|
9
src/agent/social.ts
Normal file
9
src/agent/social.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import {uniq} from 'ramda'
|
||||||
|
import {Tags} from 'src/util/nostr'
|
||||||
|
import database from 'src/agent/database'
|
||||||
|
|
||||||
|
export const getFollows = pubkey =>
|
||||||
|
Tags.wrap(database.getPersonWithFallback(pubkey).petnames).type("p").values().all()
|
||||||
|
|
||||||
|
export const getNetwork = pubkey =>
|
||||||
|
uniq(getFollows(pubkey).flatMap(getFollows))
|
@ -41,49 +41,8 @@ const processProfileEvents = async events => {
|
|||||||
return content
|
return content
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
2: () => {
|
3: () => ({petnames: e.tags}),
|
||||||
if (e.created_at > (person.relays_updated_at || 0)) {
|
|
||||||
const {relays = []} = database.getPersonWithFallback(e.pubkey)
|
|
||||||
|
|
||||||
return {
|
|
||||||
relays: relays.concat({url: e.content}),
|
|
||||||
relays_updated_at: e.created_at,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
3: () => {
|
|
||||||
const data = {petnames: e.tags}
|
|
||||||
|
|
||||||
if (e.created_at > (person.relays_updated_at || 0)) {
|
|
||||||
tryJson(() => {
|
|
||||||
Object.assign(data, {
|
|
||||||
relays_updated_at: e.created_at,
|
|
||||||
relays: Object.entries(JSON.parse(e.content))
|
|
||||||
.map(([url, conditions]) => {
|
|
||||||
const {write, read} = conditions as Record<string, boolean|string>
|
|
||||||
|
|
||||||
return {
|
|
||||||
url,
|
|
||||||
write: [false, '!'].includes(write) ? '!' : '',
|
|
||||||
read: [false, '!'].includes(read) ? '!' : '',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(r => isRelay(r.url)),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return data
|
|
||||||
},
|
|
||||||
12165: () => ({muffle: e.tags}),
|
12165: () => ({muffle: e.tags}),
|
||||||
10001: () => {
|
|
||||||
if (e.created_at > (person.relays_updated_at || 0)) {
|
|
||||||
return {
|
|
||||||
relays: e.tags.map(([url, read, write]) => ({url, read, write})),
|
|
||||||
relays_updated_at: e.created_at,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
default: () => {
|
default: () => {
|
||||||
log(`Received unsupported event type ${e.kind}`)
|
log(`Received unsupported event type ${e.kind}`)
|
||||||
},
|
},
|
||||||
@ -153,7 +112,7 @@ const processMessages = async events => {
|
|||||||
|
|
||||||
const getWeight = type => {
|
const getWeight = type => {
|
||||||
if (type === 'nip05') return 1
|
if (type === 'nip05') return 1
|
||||||
if (type === 'kind:10001') return 1
|
if (type === 'kind:10002') return 1
|
||||||
if (type === 'kind:3') return 0.8
|
if (type === 'kind:3') return 0.8
|
||||||
if (type === 'kind:2') return 0.5
|
if (type === 'kind:2') return 0.5
|
||||||
if (type === 'seen') return 0.2
|
if (type === 'seen') return 0.2
|
||||||
@ -216,19 +175,14 @@ const processRoutes = async events => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
10001: () => {
|
10002: () => {
|
||||||
e.tags
|
e.tags
|
||||||
.forEach(([url, read, write]) => {
|
.forEach(([url, read, mode]) => {
|
||||||
if (![false, '!'].includes(write)) {
|
if (mode) {
|
||||||
updates.push(
|
calculateRoute(e.pubkey, url, 'kind:10002', mode, e.created_at)
|
||||||
calculateRoute(e.pubkey, url, 'kind:100001', 'write', e.created_at)
|
} else {
|
||||||
)
|
calculateRoute(e.pubkey, url, 'kind:10002', 'read', e.created_at)
|
||||||
}
|
calculateRoute(e.pubkey, url, 'kind:10002', 'write', e.created_at)
|
||||||
|
|
||||||
if (![false, '!'].includes(read)) {
|
|
||||||
updates.push(
|
|
||||||
calculateRoute(e.pubkey, url, 'kind:100001', 'read', e.created_at)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
16
src/agent/user.ts
Normal file
16
src/agent/user.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import type {Person} from 'src/util/types'
|
||||||
|
import type {Readable} from 'svelte/store'
|
||||||
|
import {derived} from 'svelte/store'
|
||||||
|
import database from 'src/agent/database'
|
||||||
|
import keys from 'src/agent/keys'
|
||||||
|
|
||||||
|
export const user = derived(
|
||||||
|
[keys.pubkey, database.people as Readable<any>],
|
||||||
|
([pubkey, $people]) => {
|
||||||
|
if (!pubkey) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($people[pubkey] || {pubkey})
|
||||||
|
}
|
||||||
|
) as Readable<Person>
|
@ -5,9 +5,9 @@ import {createMap, ellipsize} from 'hurdak/lib/hurdak'
|
|||||||
import {get} from 'svelte/store'
|
import {get} from 'svelte/store'
|
||||||
import {renderContent} from 'src/util/html'
|
import {renderContent} from 'src/util/html'
|
||||||
import {Tags, displayPerson, findReplyId} from 'src/util/nostr'
|
import {Tags, displayPerson, findReplyId} from 'src/util/nostr'
|
||||||
import {user, getNetwork} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getUserWriteRelays} from 'src/agent/relays'
|
import {getNetwork} from 'src/agent/social'
|
||||||
import defaults from 'src/agent/defaults'
|
import {relays} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
@ -49,44 +49,50 @@ export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: strin
|
|||||||
|
|
||||||
export const addRelay = async url => {
|
export const addRelay = async url => {
|
||||||
const person = get(user) as Person
|
const person = get(user) as Person
|
||||||
const modify = relays => relays.concat({url, write: '!'})
|
|
||||||
|
|
||||||
// Set to defaults to support anonymous usage
|
relays.update($relays => {
|
||||||
defaults.relays = modify(defaults.relays)
|
$relays.push({url, write: false, read: true})
|
||||||
|
|
||||||
if (person) {
|
if (person) {
|
||||||
const relays = modify(person.relays || [])
|
(async () => {
|
||||||
|
|
||||||
// Publish to the new set of relays
|
// Publish to the new set of relays
|
||||||
await cmd.setRelays(relays, relays)
|
await cmd.setRelays($relays, $relays)
|
||||||
|
|
||||||
// Reload alerts, messages, etc
|
// Reload alerts, messages, etc
|
||||||
await loadAppData(person.pubkey)
|
await loadAppData(person.pubkey)
|
||||||
|
})()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $relays
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeRelay = async url => {
|
export const removeRelay = async url => {
|
||||||
const person = get(user) as Person
|
const person = get(user) as Person
|
||||||
const modify = relays => reject(whereEq({url}), relays)
|
|
||||||
|
|
||||||
// Set to defaults to support anonymous usage
|
relays.update($relays => {
|
||||||
defaults.relays = modify(defaults.relays)
|
$relays = reject(whereEq({url}), $relays)
|
||||||
|
|
||||||
if (person) {
|
if (person && $relays.length > 0) {
|
||||||
await cmd.setRelays(getUserWriteRelays(), modify(person.relays || []))
|
cmd.setRelays($relays, $relays)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $relays
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setRelayWriteCondition = async (url, write) => {
|
export const setRelayWriteCondition = async (url, write) => {
|
||||||
const person = get(user) as Person
|
const person = get(user) as Person
|
||||||
const modify = relays => relays.map(when(whereEq({url}), assoc('write', write)))
|
|
||||||
|
|
||||||
// Set to defaults to support anonymous usage
|
relays.update($relays => {
|
||||||
defaults.relays = modify(defaults.relays)
|
$relays = $relays.map(when(whereEq({url}), assoc('write', write)))
|
||||||
|
|
||||||
if (person) {
|
if (person && $relays.length > 0) {
|
||||||
await cmd.setRelays(getUserWriteRelays(), modify(person.relays || []))
|
cmd.setRelays($relays, $relays)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $relays
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const renderNote = (note, {showEntire = false}) => {
|
export const renderNote = (note, {showEntire = false}) => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {pluck, reject} from 'ramda'
|
import {pluck, reject} from 'ramda'
|
||||||
import {get} from 'svelte/store'
|
import {get} from 'svelte/store'
|
||||||
import {synced, now, timedelta} from 'src/util/misc'
|
import {synced, now, timedelta} from 'src/util/misc'
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getUserReadRelays} from 'src/agent/relays'
|
import {getUserReadRelays} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import Badge from 'src/partials/Badge.svelte'
|
import Badge from 'src/partials/Badge.svelte'
|
||||||
import Anchor from 'src/partials/Anchor.svelte'
|
import Anchor from 'src/partials/Anchor.svelte'
|
||||||
import Spinner from 'src/partials/Spinner.svelte'
|
import Spinner from 'src/partials/Spinner.svelte'
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import {renderNote} from 'src/app'
|
import {renderNote} from 'src/app'
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import {formatTimestamp, stringToColor} from 'src/util/misc'
|
import {formatTimestamp, stringToColor} from 'src/util/misc'
|
||||||
import Compose from "src/partials/Compose.svelte"
|
import Compose from "src/partials/Compose.svelte"
|
||||||
import Card from "src/partials/Card.svelte"
|
import Card from "src/partials/Card.svelte"
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getEventPublishRelays, getRelaysForEventParent} from 'src/agent/relays'
|
import {getEventPublishRelays, getRelaysForEventParent} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import cmd from 'src/agent/cmd'
|
import cmd from 'src/agent/cmd'
|
||||||
@ -217,7 +217,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</Anchor>
|
</Anchor>
|
||||||
<Anchor
|
<Anchor
|
||||||
href={"/" + nip19.neventEncode({id: note.id, relays: [note.seen_on.url]})}
|
href={"/" + nip19.neventEncode({id: note.id, relays: [note.seen_on]})}
|
||||||
class="text-sm text-light"
|
class="text-sm text-light"
|
||||||
type="unstyled">
|
type="unstyled">
|
||||||
{formatTimestamp(note.created_at)}
|
{formatTimestamp(note.created_at)}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount} from 'svelte'
|
import {onMount} from 'svelte'
|
||||||
import {partition, propEq, always, mergeRight, uniqBy, sortBy, prop} from 'ramda'
|
import {partition, last, propEq, always, mergeRight, uniqBy, sortBy, prop} from 'ramda'
|
||||||
import {slide} from 'svelte/transition'
|
import {slide} from 'svelte/transition'
|
||||||
import {quantify} from 'hurdak/lib/hurdak'
|
import {quantify} from 'hurdak/lib/hurdak'
|
||||||
import {createScroller, now, Cursor} from 'src/util/misc'
|
import {createScroller, now, Cursor} from 'src/util/misc'
|
||||||
|
import {Tags} from 'src/util/nostr'
|
||||||
import Spinner from 'src/partials/Spinner.svelte'
|
import Spinner from 'src/partials/Spinner.svelte'
|
||||||
import Content from 'src/partials/Content.svelte'
|
import Content from 'src/partials/Content.svelte'
|
||||||
import Note from "src/partials/Note.svelte"
|
import Note from "src/partials/Note.svelte"
|
||||||
import {getMuffle} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {modal, mergeParents} from "src/app"
|
import {modal, mergeParents} from "src/app"
|
||||||
|
|
||||||
@ -20,8 +21,10 @@
|
|||||||
|
|
||||||
const since = now()
|
const since = now()
|
||||||
const maxNotes = 300
|
const maxNotes = 300
|
||||||
const muffle = getMuffle()
|
|
||||||
const cursor = new Cursor()
|
const cursor = new Cursor()
|
||||||
|
const muffle = Tags
|
||||||
|
.wrap(($user?.muffle || []).filter(t => Math.random() > parseFloat(last(t))))
|
||||||
|
.values().all()
|
||||||
|
|
||||||
const processNewNotes = async newNotes => {
|
const processNewNotes = async newNotes => {
|
||||||
// Remove people we're not interested in hearing about, sort by created date
|
// Remove people we're not interested in hearing about, sort by created date
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import {between} from 'hurdak/lib/hurdak'
|
import {between} from 'hurdak/lib/hurdak'
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import Toggle from "src/partials/Toggle.svelte"
|
import Toggle from "src/partials/Toggle.svelte"
|
||||||
import {user} from "src/agent/helpers"
|
import {relays} from "src/agent/relays"
|
||||||
import pool from 'src/agent/pool'
|
import pool from 'src/agent/pool'
|
||||||
import {addRelay, removeRelay, setRelayWriteCondition} from "src/app"
|
import {addRelay, removeRelay, setRelayWriteCondition} from "src/app"
|
||||||
|
|
||||||
@ -19,7 +19,7 @@
|
|||||||
let showStatus = false
|
let showStatus = false
|
||||||
let joined = false
|
let joined = false
|
||||||
|
|
||||||
$: joined = find(propEq('url', relay.url), $user?.relays || [])
|
$: joined = find(propEq('url', relay.url), $relays)
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
return poll(10_000, async () => {
|
return poll(10_000, async () => {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {navigate} from "svelte-routing"
|
import {navigate} from "svelte-routing"
|
||||||
import {fuzzy} from "src/util/misc"
|
import {fuzzy} from "src/util/misc"
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import {getUserReadRelays} from 'src/agent/relays'
|
import {getUserReadRelays} from 'src/agent/relays'
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {now} from 'src/util/misc'
|
import {now} from 'src/util/misc'
|
||||||
import Channel from 'src/partials/Channel.svelte'
|
import Channel from 'src/partials/Channel.svelte'
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getRelaysForEventChildren} from 'src/agent/relays'
|
import {getRelaysForEventChildren} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import {personKinds} from 'src/util/nostr'
|
import {personKinds} from 'src/util/nostr'
|
||||||
import {now} from 'src/util/misc'
|
import {now} from 'src/util/misc'
|
||||||
import Channel from 'src/partials/Channel.svelte'
|
import Channel from 'src/partials/Channel.svelte'
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getAllPubkeyRelays} from 'src/agent/relays'
|
import {getAllPubkeyRelays} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import Tabs from "src/partials/Tabs.svelte"
|
import Tabs from "src/partials/Tabs.svelte"
|
||||||
import Network from "src/views/notes/Network.svelte"
|
import Network from "src/views/notes/Network.svelte"
|
||||||
import Popular from "src/views/notes/Popular.svelte"
|
import Popular from "src/views/notes/Popular.svelte"
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
|
|
||||||
export let activeTab
|
export let activeTab
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import Notes from "src/views/person/Notes.svelte"
|
import Notes from "src/views/person/Notes.svelte"
|
||||||
import Likes from "src/views/person/Likes.svelte"
|
import Likes from "src/views/person/Likes.svelte"
|
||||||
import Relays from "src/views/person/Relays.svelte"
|
import Relays from "src/views/person/Relays.svelte"
|
||||||
import {user} from "src/agent/helpers"
|
import {user} from "src/agent/user"
|
||||||
import {getPubkeyWriteRelays, getUserWriteRelays} from "src/agent/relays"
|
import {getPubkeyWriteRelays, getUserWriteRelays} from "src/agent/relays"
|
||||||
import network from "src/agent/network"
|
import network from "src/agent/network"
|
||||||
import keys from "src/agent/keys"
|
import keys from "src/agent/keys"
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Heading from "src/partials/Heading.svelte"
|
import Heading from "src/partials/Heading.svelte"
|
||||||
import {user} from "src/agent/helpers"
|
import {user} from "src/agent/user"
|
||||||
import {getUserWriteRelays} from 'src/agent/relays'
|
import {getUserWriteRelays} from 'src/agent/relays'
|
||||||
import cmd from "src/agent/cmd"
|
import cmd from "src/agent/cmd"
|
||||||
import {toast} from "src/app"
|
import {toast} from "src/app"
|
||||||
|
@ -8,14 +8,14 @@
|
|||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import RelayCard from "src/partials/RelayCard.svelte"
|
import RelayCard from "src/partials/RelayCard.svelte"
|
||||||
import {user} from "src/agent/helpers"
|
import {relays} from "src/agent/relays"
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import {modal, settings} from "src/app"
|
import {modal, settings} from "src/app"
|
||||||
import defaults from "src/agent/defaults"
|
import defaults from "src/agent/defaults"
|
||||||
|
|
||||||
let q = ""
|
let q = ""
|
||||||
let search
|
let search
|
||||||
let relays = []
|
let knownRelays = database.watch('relays', t => t.all())
|
||||||
|
|
||||||
fetch(get(settings).dufflepudUrl + '/relay')
|
fetch(get(settings).dufflepudUrl + '/relay')
|
||||||
.then(async res => {
|
.then(async res => {
|
||||||
@ -26,15 +26,13 @@
|
|||||||
|
|
||||||
database.relays.bulkPatch(createMap('url', defaults.relays))
|
database.relays.bulkPatch(createMap('url', defaults.relays))
|
||||||
|
|
||||||
const knownRelays = database.watch('relays', relays => relays.all())
|
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
relays = $user?.relays || []
|
const joined = new Set(pluck('url', $relays))
|
||||||
|
|
||||||
const joined = new Set(pluck('url', relays))
|
search = fuzzy(
|
||||||
const data = ($knownRelays || []).filter(r => !joined.has(r.url))
|
$knownRelays.filter(r => !joined.has(r.url)),
|
||||||
|
{keys: ["name", "description", "url"]}
|
||||||
search = fuzzy(data, {keys: ["name", "description", "url"]})
|
)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -52,11 +50,11 @@
|
|||||||
Relays are hubs for your content and connections. At least one is required to
|
Relays are hubs for your content and connections. At least one is required to
|
||||||
interact with the network, but you can join as many as you like.
|
interact with the network, but you can join as many as you like.
|
||||||
</p>
|
</p>
|
||||||
{#if relays.length === 0}
|
{#if $relays.length === 0}
|
||||||
<div class="text-center">No relays connected</div>
|
<div class="text-center">No relays connected</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="grid grid-cols-1 gap-4">
|
<div class="grid grid-cols-1 gap-4">
|
||||||
{#each relays as relay (relay.url)}
|
{#each $relays as relay (relay.url)}
|
||||||
<RelayCard showControls {relay} />
|
<RelayCard showControls {relay} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@ -79,8 +77,8 @@
|
|||||||
<RelayCard {relay} />
|
<RelayCard {relay} />
|
||||||
{/each}
|
{/each}
|
||||||
<small class="text-center">
|
<small class="text-center">
|
||||||
Showing {Math.min(($knownRelays || []).length - relays.length, 50)}
|
Showing {Math.min(($knownRelays || []).length - $relays.length, 50)}
|
||||||
of {($knownRelays || []).length - relays.length} known relays
|
of {($knownRelays || []).length - $relays.length} known relays
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Heading from "src/partials/Heading.svelte"
|
import Heading from "src/partials/Heading.svelte"
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {toast, settings} from "src/app"
|
import {toast, settings} from "src/app"
|
||||||
|
|
||||||
let values = {...$settings}
|
let values = {...$settings}
|
||||||
|
@ -2,7 +2,7 @@ import {last, identity, objOf, prop, flatten, uniq} from 'ramda'
|
|||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {ensurePlural, ellipsize, first} from 'hurdak/lib/hurdak'
|
import {ensurePlural, ellipsize, first} from 'hurdak/lib/hurdak'
|
||||||
|
|
||||||
export const personKinds = [0, 2, 3, 10001, 12165]
|
export const personKinds = [0, 2, 3, 10002, 12165]
|
||||||
|
|
||||||
export class Tags {
|
export class Tags {
|
||||||
constructor(tags) {
|
constructor(tags) {
|
||||||
|
@ -2,6 +2,9 @@ import type {Event} from 'nostr-tools'
|
|||||||
|
|
||||||
export type Relay = {
|
export type Relay = {
|
||||||
url: string
|
url: string
|
||||||
|
score?: number
|
||||||
|
write?: boolean
|
||||||
|
read?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Person = {
|
export type Person = {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import {onMount} from "svelte"
|
import {onMount} from "svelte"
|
||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {quantify} from 'hurdak/lib/hurdak'
|
import {quantify} from 'hurdak/lib/hurdak'
|
||||||
import {last, whereEq, find, reject, pluck, propEq} from 'ramda'
|
import {last, reject, pluck, propEq} from 'ramda'
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {navigate} from "svelte-routing"
|
import {navigate} from "svelte-routing"
|
||||||
import {fuzzy} from "src/util/misc"
|
import {fuzzy} from "src/util/misc"
|
||||||
@ -13,7 +13,7 @@
|
|||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Modal from "src/partials/Modal.svelte"
|
import Modal from "src/partials/Modal.svelte"
|
||||||
import Heading from 'src/partials/Heading.svelte'
|
import Heading from 'src/partials/Heading.svelte'
|
||||||
import {user} from "src/agent/helpers"
|
import {user} from "src/agent/user"
|
||||||
import {getUserWriteRelays} from 'src/agent/relays'
|
import {getUserWriteRelays} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import cmd from "src/agent/cmd"
|
import cmd from "src/agent/cmd"
|
||||||
@ -27,12 +27,15 @@
|
|||||||
let q = ''
|
let q = ''
|
||||||
let search
|
let search
|
||||||
|
|
||||||
const knownRelays = database.watch('relays', relays => relays.all())
|
const knownRelays = database.watch('relays', t => t.all())
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
const data = reject(({url}) => find(whereEq({url}), relays), $knownRelays || [])
|
const joined = new Set(pluck('url', relays))
|
||||||
|
|
||||||
search = fuzzy(data, {keys: ["name", "description", "url"]})
|
search = fuzzy(
|
||||||
|
$knownRelays.filter(r => !joined.has(r.url)),
|
||||||
|
{keys: ["name", "description", "url"]}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Content from 'src/partials/Content.svelte'
|
import Content from 'src/partials/Content.svelte'
|
||||||
import SelectButton from "src/partials/SelectButton.svelte"
|
import SelectButton from "src/partials/SelectButton.svelte"
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getUserWriteRelays} from 'src/agent/relays'
|
import {getUserWriteRelays} from 'src/agent/relays'
|
||||||
import cmd from 'src/agent/cmd'
|
import cmd from 'src/agent/cmd'
|
||||||
import {modal} from 'src/app'
|
import {modal} from 'src/app'
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import {personKinds} from "src/util/nostr"
|
import {personKinds} from "src/util/nostr"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
||||||
import {user} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
import {getUserReadRelays} from 'src/agent/relays'
|
import {getUserReadRelays} from 'src/agent/relays'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import {uniq} from 'ramda'
|
import {uniq} from 'ramda'
|
||||||
import Notes from "src/partials/Notes.svelte"
|
import Notes from "src/partials/Notes.svelte"
|
||||||
import {user, getFollows, getNetwork} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
|
import {getFollows, getNetwork} from 'src/agent/social'
|
||||||
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
||||||
|
|
||||||
// Get first- and second-order follows. shuffle and slice network so we're not
|
// Get first- and second-order follows. shuffle and slice network so we're not
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
import {uniq} from 'ramda'
|
import {uniq} from 'ramda'
|
||||||
import Notes from "src/partials/Notes.svelte"
|
import Notes from "src/partials/Notes.svelte"
|
||||||
import {isLike} from 'src/util/nostr'
|
import {isLike} from 'src/util/nostr'
|
||||||
import {user, getFollows, getNetwork} from 'src/agent/helpers'
|
import {user} from 'src/agent/user'
|
||||||
|
import {getFollows, getNetwork} from 'src/agent/social'
|
||||||
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
import {getAllPubkeyWriteRelays} from 'src/agent/relays'
|
||||||
|
|
||||||
// Get first- and second-order follows. shuffle and slice network so we're not
|
// Get first- and second-order follows. shuffle and slice network so we're not
|
||||||
|
Loading…
Reference in New Issue
Block a user