flotilla/src/app/commands.ts

120 lines
3.4 KiB
TypeScript
Raw Normal View History

2024-08-23 20:33:36 +00:00
import {uniqBy, uniq, now, choice} from "@welshman/lib"
2024-08-16 22:17:30 +00:00
import {
GROUPS,
2024-08-23 20:33:36 +00:00
GROUP_JOIN,
2024-08-16 22:17:30 +00:00
getGroupTags,
getRelayTagValues,
2024-08-16 23:39:35 +00:00
createEvent,
2024-08-23 20:33:36 +00:00
displayProfile,
2024-08-16 22:17:30 +00:00
} from "@welshman/util"
2024-08-23 21:42:50 +00:00
import {PublishStatus} from "@welshman/net"
2024-08-26 21:43:43 +00:00
import {pk, repository, INDEXER_RELAYS} from "@app/base"
2024-08-16 22:17:30 +00:00
import {
2024-08-23 21:42:50 +00:00
loadOne,
2024-08-16 22:17:30 +00:00
getWriteRelayUrls,
loadGroup,
loadGroupMembership,
loadProfile,
loadFollows,
loadMutes,
2024-08-16 23:39:35 +00:00
getRelaySelectionsByPubkey,
2024-08-16 22:17:30 +00:00
loadRelaySelections,
2024-08-16 23:39:35 +00:00
makeThunk,
publishThunk,
2024-08-23 20:33:36 +00:00
getProfilesByPubkey,
2024-08-16 22:17:30 +00:00
} 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) => {
const selections = getRelaySelectionsByPubkey().get(pubkey)
const relays = selections ? getWriteRelayUrls(selections) : []
const hints = relays.length ? relays : INDEXER_RELAYS
return hints
}
export const getPubkeyPetname = (pubkey: string) => {
const profile = getProfilesByPubkey().get(pubkey)
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-08-16 19:42:00 +00:00
export const loadUserData = async (pubkey: string, hints: string[] = []) => {
const relaySelections = await loadRelaySelections(pubkey, INDEXER_RELAYS)
2024-08-16 22:17:30 +00:00
const relays = uniq([
...getRelayTagValues(relaySelections?.tags || []),
...INDEXER_RELAYS,
...hints,
])
2024-08-16 19:42:00 +00:00
const membership = await loadGroupMembership(pubkey, relays)
const promises = [
loadProfile(pubkey, relays),
loadFollows(pubkey, relays),
loadMutes(pubkey, relays),
]
for (const [_, nom, url] of getGroupTags(membership?.event.tags || [])) {
promises.push(loadGroup(nom, [url]))
}
await Promise.all(promises)
}
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) => {
const $pk = pk.get()!
const [prev] = repository.query([{kinds: [kind], authors: [$pk]}])
2024-08-19 17:26:25 +00:00
const relays = getWriteRelayUrls(getRelaySelectionsByPubkey().get($pk))
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
}
2024-08-16 17:50:38 +00:00
export const addGroupMemberships = (newTags: string[][]) =>
updateList(GROUPS, (tags: string[][]) => uniqBy(t => t.join(""), [...tags, ...newTags]))
export const removeGroupMemberships = (noms: string[]) =>
updateList(GROUPS, (tags: string[][]) => tags.filter(t => !noms.includes(t[1])))
2024-08-23 20:33:36 +00:00
2024-08-23 21:42:50 +00:00
export const sendJoinRequest = async (nom: string, url: string): Promise<[boolean, string]> => {
const relays = [url]
2024-08-26 21:43:43 +00:00
const filters = [{kinds: [9000], "#h": [nom], "#p": [pk.get()!], since: now() - 30}]
2024-08-23 21:42:50 +00:00
2024-08-23 20:33:36 +00:00
const event = createEvent(GROUP_JOIN, {tags: [["h", nom]]})
2024-08-23 21:42:50 +00:00
const statusData = await publishThunk(makeThunk({event, relays}))
const {status, message} = statusData[url]
2024-08-26 21:43:43 +00:00
if (message.includes("already a member")) return [true, ""]
2024-08-23 21:42:50 +00:00
if (status !== PublishStatus.Success) return [false, message]
if (await loadOne({filters, relays})) return [true, ""]
2024-08-23 20:33:36 +00:00
2024-08-26 21:43:43 +00:00
return [
false,
"Your request was not automatically approved, but may be approved manually later. Please try again later or contact the group admin.",
]
2024-08-23 20:33:36 +00:00
}