flotilla/src/app/commands.ts

109 lines
3 KiB
TypeScript
Raw Normal View History

2024-09-11 18:09:25 +00:00
import {uniqBy, sleep, chunk, equals, choice} from "@welshman/lib"
import {getPubkeyTagValues, createEvent, displayProfile} from "@welshman/util"
import type {SubscribeRequestWithHandlers} from "@welshman/net"
2024-08-16 22:17:30 +00:00
import {
2024-08-30 23:25:41 +00:00
pubkey,
repository,
makeThunk,
publishThunk,
2024-08-16 22:17:30 +00:00
loadProfile,
2024-08-30 23:25:41 +00:00
profilesByPubkey,
relaySelectionsByPubkey,
getWriteRelayUrls,
2024-08-16 22:17:30 +00:00
loadFollows,
loadMutes,
2024-09-24 23:30:32 +00:00
getFollows,
2024-08-30 23:25:41 +00:00
} from "@welshman/app"
2024-09-23 17:28:33 +00:00
import {ROOM, MEMBERSHIPS, INDEXER_RELAYS} from "@app/state"
2024-08-16 19:42:00 +00:00
2024-08-23 20:33:36 +00:00
// Utils
export const getPubkeyHints = (pubkey: string) => {
2024-08-30 23:25:41 +00:00
const selections = relaySelectionsByPubkey.get().get(pubkey)
2024-08-23 20:33:36 +00:00
const relays = selections ? getWriteRelayUrls(selections) : []
const hints = relays.length ? relays : INDEXER_RELAYS
return hints
}
export const getPubkeyPetname = (pubkey: string) => {
2024-08-30 23:25:41 +00:00
const profile = profilesByPubkey.get().get(pubkey)
2024-08-23 20:33:36 +00:00
const display = displayProfile(profile)
return display
}
2024-08-26 21:43:43 +00:00
export const makeMention = (pubkey: string, hints?: string[]) => [
"p",
pubkey,
choice(hints || getPubkeyHints(pubkey)),
getPubkeyPetname(pubkey),
]
2024-08-23 20:33:36 +00:00
2024-08-26 21:43:43 +00:00
export const makeIMeta = (url: string, data: Record<string, string>) => [
"imeta",
`url ${url}`,
...Object.entries(data).map(([k, v]) => [k, v].join(" ")),
]
2024-08-23 20:33:36 +00:00
// Loaders
2024-09-11 18:09:25 +00:00
export const loadUserData = (
pubkey: string,
request: Partial<SubscribeRequestWithHandlers> = {},
) => {
const promise = Promise.all([
loadProfile(pubkey, request),
loadFollows(pubkey, request),
loadMutes(pubkey, request),
])
// Load followed profiles slowly in the background without clogging other stuff up
promise.then(async () => {
2024-09-24 23:30:32 +00:00
for (const pubkeys of chunk(50, getFollows(pubkey))) {
2024-09-11 18:09:25 +00:00
await sleep(300)
for (const pubkey of pubkeys) {
loadProfile(pubkey)
2024-09-24 23:30:32 +00:00
loadFollows(pubkey)
loadMutes(pubkey)
2024-09-11 18:09:25 +00:00
}
}
})
return promise
}
2024-08-14 23:25:36 +00:00
2024-08-23 20:33:36 +00:00
// Updates
2024-08-14 23:25:36 +00:00
export type ModifyTags = (tags: string[][]) => string[][]
export const updateList = async (kind: number, modifyTags: ModifyTags) => {
2024-08-30 23:25:41 +00:00
const $pubkey = pubkey.get()!
const [prev] = repository.query([{kinds: [kind], authors: [$pubkey]}])
const relays = getWriteRelayUrls(relaySelectionsByPubkey.get().get($pubkey))
2024-08-14 23:25:36 +00:00
2024-08-16 23:39:35 +00:00
// Preserve content if we have it
const event = prev
? {...prev, tags: modifyTags(prev.tags)}
: createEvent(kind, {tags: modifyTags([])})
2024-08-14 23:25:36 +00:00
2024-08-16 23:39:35 +00:00
publishThunk(makeThunk({event, relays}))
2024-08-14 23:25:36 +00:00
}
export const addSpaceMembership = (url: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => uniqBy(t => t.join(""), [...tags, ["r", url]]))
2024-08-23 20:33:36 +00:00
2024-09-23 17:28:33 +00:00
export const addRoomMembership = (url: string, room: string) =>
2024-09-11 18:09:25 +00:00
updateList(MEMBERSHIPS, (tags: string[][]) =>
2024-09-23 17:28:33 +00:00
uniqBy(t => t.join(""), [...tags, [ROOM, room, url]]),
2024-09-11 18:09:25 +00:00
)
2024-08-23 21:42:50 +00:00
export const removeSpaceMembership = (url: string) =>
2024-09-11 18:09:25 +00:00
updateList(MEMBERSHIPS, (tags: string[][]) =>
tags.filter(t => !equals(["r", url], t) && t[2] !== url),
)
2024-08-23 21:42:50 +00:00
2024-09-23 17:28:33 +00:00
export const removeRoomMembership = (url: string, room: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals([ROOM, room, url], t)))