Skip to content

Commit

Permalink
feat: allow /thread to be used in completed threads (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullishamy authored Jul 2, 2023
1 parent fc162a5 commit 2fe10ae
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 8 deletions.
27 changes: 25 additions & 2 deletions src/commands/thread.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import assert from 'assert'
import { ChannelType, ThreadChannel } from 'discord.js'
import { SlashCommand, SlashCreator, CommandContext } from 'slash-create'
import { commandLog } from '../communication/interaction'
Expand All @@ -6,7 +7,7 @@ import {
updateFeedbackThreadId,
validatePendingSubmission
} from '../db/submission'
import { fetchSubmissionForContext } from '../utils/commands'
import { fetchAnySubmissionForContext } from '../utils/commands'
import { getAssignedGuilds } from '../utils/discordUtils'
import { runCatching } from '../utils/request'

Expand All @@ -21,14 +22,17 @@ export default class ThreadCommand extends SlashCommand {
}

async run (ctx: CommandContext): Promise<void> {
const submission = await fetchSubmissionForContext(ctx)
const submission = await fetchAnySubmissionForContext(ctx)

if (!submission) {
return
}

let existingThread: ThreadChannel | undefined

// Running commands in a thread with a raw submission should be impossible
assert(submission.state !== 'RAW', 'submission was in raw state')

if (submission.state === 'ERROR') {
commandLog.warning({
type: 'text',
Expand All @@ -39,6 +43,21 @@ export default class ThreadCommand extends SlashCommand {
return
}

if (submission.state === 'ACCEPTED' || submission.state === 'DENIED') {
const { feedbackThread } = submission
if (!feedbackThread) {
commandLog.warning({
type: 'text',
content:
'Cannot add you, no thread exists.',
ctx
})
return
}

existingThread = feedbackThread
}

if (submission.state === 'PROCESSING' || submission.state === 'PAUSED') {
// Allow thread creation in paused state, as reviewers may need to contact submitters about warnings
existingThread = submission.feedbackThread
Expand Down Expand Up @@ -85,6 +104,10 @@ export default class ThreadCommand extends SlashCommand {
}),
'rethrow'
)

// We checked for the states above, this just lets TS infer it so we don't have any casting.
assert(submission.state === 'PROCESSING' || submission.state === 'PAUSED' || submission.state === 'WARNING', 'impossible')

await updateFeedbackThreadId(submission, feedbackThread.id)

await runCatching(
Expand Down
16 changes: 14 additions & 2 deletions src/db/submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ export async function fetchSubmissionByMessageId (
// from button votes, whereby the author must exist
const author = await fetchAuthor(data.authorId)

// May or may not exist, do not abort if it does not
let feedbackThread
if (data.feedbackThreadId) {
try {
feedbackThread = await fetchFeedbackThread(data.feedbackThreadId)
} catch {
logger.warn(`Feedback thread for submission (message ID ${id}) did not exist`)
}
}

const completed: CompletedSubmission = {
...data,
state: data.state,
Expand All @@ -221,7 +231,8 @@ export async function fetchSubmissionByMessageId (
source: data.sourceLinks,
other: data.otherLinks
},
author
author,
feedbackThread
}

return completed
Expand Down Expand Up @@ -385,11 +396,12 @@ async function resolvePrismaData (

logger.trace('API requests successful')

const submission: AnySubmission = {
const submission = {
...data,
state: data.state,

feedbackThread,
author: undefined,
tech: data.techUsed,
links: {
other: data.otherLinks,
Expand Down
5 changes: 3 additions & 2 deletions src/types/submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ export interface CompletedSubmission extends BaseSubmission {
id: Cuid
submittedAt: Date

// Author may no longer exist when we fetch in this state
author?: GuildMember
// Author / thread may no longer exist when we fetch in this state
author: GuildMember | undefined
feedbackThread: ThreadChannel | undefined
}

// These type guards exist for more readable code, and better TS behavior
Expand Down
39 changes: 37 additions & 2 deletions src/utils/commands.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,43 @@
import { CommandContext } from 'slash-create'
import { commandLog } from '../communication/interaction'
import { internalLog } from '../communication/internal'
import { fetchSubmissionByThreadId } from '../db/submission'
import { PendingSubmission, ValidatedSubmission } from '../types/submission'
import { fetchAnySubmissionByThreadId, fetchSubmissionByThreadId } from '../db/submission'
import { AnySubmission, PendingSubmission, ValidatedSubmission } from '../types/submission'

/**
* Fetches the submission for the given command context.
* This does NOT validate the state of the submission in any way
* This relies on the thread ID to perform the lookup.
*/
export async function fetchAnySubmissionForContext (ctx: CommandContext): Promise<AnySubmission | undefined> {
const id = ctx.channelID

if (!id) {
return void commandLog.error({
type: 'text',
content: 'Interaction came with no thread ID.',
ctx
})
}

const submission = await fetchAnySubmissionByThreadId(id)

if (!submission) {
commandLog.error({
type: 'text',
content: `Could not look up submission for channel ID ${id}`,
ctx
})

return void internalLog.error({
type: 'text',
content: `Could not look up submission for channel ID ${id}`,
ctx: undefined
})
}

return submission
}

/**
* Fetches the submission for the given command context.
Expand Down

0 comments on commit 2fe10ae

Please sign in to comment.