import { didFromUri, rkeyFromUri } from "$lib/api/uri"; import type { NetworkVouchItem, VouchKind } from "$lib/api/graph"; import type { DirectVouch } from "$lib/components/profile/types"; export interface VouchRelationship { viewer: string; actor: string; vouches: readonly NetworkVouchItem[]; } export type VouchBadgeState = "direct-vouch" | "direct-denounce" | "mixed" | "indirect-vouch" | "indirect-denounce"; const incoming = ({ actor, vouches }: VouchRelationship) => vouches.filter((vouch) => rkeyFromUri(vouch.uri) === actor); const hasKind = (vouches: readonly NetworkVouchItem[], kind: VouchKind) => vouches.some((vouch) => vouch.value.kind === kind); export const isDirectVouch = (relationship: VouchRelationship): boolean => incoming(relationship).some( (vouch) => didFromUri(vouch.uri) === relationship.viewer && vouch.value.kind === "vouch" ); export const isDirectDenounce = (relationship: VouchRelationship): boolean => incoming(relationship).some( (vouch) => didFromUri(vouch.uri) === relationship.viewer && vouch.value.kind === "denounce" ); export const indirectVouches = (relationship: VouchRelationship): NetworkVouchItem[] => incoming(relationship).filter((vouch) => didFromUri(vouch.uri) !== relationship.viewer); export const isMixed = (relationship: VouchRelationship): boolean => { if (isDirectVouch(relationship) || isDirectDenounce(relationship)) return false; const vouches = indirectVouches(relationship); return hasKind(vouches, "vouch") && hasKind(vouches, "denounce"); }; export const isIndirectVouch = (relationship: VouchRelationship): boolean => !isDirectVouch(relationship) && !isDirectDenounce(relationship) && hasKind(indirectVouches(relationship), "vouch"); export const isIndirectDenounce = (relationship: VouchRelationship): boolean => !isDirectVouch(relationship) && !isDirectDenounce(relationship) && hasKind(indirectVouches(relationship), "denounce"); export const vouchStrength = (relationship: VouchRelationship): number => indirectVouches(relationship).filter((vouch) => vouch.value.kind === "vouch").length; export const denounceStrength = (relationship: VouchRelationship): number => indirectVouches(relationship).filter((vouch) => vouch.value.kind === "denounce").length; export const directVouch = (relationship: VouchRelationship): DirectVouch | null => { const own = incoming(relationship).find( (vouch) => didFromUri(vouch.uri) === relationship.viewer ); return own ? { kind: own.value.kind === "denounce" ? "denounce" : "vouch", reason: own.value.reason } : null; }; export const vouchBadgeState = (relationship: VouchRelationship): VouchBadgeState | null => { if (isDirectVouch(relationship)) return "direct-vouch"; if (isDirectDenounce(relationship)) return "direct-denounce"; if (isMixed(relationship)) return "mixed"; if (isIndirectVouch(relationship)) return "indirect-vouch"; if (isIndirectDenounce(relationship)) return "indirect-denounce"; return null; };