Files
MineGeo/lib/discord-delivery.ts

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(),
});
}
}