mirror of
https://github.com/coracle-social/coracle.git
synced 2024-10-01 17:31:24 +00:00
Move relay selections to system/routing
This commit is contained in:
parent
8205f70027
commit
0405a073c0
2
.env
2
.env
@ -1,6 +1,6 @@
|
|||||||
VITE_THEME=transparent:transparent,black:#0f0f0e,white:#FFFFFF,accent:#EB5E28,accent-light:#FB652C,gray-dark:#8D8581,gray-light:#A8A5A4,danger:#ff0000,warning:#ebd112,success:#37ab51,input:#FAF6F1,input-hover:#F2EBE1
|
VITE_THEME=transparent:transparent,black:#0f0f0e,white:#FFFFFF,accent:#EB5E28,accent-light:#FB652C,gray-dark:#8D8581,gray-light:#A8A5A4,danger:#ff0000,warning:#ebd112,success:#37ab51,input:#FAF6F1,input-hover:#F2EBE1
|
||||||
VITE_DEFAULT_FOLLOWS=1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,b83a28b7e4e5d20bd960c5faeb6625f95529166b8bdb045d42634a2f35919450,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,a4cb51f4618cfcd16b2d3171c466179bed8e197c43b8598823b04de266cef110,e56e7b4326618f3d626c0e398f5082c3b16732e469e0a048b7ddb544c2be294a,011c1b374c12fbd3633e98957d3c46bed67983abecef50706c73a77c171d0d2c,b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc,b708f7392f588406212c3882e7b3bc0d9b08d62f95fa170d099127ece2770e5e,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,0fecf65daa26faf3f668e8143325a4c199a040b6345ed40a08614d7dd85b1823,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322
|
VITE_DEFAULT_FOLLOWS=1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,b83a28b7e4e5d20bd960c5faeb6625f95529166b8bdb045d42634a2f35919450,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,a4cb51f4618cfcd16b2d3171c466179bed8e197c43b8598823b04de266cef110,e56e7b4326618f3d626c0e398f5082c3b16732e469e0a048b7ddb544c2be294a,011c1b374c12fbd3633e98957d3c46bed67983abecef50706c73a77c171d0d2c,b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc,b708f7392f588406212c3882e7b3bc0d9b08d62f95fa170d099127ece2770e5e,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,0fecf65daa26faf3f668e8143325a4c199a040b6345ed40a08614d7dd85b1823,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322
|
||||||
VITE_DUFFLEPUD_URL=http://localhost:8000
|
VITE_DUFFLEPUD_URL=https://dufflepud.onrender.com
|
||||||
VITE_ENABLE_ZAPS=true
|
VITE_ENABLE_ZAPS=true
|
||||||
VITE_FORCE_RELAYS=
|
VITE_FORCE_RELAYS=
|
||||||
VITE_LOGO_URL=
|
VITE_LOGO_URL=
|
||||||
|
@ -6,7 +6,10 @@ import {Tags, isRelay, findReplyId} from "src/util/nostr"
|
|||||||
import {shuffle} from "src/util/misc"
|
import {shuffle} from "src/util/misc"
|
||||||
import {routes} from "src/agent/db"
|
import {routes} from "src/agent/db"
|
||||||
import pool from "src/agent/pool"
|
import pool from "src/agent/pool"
|
||||||
import user from "src/agent/user"
|
|
||||||
|
const ext = {routing: null}
|
||||||
|
|
||||||
|
export default {ext}
|
||||||
|
|
||||||
// From Mike Dilger:
|
// From Mike Dilger:
|
||||||
// 1) Other people's write relays — pull events from people you follow,
|
// 1) Other people's write relays — pull events from people you follow,
|
||||||
@ -63,8 +66,8 @@ export const getAllPubkeyWriteRelays = pubkeys => getAllPubkeyRelays(pubkeys, "w
|
|||||||
// Current user
|
// Current user
|
||||||
|
|
||||||
export const getUserRelays = () =>
|
export const getUserRelays = () =>
|
||||||
user
|
ext.routing
|
||||||
.getRelays()
|
.getUserRelays()
|
||||||
.filter(({url}) => isRelay(url))
|
.filter(({url}) => isRelay(url))
|
||||||
.map(assoc("score", 1))
|
.map(assoc("score", 1))
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import type {Relay} from "src/util/types"
|
|
||||||
import type {Readable} from "svelte/store"
|
import type {Readable} from "svelte/store"
|
||||||
import {uniqBy, without, reject, prop, assoc, whereEq, when, map} from "ramda"
|
import {without, prop} from "ramda"
|
||||||
import {synced} from "src/util/misc"
|
import {synced} from "src/util/misc"
|
||||||
import {derived, get} from "svelte/store"
|
import {derived, get} from "svelte/store"
|
||||||
import keys from "src/system/keys"
|
import keys from "src/system/keys"
|
||||||
import pool from "src/agent/pool"
|
|
||||||
|
|
||||||
const ext = {cmd: null}
|
const ext = {cmd: null}
|
||||||
|
|
||||||
@ -14,14 +12,10 @@ const profile = synced("agent/user/profile", {
|
|||||||
lnurl: null,
|
lnurl: null,
|
||||||
rooms_joined: [],
|
rooms_joined: [],
|
||||||
last_checked: {},
|
last_checked: {},
|
||||||
relays: pool.defaultRelays,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const roomsJoined = derived(profile, prop("rooms_joined")) as Readable<string>
|
const roomsJoined = derived(profile, prop("rooms_joined")) as Readable<string>
|
||||||
const lastChecked = derived(profile, prop("last_checked")) as Readable<Record<string, number>>
|
const lastChecked = derived(profile, prop("last_checked")) as Readable<Record<string, number>>
|
||||||
const relays = derived(profile, p =>
|
|
||||||
pool.forceRelays.length > 0 ? pool.forceRelays : p.relays
|
|
||||||
) as Readable<Array<Relay>>
|
|
||||||
|
|
||||||
// Keep a copy so we can avoid calling `get` all the time
|
// Keep a copy so we can avoid calling `get` all the time
|
||||||
|
|
||||||
@ -68,27 +62,4 @@ export default {
|
|||||||
leaveRoom(id) {
|
leaveRoom(id) {
|
||||||
this.setAppData("rooms_joined/v1", without([id], profileCopy.rooms_joined))
|
this.setAppData("rooms_joined/v1", without([id], profileCopy.rooms_joined))
|
||||||
},
|
},
|
||||||
|
|
||||||
// Relays
|
|
||||||
|
|
||||||
relays,
|
|
||||||
getRelays: () => profileCopy.relays,
|
|
||||||
updateRelays(f) {
|
|
||||||
const $relays = uniqBy(prop("url"), f(profileCopy.relays))
|
|
||||||
|
|
||||||
profile.update(assoc("relays", $relays))
|
|
||||||
|
|
||||||
if (get(keys.canSign)) {
|
|
||||||
return ext.cmd.setRelays($relays).publish($relays)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addRelay(url) {
|
|
||||||
return this.updateRelays($relays => $relays.concat({url, write: true, read: true}))
|
|
||||||
},
|
|
||||||
removeRelay(url) {
|
|
||||||
return this.updateRelays(reject(whereEq({url})))
|
|
||||||
},
|
|
||||||
setRelayWriteCondition(url, write) {
|
|
||||||
return this.updateRelays(map(when(whereEq({url}), assoc("write", write))))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import {modal} from "src/partials/state"
|
import {modal} from "src/partials/state"
|
||||||
import OverflowMenu from "src/partials/OverflowMenu.svelte"
|
import OverflowMenu from "src/partials/OverflowMenu.svelte"
|
||||||
import {keys, routing} from "src/system"
|
import {keys, routing} from "src/system"
|
||||||
import user from "src/agent/user"
|
import {watch} from "src/agent/db"
|
||||||
import {addToList} from "src/app/state"
|
import {addToList} from "src/app/state"
|
||||||
|
|
||||||
export let relay
|
export let relay
|
||||||
@ -11,23 +11,23 @@
|
|||||||
relay = routing.getRelay(relay.url)
|
relay = routing.getRelay(relay.url)
|
||||||
|
|
||||||
const {canSign} = keys
|
const {canSign} = keys
|
||||||
const {relays: userRelays} = user
|
const relays = watch(routing.policies, () => routing.getUserRelays())
|
||||||
|
|
||||||
let actions = []
|
let actions = []
|
||||||
|
|
||||||
$: joined = find(propEq("url", relay.url), $userRelays)
|
$: joined = find(propEq("url", relay.url), $relays)
|
||||||
$: {
|
$: {
|
||||||
actions = []
|
actions = []
|
||||||
|
|
||||||
if (!joined) {
|
if (!joined) {
|
||||||
actions.push({
|
actions.push({
|
||||||
onClick: () => user.addRelay(relay.url),
|
onClick: () => routing.addUserRelay(relay.url),
|
||||||
label: "Join",
|
label: "Join",
|
||||||
icon: "right-to-bracket",
|
icon: "right-to-bracket",
|
||||||
})
|
})
|
||||||
} else if ($userRelays.length > 1) {
|
} else if ($relays.length > 1) {
|
||||||
actions.push({
|
actions.push({
|
||||||
onClick: () => user.removeRelay(relay.url),
|
onClick: () => routing.removeUserRelay(relay.url),
|
||||||
label: "Leave",
|
label: "Leave",
|
||||||
icon: "right-from-bracket",
|
icon: "right-from-bracket",
|
||||||
})
|
})
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import Rating from "src/partials/Rating.svelte"
|
import Rating from "src/partials/Rating.svelte"
|
||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import {keys, routing} from "src/system"
|
import {keys, routing} from "src/system"
|
||||||
|
import {watch} from "src/agent/db"
|
||||||
import pool from "src/agent/pool"
|
import pool from "src/agent/pool"
|
||||||
import user from "src/agent/user"
|
import user from "src/agent/user"
|
||||||
import {loadAppData} from "src/app/state"
|
import {loadAppData} from "src/app/state"
|
||||||
@ -22,18 +23,17 @@
|
|||||||
export let showControls = false
|
export let showControls = false
|
||||||
|
|
||||||
const {canSign} = keys
|
const {canSign} = keys
|
||||||
const {relays} = user
|
|
||||||
|
|
||||||
let statusHover = false
|
let statusHover = false
|
||||||
let quality = null
|
let quality = null
|
||||||
let message = null
|
let message = null
|
||||||
|
|
||||||
$: hasRelay = Boolean(find(propEq("url", relay.url), $relays))
|
const relays = watch(routing.policies, () => routing.getUserRelays())
|
||||||
|
|
||||||
const removeRelay = r => user.removeRelay(r.url)
|
const removeRelay = r => routing.removeUserRelay(r.url)
|
||||||
|
|
||||||
const addRelay = r => {
|
const addRelay = r => {
|
||||||
user.addRelay(r.url)
|
routing.addUserRelay(r.url)
|
||||||
|
|
||||||
const pubkey = keys.getPubkey()
|
const pubkey = keys.getPubkey()
|
||||||
const profile = user.getProfile()
|
const profile = user.getProfile()
|
||||||
@ -47,6 +47,8 @@
|
|||||||
modal.push({type: "relay/detail", url: relay.url})
|
modal.push({type: "relay/detail", url: relay.url})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: hasRelay = Boolean(find(propEq("url", relay.url), $relays))
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
return poll(10_000, () => {
|
return poll(10_000, () => {
|
||||||
;[quality, message] = pool.getQuality(relay.url)
|
;[quality, message] = pool.getQuality(relay.url)
|
||||||
@ -114,7 +116,7 @@
|
|||||||
<span>Publish to this relay?</span>
|
<span>Publish to this relay?</span>
|
||||||
<Toggle
|
<Toggle
|
||||||
value={relay.write}
|
value={relay.write}
|
||||||
on:change={() => user.setRelayWriteCondition(relay.url, !relay.write)} />
|
on:change={() => routing.setUserRelayPolicy(relay.url, {write: !relay.write})} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,17 +10,16 @@
|
|||||||
import {getUserReadRelays} from "src/agent/relays"
|
import {getUserReadRelays} from "src/agent/relays"
|
||||||
import network from "src/agent/network"
|
import network from "src/agent/network"
|
||||||
import {watch} from "src/agent/db"
|
import {watch} from "src/agent/db"
|
||||||
import user from "src/agent/user"
|
|
||||||
|
|
||||||
export let q = ""
|
export let q = ""
|
||||||
export let limit = 50
|
export let limit = 50
|
||||||
export let relays = user.relays
|
|
||||||
export let placeholder = "Search relays or add a custom url"
|
export let placeholder = "Search relays or add a custom url"
|
||||||
export let hideIfEmpty = false
|
export let hideIfEmpty = false
|
||||||
|
|
||||||
let search
|
let search
|
||||||
let reviews = []
|
let reviews = []
|
||||||
|
|
||||||
|
const userRelays = watch(routing.policies, () => routing.getUserRelays())
|
||||||
const knownRelays = watch(routing.relays, () => routing.relays.all())
|
const knownRelays = watch(routing.relays, () => routing.relays.all())
|
||||||
|
|
||||||
$: ratings = mapValues(
|
$: ratings = mapValues(
|
||||||
@ -29,7 +28,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
const joined = new Set(pluck("url", $relays))
|
const joined = new Set(pluck("url", $userRelays))
|
||||||
|
|
||||||
search = fuzzy(
|
search = fuzzy(
|
||||||
$knownRelays.filter(r => !joined.has(r.url)),
|
$knownRelays.filter(r => !joined.has(r.url)),
|
||||||
@ -65,8 +64,8 @@
|
|||||||
{/each}
|
{/each}
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<small class="text-center">
|
<small class="text-center">
|
||||||
Showing {Math.min(($knownRelays || []).length - $relays.length, 50)}
|
Showing {Math.min(($knownRelays || []).length - $userRelays.length, 50)}
|
||||||
of {($knownRelays || []).length - $relays.length} known relays
|
of {($knownRelays || []).length - $userRelays.length} known relays
|
||||||
</small>
|
</small>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
import {DEFAULT_RELAYS, routing, keys} from "src/system"
|
import {DEFAULT_RELAYS, routing, keys} from "src/system"
|
||||||
import {watch} from "src/agent/db"
|
import {watch} from "src/agent/db"
|
||||||
import network from "src/agent/network"
|
import network from "src/agent/network"
|
||||||
import user from "src/agent/user"
|
|
||||||
import pool from "src/agent/pool"
|
import pool from "src/agent/pool"
|
||||||
import {loadAppData} from "src/app/state"
|
import {loadAppData} from "src/app/state"
|
||||||
|
|
||||||
@ -64,7 +63,7 @@
|
|||||||
|
|
||||||
currentRelays[i] = null
|
currentRelays[i] = null
|
||||||
|
|
||||||
if (searching && user.getRelays().length > 0) {
|
if (searching && routing.getUserRelays().length > 0) {
|
||||||
searching = false
|
searching = false
|
||||||
modal = "success"
|
modal = "success"
|
||||||
|
|
||||||
|
@ -9,11 +9,9 @@
|
|||||||
import OnboardingRelays from "src/app/views/OnboardingRelays.svelte"
|
import OnboardingRelays from "src/app/views/OnboardingRelays.svelte"
|
||||||
import OnboardingFollows from "src/app/views/OnboardingFollows.svelte"
|
import OnboardingFollows from "src/app/views/OnboardingFollows.svelte"
|
||||||
import OnboardingNote from "src/app/views/OnboardingNote.svelte"
|
import OnboardingNote from "src/app/views/OnboardingNote.svelte"
|
||||||
import {DEFAULT_FOLLOWS, social} from "src/system"
|
import {DEFAULT_FOLLOWS, DEFAULT_RELAYS, social, routing} from "src/system"
|
||||||
import {getPubkeyWriteRelays, sampleRelays} from "src/agent/relays"
|
import {getPubkeyWriteRelays, sampleRelays} from "src/agent/relays"
|
||||||
import network from "src/agent/network"
|
import network from "src/agent/network"
|
||||||
import user from "src/agent/user"
|
|
||||||
import pool from "src/agent/pool"
|
|
||||||
import {keys, directory, cmd} from "src/system"
|
import {keys, directory, cmd} from "src/system"
|
||||||
import {loadAppData} from "src/app/state"
|
import {loadAppData} from "src/app/state"
|
||||||
import {modal} from "src/partials/state"
|
import {modal} from "src/partials/state"
|
||||||
@ -22,25 +20,21 @@
|
|||||||
|
|
||||||
const privkey = generatePrivateKey()
|
const privkey = generatePrivateKey()
|
||||||
const profile = {}
|
const profile = {}
|
||||||
const {relays} = user
|
|
||||||
|
|
||||||
if ($relays.length === 0) {
|
if (routing.getUserRelays().length === 0) {
|
||||||
user.updateRelays(() =>
|
routing.setUserRelays(DEFAULT_RELAYS.map(url => ({url, read: true, write: true})))
|
||||||
(pool.forceUrls.length > 0 ? pool.forceUrls : pool.defaultUrls).map(url => ({
|
|
||||||
url,
|
|
||||||
write: true,
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const signup = async note => {
|
const signup = async note => {
|
||||||
|
const relays = routing.getUserRelays()
|
||||||
|
|
||||||
await keys.login("privkey", privkey)
|
await keys.login("privkey", privkey)
|
||||||
|
|
||||||
// Re-save preferences now that we have a key
|
// Re-save preferences now that we have a key
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.updateRelays(() => user.getRelays()),
|
routing.setUserRelays(relays),
|
||||||
cmd.updateUser(profile).publish(user.getRelays()),
|
cmd.updateUser(profile).publish(relays),
|
||||||
note && cmd.createNote(note).publish(user.getRelays()),
|
note && cmd.createNote(note).publish(relays),
|
||||||
social.updatePetnames(
|
social.updatePetnames(
|
||||||
social.getUserFollows().map(pubkey => {
|
social.getUserFollows().map(pubkey => {
|
||||||
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
|
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
|
||||||
@ -60,7 +54,7 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Prime our database with some defaults
|
// Prime our database with some defaults
|
||||||
network.loadPeople(DEFAULT_FOLLOWS, {
|
network.loadPeople(DEFAULT_FOLLOWS, {
|
||||||
relays: sampleRelays(user.getRelays()),
|
relays: sampleRelays(routing.getUserRelays()),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,20 +9,21 @@
|
|||||||
import RelayCard from "src/app/shared/RelayCard.svelte"
|
import RelayCard from "src/app/shared/RelayCard.svelte"
|
||||||
import {routing} from "src/system"
|
import {routing} from "src/system"
|
||||||
import {watch} from "src/agent/db"
|
import {watch} from "src/agent/db"
|
||||||
import user from "src/agent/user"
|
|
||||||
|
|
||||||
const {relays} = user
|
|
||||||
|
|
||||||
let q = ""
|
let q = ""
|
||||||
let search
|
let search
|
||||||
|
|
||||||
|
const userRelays = watch(routing.policies, () => routing.getUserRelays())
|
||||||
const knownRelays = watch(routing.relays, () => routing.relays.all())
|
const knownRelays = watch(routing.relays, () => routing.relays.all())
|
||||||
|
|
||||||
$: joined = new Set(pluck("url", $relays))
|
$: {
|
||||||
$: search = fuzzy(
|
const joined = new Set(pluck("url", $userRelays))
|
||||||
$knownRelays.filter(r => !joined.has(r.url)),
|
|
||||||
{keys: ["name", "description", "url"]}
|
search = fuzzy(
|
||||||
)
|
$knownRelays.filter(r => !joined.has(r.url)),
|
||||||
|
{keys: ["name", "description", "url"]}
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Content>
|
<Content>
|
||||||
@ -44,14 +45,14 @@
|
|||||||
<i class="fa fa-server fa-lg" />
|
<i class="fa fa-server fa-lg" />
|
||||||
<h2 class="staatliches text-2xl">Your relays</h2>
|
<h2 class="staatliches text-2xl">Your relays</h2>
|
||||||
</div>
|
</div>
|
||||||
{#if $relays.length === 0}
|
{#if $userRelays.length === 0}
|
||||||
<div class="mt-8 flex items-center justify-center gap-2 text-center">
|
<div class="mt-8 flex items-center justify-center gap-2 text-center">
|
||||||
<i class="fa fa-triangle-exclamation" />
|
<i class="fa fa-triangle-exclamation" />
|
||||||
<span>No relays connected</span>
|
<span>No relays connected</span>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="grid grid-cols-1 gap-4">
|
<div class="grid grid-cols-1 gap-4">
|
||||||
{#each $relays as relay (relay.url)}
|
{#each $userRelays as relay (relay.url)}
|
||||||
<RelayCard {relay} />
|
<RelayCard {relay} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@ -67,7 +68,7 @@
|
|||||||
<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 - $userRelays.length, 50)}
|
||||||
of {$knownRelays.length - $relays.length} known relays
|
of {$knownRelays.length - $userRelays.length} known relays
|
||||||
</small>
|
</small>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
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/app/shared/RelayCard.svelte"
|
import RelayCard from "src/app/shared/RelayCard.svelte"
|
||||||
import user from "src/agent/user"
|
import {routing} from "src/system"
|
||||||
|
import {watch} from "src/agent/db"
|
||||||
import {modal} from "src/partials/state"
|
import {modal} from "src/partials/state"
|
||||||
|
|
||||||
const {relays} = user
|
const relays = watch(routing.policies, () => routing.getUserRelays())
|
||||||
|
|
||||||
document.title = "Relays"
|
document.title = "Relays"
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
import Heading from "src/partials/Heading.svelte"
|
import Heading from "src/partials/Heading.svelte"
|
||||||
import Compose from "src/partials/Compose.svelte"
|
import Compose from "src/partials/Compose.svelte"
|
||||||
import Rating from "src/partials/Rating.svelte"
|
import Rating from "src/partials/Rating.svelte"
|
||||||
import {cmd} from "src/system"
|
import {cmd, routing} from "src/system"
|
||||||
import user from "src/agent/user"
|
|
||||||
|
|
||||||
export let url
|
export let url
|
||||||
|
|
||||||
@ -27,7 +26,7 @@
|
|||||||
["r", url],
|
["r", url],
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.publish(user.getRelays())
|
.publish(routing.getUserRelays())
|
||||||
|
|
||||||
modal.pop()
|
modal.pop()
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import initRouting from "src/system/routing"
|
|||||||
import initCmd from "src/system/cmd"
|
import initCmd from "src/system/cmd"
|
||||||
import {getUserWriteRelays} from "src/agent/relays"
|
import {getUserWriteRelays} from "src/agent/relays"
|
||||||
import {default as agentSync} from "src/agent/sync"
|
import {default as agentSync} from "src/agent/sync"
|
||||||
|
import relays from "src/agent/relays"
|
||||||
import pool from "src/agent/pool"
|
import pool from "src/agent/pool"
|
||||||
import user from "src/agent/user"
|
import user from "src/agent/user"
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ const settings = initSettings({keys, sync, getCmd, getUserWriteRelays})
|
|||||||
const directory = initDirectory({sync, sortByGraph: social.sortByGraph})
|
const directory = initDirectory({sync, sortByGraph: social.sortByGraph})
|
||||||
const nip05 = initNip05({sync, sortByGraph: social.sortByGraph})
|
const nip05 = initNip05({sync, sortByGraph: social.sortByGraph})
|
||||||
const nip57 = initNip57({sync, sortByGraph: social.sortByGraph})
|
const nip57 = initNip57({sync, sortByGraph: social.sortByGraph})
|
||||||
const routing = initRouting({sync, sortByGraph: social.sortByGraph})
|
const routing = initRouting({keys, sync, getCmd, sortByGraph: social.sortByGraph})
|
||||||
const content = initContent({keys, sync, getCmd, getUserWriteRelays})
|
const content = initContent({keys, sync, getCmd, getUserWriteRelays})
|
||||||
const cmd = initCmd({keys, sync, pool, displayPubkey: directory.displayPubkey})
|
const cmd = initCmd({keys, sync, pool, displayPubkey: directory.displayPubkey})
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ settings.store.subscribe($settings => {
|
|||||||
|
|
||||||
user.ext.cmd = cmd
|
user.ext.cmd = cmd
|
||||||
pool.ext.routing = routing
|
pool.ext.routing = routing
|
||||||
|
relays.ext.routing = routing
|
||||||
|
|
||||||
// ===========================================================
|
// ===========================================================
|
||||||
// Initialization
|
// Initialization
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import {sortBy, last, inc} from "ramda"
|
import {sortBy, uniqBy, reject, whereEq, when, prop, last, inc} from "ramda"
|
||||||
|
import {get} from "svelte/store"
|
||||||
import {fuzzy, tryJson, now, fetchJson} from "src/util/misc"
|
import {fuzzy, tryJson, now, fetchJson} from "src/util/misc"
|
||||||
import {warn} from "src/util/logger"
|
import {warn} from "src/util/logger"
|
||||||
import {normalizeRelayUrl, isShareableRelay} from "src/util/nostr"
|
import {normalizeRelayUrl, isShareableRelay, Tags} from "src/util/nostr"
|
||||||
import {DUFFLEPUD_URL, DEFAULT_RELAYS, FORCE_RELAYS} from "src/system/env"
|
import {DUFFLEPUD_URL, DEFAULT_RELAYS, FORCE_RELAYS} from "src/system/env"
|
||||||
import {Table, watch} from "src/agent/db"
|
import {Table, watch} from "src/agent/db"
|
||||||
|
|
||||||
export default ({sync, sortByGraph}) => {
|
export default ({keys, sync, getCmd, sortByGraph}) => {
|
||||||
const relays = new Table("routing/relays", "url", {sort: sortBy(e => -e.count)})
|
const relays = new Table("routing/relays", "url", {sort: sortBy(e => -e.count)})
|
||||||
const relaySelections = new Table("routing/relaySelections", "pubkey", {sort: sortByGraph})
|
const policies = new Table("routing/policies", "pubkey", {sort: sortByGraph})
|
||||||
|
|
||||||
const addRelay = url => {
|
const addRelay = url => {
|
||||||
const relay = relays.get(url)
|
const relay = relays.get(url)
|
||||||
@ -22,16 +23,21 @@ export default ({sync, sortByGraph}) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addPolicies = ({pubkey, created_at}, policies) => {
|
const setPolicy = ({pubkey, created_at}, relays) => {
|
||||||
if (policies?.length > 0) {
|
if (relays?.length > 0) {
|
||||||
const selection = relaySelections.get(pubkey)
|
if (created_at < policies.get(pubkey)?.created_at) {
|
||||||
|
|
||||||
if (created_at < selection?.created_at) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
policies.forEach(({url}) => addRelay(url))
|
policies.patch({
|
||||||
relaySelections.patch({pubkey, created_at, policies})
|
pubkey,
|
||||||
|
created_at,
|
||||||
|
relays: uniqBy(prop("url"), relays).map(relay => {
|
||||||
|
addRelay(relay.url)
|
||||||
|
|
||||||
|
return {read: true, write: true, ...relay}
|
||||||
|
}),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +48,7 @@ export default ({sync, sortByGraph}) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
sync.addHandler(3, e => {
|
sync.addHandler(3, e => {
|
||||||
addPolicies(
|
setPolicy(
|
||||||
e,
|
e,
|
||||||
tryJson(() => {
|
tryJson(() => {
|
||||||
Object.entries(JSON.parse(e.content || ""))
|
Object.entries(JSON.parse(e.content || ""))
|
||||||
@ -60,18 +66,21 @@ export default ({sync, sortByGraph}) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
sync.addHandler(10002, e => {
|
sync.addHandler(10002, e => {
|
||||||
addPolicies(
|
setPolicy(
|
||||||
e,
|
e,
|
||||||
e.tags.map(([_, url, mode = "read"]) => {
|
Tags.from(e)
|
||||||
const write = mode === "write"
|
.type("r")
|
||||||
const read = mode === "read"
|
.all()
|
||||||
|
.map(([_, url, mode]) => {
|
||||||
|
const write = !mode || mode === "write"
|
||||||
|
const read = !mode || mode === "read"
|
||||||
|
|
||||||
if (!write && !read) {
|
if (!write && !read) {
|
||||||
warn(`Encountered unknown relay mode: ${mode}`)
|
warn(`Encountered unknown relay mode: ${mode}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {url: normalizeRelayUrl(url), write, read}
|
return {url: normalizeRelayUrl(url), write, read}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -83,6 +92,32 @@ export default ({sync, sortByGraph}) => {
|
|||||||
|
|
||||||
const displayRelay = ({url}) => last(url.split("://"))
|
const displayRelay = ({url}) => last(url.split("://"))
|
||||||
|
|
||||||
|
const getPubkeyRelays = (pubkey, mode = null) => {
|
||||||
|
const relays = policies.get(pubkey)?.relays || []
|
||||||
|
|
||||||
|
return mode ? relays.filter(prop(mode)) : relays
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserKey = () => keys.getPubkey() || "anonymous"
|
||||||
|
|
||||||
|
const getUserRelays = (...args) => getPubkeyRelays(getUserKey(), ...args)
|
||||||
|
|
||||||
|
const setUserRelays = relays => {
|
||||||
|
if (get(keys.canSign)) {
|
||||||
|
return getCmd().setRelays(relays).publish(relays)
|
||||||
|
} else {
|
||||||
|
setPolicy({pubkey: getUserKey(), created_at: now()}, relays)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addUserRelay = url => setUserRelays(getUserRelays().concat({url}))
|
||||||
|
|
||||||
|
const removeUserRelay = url =>
|
||||||
|
setUserRelays(reject(whereEq({url: normalizeRelayUrl(url)}), getUserRelays()))
|
||||||
|
|
||||||
|
const setUserRelayPolicy = (url, policy) =>
|
||||||
|
setUserRelays(getUserRelays().map(when(whereEq({url}), p => ({...p, ...policy}))))
|
||||||
|
|
||||||
const initialize = async () => {
|
const initialize = async () => {
|
||||||
// Throw some hardcoded defaults in there
|
// Throw some hardcoded defaults in there
|
||||||
DEFAULT_RELAYS.forEach(addRelay)
|
DEFAULT_RELAYS.forEach(addRelay)
|
||||||
@ -101,11 +136,18 @@ export default ({sync, sortByGraph}) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
relays,
|
relays,
|
||||||
relaySelections,
|
policies,
|
||||||
getRelay,
|
getRelay,
|
||||||
getRelayMeta,
|
getRelayMeta,
|
||||||
searchRelays,
|
searchRelays,
|
||||||
displayRelay,
|
displayRelay,
|
||||||
|
getPubkeyRelays,
|
||||||
|
getUserKey,
|
||||||
|
getUserRelays,
|
||||||
|
setUserRelays,
|
||||||
|
addUserRelay,
|
||||||
|
removeUserRelay,
|
||||||
|
setUserRelayPolicy,
|
||||||
initialize,
|
initialize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,19 +249,7 @@ export const hsl = (hue, {saturation = 100, lightness = 50, opacity = 1} = {}) =
|
|||||||
`hsl(${hue}, ${saturation}%, ${lightness}%, ${opacity})`
|
`hsl(${hue}, ${saturation}%, ${lightness}%, ${opacity})`
|
||||||
|
|
||||||
export const tryFunc = (f, ignore = null) => {
|
export const tryFunc = (f, ignore = null) => {
|
||||||
try {
|
const onError = e => {
|
||||||
const r = f()
|
|
||||||
|
|
||||||
if (is(Promise, r)) {
|
|
||||||
return r.catch(e => {
|
|
||||||
if (!ignore || !e.toString().includes(ignore)) {
|
|
||||||
warn(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (ignore === false) {
|
if (ignore === false) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -272,6 +260,18 @@ export const tryFunc = (f, ignore = null) => {
|
|||||||
|
|
||||||
warn(e)
|
warn(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const r = f()
|
||||||
|
|
||||||
|
if (is(Promise, r)) {
|
||||||
|
return r.catch(onError)
|
||||||
|
} else {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
onError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tryJson = f => tryFunc(f, "JSON")
|
export const tryJson = f => tryFunc(f, "JSON")
|
||||||
|
Loading…
Reference in New Issue
Block a user