You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
5.7 KiB
217 lines
5.7 KiB
import { NDKRelaySet, type NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk' |
|
import { writable, type Unsubscriber, type Writable } from 'svelte/store' |
|
import { ndk } from './ndk' |
|
import { isPRStatus, summary_defaults } from '$lib/components/prs/type' |
|
import type { User } from '$lib/components/users/type' |
|
import { ensureUser } from './users' |
|
import type { PRStatus, PRSummaries } from '$lib/components/prs/type' |
|
import { ensureSelectedRepo } from './repo' |
|
import { patch_kind, pr_kind, pr_status_kind, repo_kind } from '$lib/kinds' |
|
import type { Repo } from '$lib/components/repo/type' |
|
import { extractPatchMessage } from '$lib/components/events/content/utils' |
|
|
|
export const pr_summaries: Writable<PRSummaries> = writable({ |
|
id: '', |
|
summaries: [], |
|
loading: false, |
|
}) |
|
|
|
let selected_repo_id: string = '' |
|
|
|
let authors_unsubscribers: Unsubscriber[] = [] |
|
|
|
let sub: NDKSubscription |
|
|
|
export const ensurePRSummaries = async (repo_id: string) => { |
|
if (selected_repo_id == repo_id) return |
|
pr_summaries.set({ |
|
id: repo_id, |
|
summaries: [], |
|
loading: repo_id !== '', |
|
}) |
|
|
|
if (sub) sub.stop() |
|
if (sub_statuses) sub_statuses.stop() |
|
authors_unsubscribers.forEach((u) => u()) |
|
authors_unsubscribers = [] |
|
|
|
selected_repo_id = repo_id |
|
|
|
const repo = await ensureSelectedRepo(repo_id) |
|
|
|
sub = ndk.subscribe( |
|
[ |
|
{ |
|
kinds: [pr_kind], |
|
'#a': repo.maintainers.map( |
|
(m) => `${repo_kind}:${m.hexpubkey}:${repo.repo_id}` |
|
), |
|
limit: 50, |
|
}, |
|
{ |
|
kinds: [patch_kind], |
|
'#a': repo.maintainers.map( |
|
(m) => `${repo_kind}:${m.hexpubkey}:${repo.repo_id}` |
|
), |
|
'#t': ['root'], |
|
limit: 50, |
|
}, |
|
], |
|
{ |
|
closeOnEose: true, |
|
}, |
|
repo.relays.length > 0 |
|
? NDKRelaySet.fromRelayUrls(repo.relays, ndk) |
|
: undefined |
|
) |
|
|
|
sub.on('event', (event: NDKEvent) => { |
|
try { |
|
if (event.kind == patch_kind && event.content.length > 0) { |
|
pr_summaries.update((prs) => { |
|
return { |
|
...prs, |
|
summaries: [ |
|
...prs.summaries, |
|
{ |
|
...summary_defaults, |
|
id: event.id, |
|
repo_id: repo_id, |
|
title: ( |
|
event.tagValue('name') || |
|
event.tagValue('description') || |
|
extractPatchMessage(event.content) || |
|
'' |
|
).split('\n')[0], |
|
descritpion: event.tagValue('description') || '', |
|
created_at: event.created_at, |
|
comments: 0, |
|
author: { |
|
hexpubkey: event.pubkey, |
|
loading: true, |
|
npub: '', |
|
}, |
|
loading: false, |
|
}, |
|
], |
|
} |
|
}) |
|
} |
|
if (event.kind == pr_kind) { |
|
pr_summaries.update((prs) => { |
|
return { |
|
...prs, |
|
summaries: [ |
|
...prs.summaries, |
|
{ |
|
...summary_defaults, |
|
id: event.id, |
|
repo_id: repo_id, |
|
title: event.tagValue('name') || '', |
|
descritpion: event.tagValue('description') || '', |
|
created_at: event.created_at, |
|
comments: 0, |
|
author: { |
|
hexpubkey: event.pubkey, |
|
loading: true, |
|
npub: '', |
|
}, |
|
loading: false, |
|
}, |
|
], |
|
} |
|
}) |
|
} |
|
|
|
authors_unsubscribers.push( |
|
ensureUser(event.pubkey).subscribe((u: User) => { |
|
pr_summaries.update((prs) => { |
|
return { |
|
...prs, |
|
summaries: prs.summaries.map((o) => ({ |
|
...o, |
|
author: event.pubkey === o.author.hexpubkey ? u : o.author, |
|
})), |
|
} |
|
}) |
|
}) |
|
) |
|
} catch {} |
|
}) |
|
sub.on('eose', () => { |
|
pr_summaries.update((prs) => { |
|
getAndUpdatePRStatus(prs, repo) |
|
return { |
|
...prs, |
|
loading: false, |
|
} |
|
}) |
|
}) |
|
} |
|
|
|
let sub_statuses: NDKSubscription |
|
|
|
function getAndUpdatePRStatus(prs: PRSummaries, repo: Repo): void { |
|
if (sub_statuses) sub_statuses.stop() |
|
sub_statuses = ndk.subscribe( |
|
{ |
|
kinds: [pr_status_kind], |
|
'#e': prs.summaries.map((pr) => pr.id), |
|
'#r': [`r-${prs.id}`], |
|
}, |
|
{ |
|
closeOnEose: false, |
|
}, |
|
NDKRelaySet.fromRelayUrls(repo.relays, ndk) |
|
) |
|
sub_statuses.on('event', (event: NDKEvent) => { |
|
const tagged_pr_event = event.tagValue('e') |
|
if ( |
|
event.kind == pr_status_kind && |
|
tagged_pr_event && |
|
event.created_at && |
|
event.getMatchingTags('l').length === 1 && |
|
event.getMatchingTags('l')[0].length > 1 |
|
) { |
|
const potential_status = event.getMatchingTags('l')[0][1] |
|
|
|
if (isPRStatus(potential_status)) { |
|
pr_summaries.update((prs) => { |
|
return { |
|
...prs, |
|
summaries: prs.summaries.map((o) => { |
|
if ( |
|
o.id === tagged_pr_event && |
|
event.created_at && |
|
o.status_date < event.created_at |
|
) { |
|
return { |
|
...o, |
|
status: potential_status as PRStatus, |
|
status_date: event.created_at, |
|
} |
|
} |
|
|
|
return o |
|
}), |
|
} |
|
}) |
|
} |
|
} |
|
}) |
|
|
|
sub_statuses.on('eose', () => { |
|
pr_summaries.update((prs) => { |
|
return { |
|
...prs, |
|
summaries: prs.summaries.map((o) => ({ |
|
...o, |
|
status: o.status || 'Open', |
|
})), |
|
} |
|
}) |
|
}) |
|
} |
|
function extractTagContent(arg0: string): string { |
|
throw new Error('Function not implemented.') |
|
}
|
|
|