forked from coracle/flotilla
90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import {
|
|
REPORT,
|
|
ROOM_ADD_MEMBER,
|
|
ROOM_JOIN,
|
|
ROOM_LEAVE,
|
|
ROOM_MEMBERS,
|
|
ROOM_REMOVE_MEMBER,
|
|
getPubkeyTagValues,
|
|
getTagValue,
|
|
sortEventsDesc,
|
|
} from "@welshman/util"
|
|
import type {TrustedEvent} from "@welshman/util"
|
|
import {first, groupBy, removeUndefined} from "@welshman/lib"
|
|
import {derived} from "svelte/store"
|
|
import {deriveEventsForUrl} from "@app/repository"
|
|
import {getRoomMembers} from "@app/members"
|
|
// Action items (admin review queue)
|
|
|
|
export const deriveSpaceActionItems = (url: string) =>
|
|
derived(
|
|
deriveEventsForUrl(url, [
|
|
{
|
|
kinds: [REPORT, ROOM_JOIN, ROOM_LEAVE, ROOM_MEMBERS, ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER],
|
|
},
|
|
]),
|
|
$events => {
|
|
const getRoomId = (e: TrustedEvent) =>
|
|
getTagValue(e.kind === ROOM_MEMBERS ? "d" : "h", e.tags)
|
|
const reports = $events.filter(e => e.kind === REPORT)
|
|
const pendingJoins: TrustedEvent[] = []
|
|
|
|
// Room-level join requests — most recent per pubkey+h
|
|
for (const [h, roomEvents] of groupBy(getRoomId, $events)) {
|
|
if (!h) continue
|
|
|
|
const roomJoins: TrustedEvent[] = []
|
|
const roomLeaves: TrustedEvent[] = []
|
|
const roomMembershipEvents: TrustedEvent[] = []
|
|
|
|
for (const event of roomEvents) {
|
|
switch (event.kind) {
|
|
case ROOM_JOIN:
|
|
roomJoins.push(event)
|
|
break
|
|
case ROOM_LEAVE:
|
|
roomLeaves.push(event)
|
|
break
|
|
case ROOM_MEMBERS:
|
|
case ROOM_ADD_MEMBER:
|
|
case ROOM_REMOVE_MEMBER:
|
|
roomMembershipEvents.push(event)
|
|
break
|
|
}
|
|
}
|
|
|
|
const roomMembers = new Set(getRoomMembers(url, h, roomMembershipEvents))
|
|
|
|
pendingJoins.push(
|
|
...removeUndefined(
|
|
Array.from(groupBy(e => e.pubkey, roomJoins).values()).map(events =>
|
|
first(sortEventsDesc(events)),
|
|
),
|
|
).filter(({pubkey, created_at}) => {
|
|
if (roomMembers.has(pubkey)) return false
|
|
if (
|
|
roomMembershipEvents.some(event => {
|
|
if (event.created_at <= created_at) {
|
|
return false
|
|
}
|
|
|
|
if (event.kind === ROOM_MEMBERS) {
|
|
return true
|
|
}
|
|
|
|
return getPubkeyTagValues(event.tags).includes(pubkey)
|
|
})
|
|
) {
|
|
return false
|
|
}
|
|
if (roomLeaves.some(e => e.pubkey === pubkey && e.created_at > created_at)) return false
|
|
|
|
return true
|
|
}),
|
|
)
|
|
}
|
|
|
|
return sortEventsDesc([...reports, ...pendingJoins])
|
|
},
|
|
)
|