Refine board notes, clipping evidence, and case reports
This commit is contained in:
@@ -5,18 +5,6 @@ import type { CaseReport, CaseReportEvidence, CaseReportSubmissionInput, CaseRep
|
||||
type LevelRef = { id:string; board_id:string }
|
||||
|
||||
function trimmed(value: unknown, max: number) { return String(value || '').trim().slice(0,max) }
|
||||
function optionalUrl(value: unknown) {
|
||||
const candidate = trimmed(value,2_000)
|
||||
if (!candidate) return null
|
||||
try { return new URL(candidate).toString() } catch { throw new Error('Source links must be absolute URLs') }
|
||||
}
|
||||
function optionalTimestamp(value: unknown) {
|
||||
const candidate = trimmed(value,100)
|
||||
if (!candidate) return null
|
||||
const date = new Date(candidate)
|
||||
if (!Number.isFinite(date.getTime())) throw new Error('Evidence dates must be valid dates')
|
||||
return date.toISOString()
|
||||
}
|
||||
function unfinishedRelation(value: string) {
|
||||
return !value.trim() || /^proof\s+that(?:\s*(?:…|\.{3}))?\s*$/iu.test(value.trim())
|
||||
}
|
||||
@@ -130,29 +118,6 @@ export async function submitCaseReport(pool: Pool, levelSlug: string, rawInput:
|
||||
const report = (await client.query<{ board_id:string }>('SELECT board_id FROM osint.case_reports WHERE board_id=$1 FOR UPDATE', [level.board_id])).rows[0]
|
||||
if (!report) throw new Error('This level does not have a case report')
|
||||
const investigatorName = trimmed(rawInput?.investigatorName,300) || 'Player'
|
||||
const drafts = Array.isArray(rawInput?.evidence) ? rawInput.evidence.slice(0,100) : []
|
||||
if (new Set(drafts.map(item => item.connectionId)).size !== drafts.length) throw new Error('A report cannot submit the same connection twice')
|
||||
for (const draft of drafts) {
|
||||
const relationText = trimmed(draft.relationText,2_000)
|
||||
const sourceCitation = trimmed(draft.sourceCitation,1_000)
|
||||
const sourceUri = optionalUrl(draft.sourceUri)
|
||||
const publishedAt = optionalTimestamp(draft.publishedAt)
|
||||
const owned = (await client.query<{ connection_id:string; document_id:string }>(`SELECT connection.id AS connection_id,document.exhibit_id AS document_id
|
||||
FROM osint.exhibit_connections connection
|
||||
JOIN osint.claim_exhibits claim ON claim.exhibit_id=CASE
|
||||
WHEN connection.from_exhibit_id=$3 THEN connection.to_exhibit_id ELSE connection.from_exhibit_id END
|
||||
JOIN osint.document_exhibits document ON document.exhibit_id=CASE
|
||||
WHEN connection.from_exhibit_id=$3 THEN connection.from_exhibit_id ELSE connection.to_exhibit_id END
|
||||
WHERE connection.id=$1 AND connection.board_id=$2
|
||||
AND $3::uuid IN (connection.from_exhibit_id,connection.to_exhibit_id)`, [draft.connectionId,level.board_id,draft.documentExhibitId])).rows[0]
|
||||
if (!owned || owned.document_id !== draft.documentExhibitId) throw new Error('Report evidence must reference a claim-to-document connection on this board')
|
||||
await client.query('UPDATE osint.exhibit_connections SET label=$2 WHERE id=$1', [draft.connectionId,relationText || null])
|
||||
await client.query(`UPDATE osint.document_exhibits SET published_at=$2,citation_text=$3,source_uri=$4 WHERE exhibit_id=$1`,
|
||||
[draft.documentExhibitId,publishedAt,sourceCitation,sourceUri])
|
||||
await client.query(`INSERT INTO osint.exhibit_citations (board_id,exhibit_id,display_number)
|
||||
SELECT $1,$2,COALESCE(MAX(display_number),0)+1 FROM osint.exhibit_citations WHERE board_id=$1
|
||||
ON CONFLICT (board_id,exhibit_id) DO NOTHING`, [level.board_id,draft.documentExhibitId])
|
||||
}
|
||||
await client.query('UPDATE osint.case_reports SET investigator_name=$2,updated_at=NOW() WHERE board_id=$1', [level.board_id,investigatorName])
|
||||
const assembled = (await loadCaseReport(client,level))!
|
||||
const pendingGoals = Number((await client.query<{ count:string }>(`SELECT COUNT(*)::text AS count FROM osint.level_goals goal
|
||||
|
||||
Reference in New Issue
Block a user