68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
import {
|
|
announcementMessage,
|
|
DiscordClient,
|
|
DiscordDeliveryError,
|
|
} from "./discord-client";
|
|
import type { DiscordAnnouncement } from "../shared/discord";
|
|
type Source = Parameters<typeof announcementMessage>[3];
|
|
export async function deliverDiscordAnnouncement(
|
|
job: DiscordAnnouncement,
|
|
dependencies: {
|
|
origin: string;
|
|
channel: string;
|
|
client: Pick<DiscordClient, "send">;
|
|
load: () => Promise<Source | null>;
|
|
finish: (patch: Partial<DiscordAnnouncement>) => Promise<void>;
|
|
now?: () => number;
|
|
},
|
|
) {
|
|
const {
|
|
origin,
|
|
channel,
|
|
client,
|
|
load,
|
|
finish,
|
|
now = Date.now,
|
|
} = dependencies;
|
|
const released = { lease_owner: null, lease_until: null };
|
|
try {
|
|
const source = await load();
|
|
if (!source) {
|
|
await finish({ ...released, state: "skipped", last_error: null });
|
|
return;
|
|
}
|
|
const messageId = await client.send(
|
|
channel,
|
|
announcementMessage(job.id, job.kind, origin, source),
|
|
);
|
|
await finish({
|
|
...released,
|
|
state: "sent",
|
|
channel_id: channel,
|
|
message_id: messageId,
|
|
sent_at: new Date(now()).toISOString(),
|
|
last_error: null,
|
|
});
|
|
} catch (failure) {
|
|
const error =
|
|
failure instanceof DiscordDeliveryError
|
|
? failure
|
|
: new DiscordDeliveryError(
|
|
"Discord delivery could not be confirmed. Delivery will retry.",
|
|
);
|
|
await finish({
|
|
...released,
|
|
state: error.permanent || job.attempts >= 8 ? "failed" : "pending",
|
|
last_error: error.message,
|
|
next_attempt_at: new Date(
|
|
now() +
|
|
Math.max(
|
|
error.retryAfter,
|
|
Math.min(3600, 30 * 2 ** (job.attempts - 1)),
|
|
) *
|
|
1000,
|
|
).toISOString(),
|
|
});
|
|
}
|
|
}
|