generated from nhcarrigan/template
feat: migrate away from trello (#2)
Closes #1 Reviewed-on: https://codeberg.org/nhcarrigan/a4p-bot/pulls/2 Co-authored-by: Naomi <commits@nhcarrigan.com> Co-committed-by: Naomi <commits@nhcarrigan.com>
This commit is contained in:
parent
bbd6a710bb
commit
a85b478dba
@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "20",
|
"node": "20",
|
||||||
"pnpm": "8"
|
"pnpm": "9"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"template",
|
"template",
|
||||||
|
3614
pnpm-lock.yaml
generated
3614
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,22 +0,0 @@
|
|||||||
generator client {
|
|
||||||
provider = "prisma-client-js"
|
|
||||||
}
|
|
||||||
|
|
||||||
datasource db {
|
|
||||||
provider = "mongodb"
|
|
||||||
url = env("MONGO_URI")
|
|
||||||
}
|
|
||||||
|
|
||||||
model rewards {
|
|
||||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
||||||
trelloId String
|
|
||||||
messageId String
|
|
||||||
createdAt Int @default(0)
|
|
||||||
claimedBy String @default("") // user who claimed
|
|
||||||
completed Boolean @default(false)
|
|
||||||
|
|
||||||
@@unique([trelloId], map: "trello")
|
|
||||||
@@unique([messageId], map: "message")
|
|
||||||
@@index([claimedBy, completed])
|
|
||||||
@@index([claimedBy])
|
|
||||||
}
|
|
@ -41,6 +41,4 @@ export const TrelloComments: {
|
|||||||
[Webhooks.NewCommissions]: (userName) => `Artwork claimed by ${userName}.`,
|
[Webhooks.NewCommissions]: (userName) => `Artwork claimed by ${userName}.`,
|
||||||
[Webhooks.CompleteCommissions]: (userName) =>
|
[Webhooks.CompleteCommissions]: (userName) =>
|
||||||
`Distribution claimed by ${userName}.`,
|
`Distribution claimed by ${userName}.`,
|
||||||
[Webhooks.NewTest]: (userName) => `Artwork claimed by ${userName}.`,
|
|
||||||
[Webhooks.CompleteTest]: (userName) => `Distribution claimed by ${userName}.`,
|
|
||||||
};
|
};
|
||||||
|
@ -1,25 +1,19 @@
|
|||||||
import { Message } from "discord.js";
|
import { User } from "discord.js";
|
||||||
|
|
||||||
export enum Webhooks {
|
export enum Webhooks {
|
||||||
NewCommissions = "1172850885571911760",
|
NewCommissions = "1172850885571911760",
|
||||||
CompleteCommissions = "1173062416041525259",
|
CompleteCommissions = "1173062416041525259",
|
||||||
NewTest = "1173009530511171634",
|
|
||||||
CompleteTest = "946487942526935060",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grabs the message from Discord, formats it based on the webhook ID.
|
* Grabs the user from Discord, formats it based on the webhook ID.
|
||||||
*
|
*
|
||||||
* @param {Message} message The message payload from Discord.
|
* @param {User} u The user payload from Discord.
|
||||||
* @returns {string} The formatted text to send.
|
* @returns {string} The formatted text to send.
|
||||||
*/
|
*/
|
||||||
export const DMTexts: { [key in Webhooks]: (message: Message) => string } = {
|
export const ClaimTexts: { [key in Webhooks]: (u: User) => string } = {
|
||||||
[Webhooks.NewCommissions]: (message) =>
|
[Webhooks.NewCommissions]: (u) =>
|
||||||
`[Here is the donation commission you claimed~!](${message.url})\n> ${message.content}`,
|
`Thanks for agreeing to do this art, <@!${u.id}>~! When it's completed, upload the image here and I'll automatically close this thread!`,
|
||||||
[Webhooks.CompleteCommissions]: (message) =>
|
[Webhooks.CompleteCommissions]: (u) =>
|
||||||
`[Thank you for agreeing to deliver the following commission~!](${message.url})\n> ${message.content}`,
|
`Thanks for agreeing to deliver this art, <@!${u.id}>~! When it's completed, upload a confirmation image here and I'll automatically close this thread!`,
|
||||||
[Webhooks.NewTest]: (message) =>
|
|
||||||
`[Here is the donation commission you claimed~!](${message.url})\n> ${message.content}`,
|
|
||||||
[Webhooks.CompleteTest]: (message) =>
|
|
||||||
`[Thank you for agreeing to deliver the following commission~!](${message.url})\n> ${message.content}`,
|
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { Message, PermissionFlagsBits } from "discord.js";
|
import {
|
||||||
|
ChannelType,
|
||||||
|
Message,
|
||||||
|
PermissionFlagsBits,
|
||||||
|
TextChannel,
|
||||||
|
} from "discord.js";
|
||||||
|
|
||||||
import { ExtendedClient } from "../interface/ExtendedClient";
|
import { ExtendedClient } from "../interface/ExtendedClient";
|
||||||
import { logTicketMessage } from "../modules/logTicketMessage";
|
import { logTicketMessage } from "../modules/logTicketMessage";
|
||||||
@ -106,6 +111,48 @@ export const onMessageCreate = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.channel.type === ChannelType.PublicThread) {
|
||||||
|
if (message.channel.parentId === "1172568787330019340") {
|
||||||
|
const { attachments } = message;
|
||||||
|
if (!attachments.size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await message.reply({
|
||||||
|
content:
|
||||||
|
"Accepting this as submission and closing out art request. Thanks for your support!",
|
||||||
|
});
|
||||||
|
const starter = await message.channel.fetchStarterMessage();
|
||||||
|
const distChannel = (await message.channel.guild.channels.fetch(
|
||||||
|
"1173061747737903315"
|
||||||
|
)) as TextChannel;
|
||||||
|
if (!starter || !distChannel) {
|
||||||
|
await message.channel.send(
|
||||||
|
"<@!465650873650118659>, couldn't port this to distributor channel. Please port manually~!"
|
||||||
|
);
|
||||||
|
await message.channel.setArchived(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await message.channel.setArchived(true);
|
||||||
|
await distChannel.send({
|
||||||
|
content: starter.content,
|
||||||
|
files: [...attachments.values()],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.channel.parentId === "1173061747737903315") {
|
||||||
|
const { attachments } = message;
|
||||||
|
if (!attachments.size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await message.reply({
|
||||||
|
content:
|
||||||
|
"Accepting this as delivery confirmation and closing out distribution request. Thanks for your support!",
|
||||||
|
});
|
||||||
|
await message.channel.setArchived(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (message.author.bot && !isValidWebhook(message.author.id)) {
|
if (message.author.bot && !isValidWebhook(message.author.id)) {
|
||||||
|
@ -2,11 +2,12 @@ import {
|
|||||||
MessageReaction,
|
MessageReaction,
|
||||||
PartialMessageReaction,
|
PartialMessageReaction,
|
||||||
PartialUser,
|
PartialUser,
|
||||||
|
TextChannel,
|
||||||
|
ThreadAutoArchiveDuration,
|
||||||
User,
|
User,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
|
|
||||||
import { TrelloComments } from "../config/Trello";
|
import { ClaimTexts } from "../config/Webhooks";
|
||||||
import { DMTexts } from "../config/Webhooks";
|
|
||||||
import { ExtendedClient } from "../interface/ExtendedClient";
|
import { ExtendedClient } from "../interface/ExtendedClient";
|
||||||
import { isValidWebhook } from "../utils/isValidWebhook";
|
import { isValidWebhook } from "../utils/isValidWebhook";
|
||||||
|
|
||||||
@ -49,58 +50,24 @@ export const onReactionAdd = async (
|
|||||||
await r.users.remove(user.id);
|
await r.users.remove(user.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const claimedByUser = await bot.db.rewards.findMany({
|
|
||||||
where: {
|
const channel = r.message.channel as TextChannel;
|
||||||
claimedBy: user.id,
|
const claimedByUser = (await channel.threads.fetchActive()).threads.filter(
|
||||||
completed: false,
|
(t) => t.name === user.id
|
||||||
},
|
);
|
||||||
});
|
if (claimedByUser.size >= 2) {
|
||||||
if (claimedByUser.length >= 2) {
|
|
||||||
await r.users.remove(user.id);
|
await r.users.remove(user.id);
|
||||||
await user.send(
|
await user.send(
|
||||||
"You currently have 2 open art rewards. Please do not claim another until you have completed one of your outstanding art works."
|
"You currently have 2 open art rewards. Please do not claim another until you have completed one of your outstanding art works."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const files = [...message.attachments.values()];
|
const thread = await channel.threads.create({
|
||||||
await user
|
autoArchiveDuration: ThreadAutoArchiveDuration.OneWeek,
|
||||||
.send({
|
name: user.id,
|
||||||
content: DMTexts[message.author.id](message),
|
});
|
||||||
files,
|
await thread.members.add(user.id);
|
||||||
})
|
await thread.send(ClaimTexts[message.author.id](user as User));
|
||||||
.catch(async (err) => {
|
|
||||||
await bot.debug.send({
|
|
||||||
content: `[Failed to DM ${user.username}:](<${r.message.url}>) ${err.message}`,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const trelloId =
|
|
||||||
message.content.split("You can ignore this it's just for the bot. ")[1] ||
|
|
||||||
message.content.split(
|
|
||||||
"You can ignore this ID it's just for the bot: "
|
|
||||||
)[1];
|
|
||||||
if (trelloId) {
|
|
||||||
await fetch(
|
|
||||||
`https://api.trello.com/1/cards/${trelloId}/actions/comments?text=${TrelloComments[
|
|
||||||
message.author.id
|
|
||||||
](user.displayName || user.username || user.id)}&key=${
|
|
||||||
process.env.TRELLO_KEY
|
|
||||||
}&token=${process.env.TRELLO_TOKEN}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
accept: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
await bot.db.rewards.update({
|
|
||||||
where: {
|
|
||||||
trelloId,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
claimedBy: user.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await bot.debug.send(
|
await bot.debug.send(
|
||||||
`Error in processing new reaction: ${(err as Error).message}`
|
`Error in processing new reaction: ${(err as Error).message}`
|
||||||
|
@ -4,8 +4,9 @@ import { ExtendedClient } from "../interface/ExtendedClient";
|
|||||||
import { checkAirtableRecords } from "../modules/checkAirtableRecords";
|
import { checkAirtableRecords } from "../modules/checkAirtableRecords";
|
||||||
import { fetchMessages } from "../modules/messages/fetchMessages";
|
import { fetchMessages } from "../modules/messages/fetchMessages";
|
||||||
import { sendUnclaimedArt } from "../modules/reminders/sendUnclaimedArt";
|
import { sendUnclaimedArt } from "../modules/reminders/sendUnclaimedArt";
|
||||||
|
import { sendUnclaimedDistros } from "../modules/reminders/sendUnclaimedDistros";
|
||||||
import { sendUnfinishedArt } from "../modules/reminders/sendUnfinishedArt";
|
import { sendUnfinishedArt } from "../modules/reminders/sendUnfinishedArt";
|
||||||
import { serve } from "../server/serve";
|
import { sendUnfinishedDistros } from "../modules/reminders/sendUnfinsihedDistros";
|
||||||
import { getNewsFeed } from "../utils/getNewsFeed";
|
import { getNewsFeed } from "../utils/getNewsFeed";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,13 +30,13 @@ export const onReady = async (bot: ExtendedClient) => {
|
|||||||
|
|
||||||
scheduleJob("0 9 * * 1,3,5", async () => {
|
scheduleJob("0 9 * * 1,3,5", async () => {
|
||||||
await sendUnclaimedArt(bot);
|
await sendUnclaimedArt(bot);
|
||||||
|
await sendUnclaimedDistros(bot);
|
||||||
});
|
});
|
||||||
|
|
||||||
scheduleJob("0 9 * * 6", async () => {
|
scheduleJob("0 9 * * 6", async () => {
|
||||||
await sendUnfinishedArt(bot);
|
await sendUnfinishedArt(bot);
|
||||||
|
await sendUnfinishedDistros(bot);
|
||||||
});
|
});
|
||||||
|
|
||||||
await serve(bot);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await bot.debug.send(`Error on ready event: ${(err as Error).message}`);
|
await bot.debug.send(`Error on ready event: ${(err as Error).message}`);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
|
|
||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
import { Client, Events, GatewayIntentBits, WebhookClient } from "discord.js";
|
import { Client, Events, GatewayIntentBits, WebhookClient } from "discord.js";
|
||||||
|
|
||||||
import { onInteractionCreate } from "./events/onInteractionCreate";
|
import { onInteractionCreate } from "./events/onInteractionCreate";
|
||||||
@ -32,14 +31,12 @@ import { logHandler } from "./utils/logHandler";
|
|||||||
GatewayIntentBits.GuildMembers,
|
GatewayIntentBits.GuildMembers,
|
||||||
],
|
],
|
||||||
}) as ExtendedClient;
|
}) as ExtendedClient;
|
||||||
bot.db = new PrismaClient();
|
|
||||||
bot.debug = new WebhookClient({ url: process.env.DEBUG });
|
bot.debug = new WebhookClient({ url: process.env.DEBUG });
|
||||||
bot.comm = new WebhookClient({ url: process.env.COMM });
|
bot.comm = new WebhookClient({ url: process.env.COMM });
|
||||||
bot.dist = new WebhookClient({ url: process.env.DIST });
|
bot.dist = new WebhookClient({ url: process.env.DIST });
|
||||||
bot.news = new WebhookClient({ url: process.env.NEWS });
|
bot.news = new WebhookClient({ url: process.env.NEWS });
|
||||||
bot.ticket = new WebhookClient({ url: process.env.TICKET });
|
bot.ticket = new WebhookClient({ url: process.env.TICKET });
|
||||||
bot.ticketLogs = {};
|
bot.ticketLogs = {};
|
||||||
await bot.db.$connect();
|
|
||||||
|
|
||||||
const commit = execSync("git rev-parse HEAD").toString().trim();
|
const commit = execSync("git rev-parse HEAD").toString().trim();
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
import { Client, WebhookClient } from "discord.js";
|
import { Client, WebhookClient } from "discord.js";
|
||||||
|
|
||||||
export interface ExtendedClient extends Client {
|
export interface ExtendedClient extends Client {
|
||||||
db: PrismaClient;
|
|
||||||
debug: WebhookClient;
|
debug: WebhookClient;
|
||||||
comm: WebhookClient;
|
comm: WebhookClient;
|
||||||
dist: WebhookClient;
|
dist: WebhookClient;
|
||||||
|
@ -3,7 +3,6 @@ import { join } from "path";
|
|||||||
|
|
||||||
import { AttachmentBuilder } from "discord.js";
|
import { AttachmentBuilder } from "discord.js";
|
||||||
|
|
||||||
import { ActionsToLabel, PlatformsToLabel, Trello } from "../config/Trello";
|
|
||||||
import { AirtableResponse } from "../interface/AirtableResponse";
|
import { AirtableResponse } from "../interface/AirtableResponse";
|
||||||
import { ExtendedClient } from "../interface/ExtendedClient";
|
import { ExtendedClient } from "../interface/ExtendedClient";
|
||||||
|
|
||||||
@ -44,12 +43,9 @@ export const checkAirtableRecords = async (bot: ExtendedClient) => {
|
|||||||
const {
|
const {
|
||||||
Name: name,
|
Name: name,
|
||||||
Reference: images,
|
Reference: images,
|
||||||
Action: action,
|
|
||||||
"Contact Method": platform,
|
"Contact Method": platform,
|
||||||
Handle: handle,
|
Handle: handle,
|
||||||
"Anything Else?": note,
|
"Anything Else?": note,
|
||||||
"Email Address": email,
|
|
||||||
"What would you like us to draw?": request,
|
|
||||||
} = record.fields;
|
} = record.fields;
|
||||||
const files: AttachmentBuilder[] = [];
|
const files: AttachmentBuilder[] = [];
|
||||||
for (const imageUrl of images) {
|
for (const imageUrl of images) {
|
||||||
@ -61,117 +57,10 @@ export const checkAirtableRecords = async (bot: ExtendedClient) => {
|
|||||||
});
|
});
|
||||||
files.push(file);
|
files.push(file);
|
||||||
}
|
}
|
||||||
|
await bot.comm.send({
|
||||||
if (!process.env.TRELLO_TOKEN || !process.env.TRELLO_KEY) {
|
content: `**FOR:** ${name} - Contact via ${platform}: ${handle}\n\n${note}\n\nReferences:`,
|
||||||
await bot.debug.send({
|
|
||||||
content:
|
|
||||||
"Cannot create card on Trello. Missing environment variables.",
|
|
||||||
});
|
|
||||||
await bot.comm.send({
|
|
||||||
content: `${name} | Trello failed to generate. | References attached below:`,
|
|
||||||
files,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cardRes = await fetch(
|
|
||||||
`https://api.trello.com/1/cards?idList=${Trello.newCardListId}&key=${
|
|
||||||
process.env.TRELLO_KEY
|
|
||||||
}&token=${process.env.TRELLO_TOKEN}&name=${encodeURIComponent(
|
|
||||||
name
|
|
||||||
)}&desc=${encodeURIComponent(
|
|
||||||
`${name} helped us with: ${action}\n\nPlease contact them at ${
|
|
||||||
platform === "Email" ? email : `${handle} on ${platform}`
|
|
||||||
} to update them on art.\n\nUSER NOTE: ${note}\nART REQUEST: ${request}`
|
|
||||||
)}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Accept: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const card = (await cardRes.json()) as { id: string; url: string };
|
|
||||||
await fetch(
|
|
||||||
`https://api.trello.com/1/cards/${card.id}/attachments?key=${
|
|
||||||
process.env.TRELLO_KEY
|
|
||||||
}&token=${
|
|
||||||
process.env.TRELLO_TOKEN
|
|
||||||
}&name=reference.png&url=${encodeURIComponent(
|
|
||||||
images[0]?.url ?? "https://cdn.naomi.lgbt/banner.png"
|
|
||||||
)}&setCover=true`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
accept: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
for (const imageUrl of images.slice(1)) {
|
|
||||||
await fetch(
|
|
||||||
`https://api.trello.com/1/cards/${card.id}/attachments?key=${
|
|
||||||
process.env.TRELLO_KEY
|
|
||||||
}&token=${
|
|
||||||
process.env.TRELLO_TOKEN
|
|
||||||
}&name=reference.png&url=${encodeURIComponent(imageUrl.url)}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
accept: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Use this if we want to add checklist to every card :3
|
|
||||||
// await fetch(
|
|
||||||
// `https://api.trello.com/1/cards/${
|
|
||||||
// card.id
|
|
||||||
// }/checklists?idChecklistSource=${
|
|
||||||
// Trello.checklistId
|
|
||||||
// }&name=${encodeURIComponent("To Do")}&key=${
|
|
||||||
// process.env.TRELLO_KEY
|
|
||||||
// }&token=${process.env.TRELLO_TOKEN}`,
|
|
||||||
// {
|
|
||||||
// method: "POST",
|
|
||||||
// headers: {
|
|
||||||
// accept: "application/json",
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
if (PlatformsToLabel[platform]) {
|
|
||||||
await fetch(
|
|
||||||
`https://api.trello.com/1/cards/${card.id}/idLabels?value=${PlatformsToLabel[platform]}&key=${process.env.TRELLO_KEY}&token=${process.env.TRELLO_TOKEN}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
accept: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (ActionsToLabel[action]) {
|
|
||||||
await fetch(
|
|
||||||
`https://api.trello.com/1/cards/${card.id}/idLabels?value=${ActionsToLabel[action]}&key=${process.env.TRELLO_KEY}&token=${process.env.TRELLO_TOKEN}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
accept: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const msg = await bot.comm.send({
|
|
||||||
content: `${name} | [Trello](<${card.url}>) | References attached below.\nYou can ignore this ID it's just for the bot: ${card.id}`,
|
|
||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
await bot.db.rewards.create({
|
|
||||||
data: {
|
|
||||||
trelloId: card.id,
|
|
||||||
createdAt: Date.now(),
|
|
||||||
claimedBy: "",
|
|
||||||
completed: false,
|
|
||||||
messageId: msg.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { TextChannel } from "discord.js";
|
||||||
|
|
||||||
import { ExtendedClient } from "../../interface/ExtendedClient";
|
import { ExtendedClient } from "../../interface/ExtendedClient";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7,16 +9,19 @@ import { ExtendedClient } from "../../interface/ExtendedClient";
|
|||||||
*/
|
*/
|
||||||
export const sendUnclaimedArt = async (bot: ExtendedClient) => {
|
export const sendUnclaimedArt = async (bot: ExtendedClient) => {
|
||||||
try {
|
try {
|
||||||
const unclaimed = await bot.db.rewards.findMany({
|
const guild = await bot.guilds.fetch("1172566005311090798");
|
||||||
where: {
|
const artChannel = (await guild.channels.fetch(
|
||||||
claimedBy: "",
|
"1172568787330019340"
|
||||||
},
|
)) as TextChannel;
|
||||||
|
const messages = await artChannel.messages.fetch({
|
||||||
|
after: "1241326793294610443",
|
||||||
});
|
});
|
||||||
if (!unclaimed.length) {
|
const filtered = messages.filter((m) => !m.hasThread);
|
||||||
|
|
||||||
|
if (!filtered.size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const guild = await bot.guilds.fetch("1172566005311090798");
|
|
||||||
const channel = await guild.channels.fetch("1172568865218252801");
|
const channel = await guild.channels.fetch("1172568865218252801");
|
||||||
|
|
||||||
if (!channel || !("send" in channel)) {
|
if (!channel || !("send" in channel)) {
|
||||||
@ -28,12 +33,7 @@ export const sendUnclaimedArt = async (bot: ExtendedClient) => {
|
|||||||
|
|
||||||
The following art rewards have not been claimed yet. If you have the capacity to do so, please consider taking one on.
|
The following art rewards have not been claimed yet. If you have the capacity to do so, please consider taking one on.
|
||||||
|
|
||||||
${unclaimed
|
${filtered.map((r) => `- ${r.url}`).join("\n")}`);
|
||||||
.map(
|
|
||||||
(r) =>
|
|
||||||
`- https://discord.com/channels/1172566005311090798/1172568787330019340/${r.messageId}`
|
|
||||||
)
|
|
||||||
.join("\n")}`);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await bot.debug.send(`Cannot send unclaimed art reminder: ${err}`);
|
await bot.debug.send(`Cannot send unclaimed art reminder: ${err}`);
|
||||||
}
|
}
|
||||||
|
40
src/modules/reminders/sendUnclaimedDistros.ts
Normal file
40
src/modules/reminders/sendUnclaimedDistros.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { TextChannel } from "discord.js";
|
||||||
|
|
||||||
|
import { ExtendedClient } from "../../interface/ExtendedClient";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a reminder to claim the unclaimed distribution requests.
|
||||||
|
*
|
||||||
|
* @param {ExtendedClient} bot The bot's Discord instance.
|
||||||
|
*/
|
||||||
|
export const sendUnclaimedDistros = async (bot: ExtendedClient) => {
|
||||||
|
try {
|
||||||
|
const guild = await bot.guilds.fetch("1172566005311090798");
|
||||||
|
const artChannel = (await guild.channels.fetch(
|
||||||
|
"1173061747737903315"
|
||||||
|
)) as TextChannel;
|
||||||
|
const messages = await artChannel.messages.fetch({
|
||||||
|
after: "1241055357112025168",
|
||||||
|
});
|
||||||
|
const filtered = messages.filter((m) => !m.hasThread);
|
||||||
|
|
||||||
|
if (!filtered.size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = await guild.channels.fetch("1173061809834565764");
|
||||||
|
|
||||||
|
if (!channel || !("send" in channel)) {
|
||||||
|
await bot.debug.send(`Failed to find <#1173061809834565764>~!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await channel.send(`## Unclaimed Distribtions!
|
||||||
|
|
||||||
|
The following art rewards have not been distributed yet. If you have the capacity to do so, please consider taking one on.
|
||||||
|
|
||||||
|
${filtered.map((r) => `- ${r.url}`).join("\n")}`);
|
||||||
|
} catch (err) {
|
||||||
|
await bot.debug.send(`Cannot send unclaimed distro reminder: ${err}`);
|
||||||
|
}
|
||||||
|
};
|
@ -1,3 +1,5 @@
|
|||||||
|
import { TextChannel } from "discord.js";
|
||||||
|
|
||||||
import { ExtendedClient } from "../../interface/ExtendedClient";
|
import { ExtendedClient } from "../../interface/ExtendedClient";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7,36 +9,16 @@ import { ExtendedClient } from "../../interface/ExtendedClient";
|
|||||||
*/
|
*/
|
||||||
export const sendUnfinishedArt = async (bot: ExtendedClient) => {
|
export const sendUnfinishedArt = async (bot: ExtendedClient) => {
|
||||||
try {
|
try {
|
||||||
const unfinished = await bot.db.rewards.findMany({
|
|
||||||
where: {
|
|
||||||
claimedBy: {
|
|
||||||
not: "",
|
|
||||||
},
|
|
||||||
completed: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!unfinished.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const guild = await bot.guilds.fetch("1172566005311090798");
|
const guild = await bot.guilds.fetch("1172566005311090798");
|
||||||
const channel = await guild.channels.fetch("1172568865218252801");
|
const channel = (await guild.channels.fetch(
|
||||||
|
"1172568787330019340"
|
||||||
if (!channel || !("send" in channel)) {
|
)) as TextChannel;
|
||||||
await bot.debug.send(`Failed to find <#1172568865218252801>~!`);
|
const threads = await channel.threads.fetchActive();
|
||||||
return;
|
for (const thread of threads.threads.values()) {
|
||||||
|
await thread.send({
|
||||||
|
content: `<@!${thread.name}>, this art appears unfinished. When it's complete, please upload the image here and the thread will be processed.`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.send(`## Unfinished Art!
|
|
||||||
|
|
||||||
The following art rewards have not been completed yet. We would like to keep a turnaround time of a couple of weeks, but your health is also important! So if you have claimed one of these and don't have the capacity to finish it, let Angel or Naomi know.
|
|
||||||
|
|
||||||
${unfinished
|
|
||||||
.map(
|
|
||||||
(r) =>
|
|
||||||
`- https://discord.com/channels/1172566005311090798/1172568787330019340/${r.messageId}`
|
|
||||||
)
|
|
||||||
.join("\n")}`);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await bot.debug.send(`Cannot send unfinished art reminder: ${err}`);
|
await bot.debug.send(`Cannot send unfinished art reminder: ${err}`);
|
||||||
}
|
}
|
||||||
|
25
src/modules/reminders/sendUnfinsihedDistros.ts
Normal file
25
src/modules/reminders/sendUnfinsihedDistros.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { TextChannel } from "discord.js";
|
||||||
|
|
||||||
|
import { ExtendedClient } from "../../interface/ExtendedClient";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a reminder to finish claimed distribution requests.
|
||||||
|
*
|
||||||
|
* @param {ExtendedClient} bot The bot's Discord instance.
|
||||||
|
*/
|
||||||
|
export const sendUnfinishedDistros = async (bot: ExtendedClient) => {
|
||||||
|
try {
|
||||||
|
const guild = await bot.guilds.fetch("1172566005311090798");
|
||||||
|
const channel = (await guild.channels.fetch(
|
||||||
|
"1173061747737903315"
|
||||||
|
)) as TextChannel;
|
||||||
|
const threads = await channel.threads.fetchActive();
|
||||||
|
for (const thread of threads.threads.values()) {
|
||||||
|
await thread.send({
|
||||||
|
content: `<@!${thread.name}>, this distribution appears unconfirmed. When it's complete, please upload a confirmation image here and the thread will be processed.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
await bot.debug.send(`Cannot send unfinished art reminder: ${err}`);
|
||||||
|
}
|
||||||
|
};
|
@ -11,6 +11,8 @@ import { ExtendedClient } from "../interface/ExtendedClient";
|
|||||||
/**
|
/**
|
||||||
* Instantiates the web server for listening to webhook payloads.
|
* Instantiates the web server for listening to webhook payloads.
|
||||||
*
|
*
|
||||||
|
* TODO: Delete this entirely once all trello things are done.
|
||||||
|
*
|
||||||
* @param {ExtendedClient} bot The bot's Discord instance.
|
* @param {ExtendedClient} bot The bot's Discord instance.
|
||||||
*/
|
*/
|
||||||
export const serve = async (bot: ExtendedClient) => {
|
export const serve = async (bot: ExtendedClient) => {
|
||||||
@ -80,14 +82,6 @@ export const serve = async (bot: ExtendedClient) => {
|
|||||||
await bot.dist.send({
|
await bot.dist.send({
|
||||||
content: `${card.name} | [Trello Card](<${card.url}>) | ${contact}\nYou can ignore this ID it's just for the bot: ${card.id}`,
|
content: `${card.name} | [Trello Card](<${card.url}>) | ${contact}\nYou can ignore this ID it's just for the bot: ${card.id}`,
|
||||||
});
|
});
|
||||||
await bot.db.rewards.update({
|
|
||||||
where: {
|
|
||||||
trelloId: card.id,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
completed: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const httpServer = http.createServer(app);
|
const httpServer = http.createServer(app);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user