Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto thread title fix, Resume Review features #375

Merged
merged 9 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

There are subtle issues when making some chaings. These are notes for steps to take to make sure it's done correctly when needed.

Generating images for #resume-review requires GraphicsMagick installed. [Brew](https://formulae.brew.sh/formula/graphicsmagick), [Linux](http://www.graphicsmagick.org/)

## Environment variables

Adding a new environment variable needs to be done in several places to work corectly and be predictable for new developers:
Expand Down
6 changes: 1 addition & 5 deletions src/features/autoban.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ const tags = [
];

const autoban: ChannelHandlers = {
handleMessage: async ({ msg: maybeMessage }) => {
const msg = maybeMessage.partial
? await maybeMessage.fetch()
: maybeMessage;

handleMessage: async ({ msg }) => {
const content = msg.content.toLowerCase();
const hasToken = tags.some((token) => content.includes(token));

Expand Down
10 changes: 3 additions & 7 deletions src/features/autothread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,14 @@ const IDLE_TIMEOUT = 36;
const STAFF_ACCEPT_THRESHOLD = 2;

const autoThread: ChannelHandlers = {
handleMessage: async ({ msg: maybeMessage }) => {
handleMessage: async ({ msg }) => {
if (
maybeMessage.channel.type === ChannelType.PublicThread ||
maybeMessage.channel.type === ChannelType.PrivateThread
msg.channel.type === ChannelType.PublicThread ||
msg.channel.type === ChannelType.PrivateThread
) {
return;
}

const msg = maybeMessage.partial
? await maybeMessage.fetch()
: maybeMessage;

// Delete top-level replies
if (msg.type === MessageType.Reply) {
const repliedTo = await msg.fetchReference();
Expand Down
12 changes: 4 additions & 8 deletions src/features/promotion-threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@ import fetch from "node-fetch";
import { ChannelType, MessageType } from "discord.js";

const promotionThread: ChannelHandlers = {
handleMessage: async ({ msg: maybeMessage }) => {
handleMessage: async ({ msg }) => {
if (
maybeMessage.channel.type === ChannelType.PublicThread ||
maybeMessage.channel.type === ChannelType.PrivateThread
msg.channel.type === ChannelType.PublicThread ||
msg.channel.type === ChannelType.PrivateThread
) {
return;
}

const msg = maybeMessage.partial
? await maybeMessage.fetch()
: maybeMessage;

// Delete top-level replies
if (msg.type === MessageType.Reply) {
msg.author.send(msg.content);
Expand All @@ -39,7 +35,7 @@ const promotionThread: ChannelHandlers = {
const title = await (async () => {
let maybeTitle = msg.author.username;
if (firstLink) {
if (firstLink.startsWith("https://twitter.com/")) {
if (/^https:\/\/twitter.com|^https:\/\/x.com/.test(firstLink)) {
try {
const res = await fetch(
`https://publish.twitter.com/oembed?url=${firstLink}`,
Expand Down
74 changes: 54 additions & 20 deletions src/features/resume-review.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Message } from "discord.js";
import {
ButtonBuilder,
ActionRowBuilder,
AttachmentBuilder,
ButtonStyle,
Message,
} from "discord.js";
import { CHANNELS } from "../constants/channels";
import { createAttachmentBuilderFromURL } from "../helpers/generate-pdf";
import { ChannelHandlers } from "../types";
import cooldown from "./cooldown";
Expand All @@ -12,11 +19,15 @@ export const findResumeAttachment = (msg: Message) => {
(attachment) => attachment.contentType === PDF_CONTENT_TYPE,
);
};
export const REVIEW_COMMAND = "review-resume";
export const DELETE_COMMAND = "delete-post";

const sendResumeMessage = async (msg: Message): Promise<true | void> => {
const buildResumeImages = async (
msg: Message,
): Promise<AttachmentBuilder[]> => {
const attachment = findResumeAttachment(msg);
if (!attachment) {
return;
return [];
}

const builder = await createAttachmentBuilderFromURL(
Expand All @@ -25,34 +36,57 @@ const sendResumeMessage = async (msg: Message): Promise<true | void> => {
);
if (!builder) {
logger.log("[RESUME]", "Failed to generate resume PDF in thread");
return;
return [];
}

await msg.channel.send({
files: builder,
});

return true;
return builder;
};

const resumeReviewPdf: ChannelHandlers = {
handleMessage: async ({ msg }) => {
// NOTE: This cast is safe as we are fetching the actual message in the index.ts/handleMessage
const message = msg as Message;
const cooldownKey = `resume-${msg.channelId}`;
handleMessage: async ({ msg: message }) => {
if (
!message.channel.isThread() ||
message.channel.parentId !== CHANNELS.resumeReview
) {
return;
}
const cooldownKey = `resume-${message.channelId}`;

if (cooldown.hasCooldown(message.author.id, cooldownKey)) {
message.channel.send(
"You posted just a few minutes ago. Please wait a bit before creating a new preview.",
);
return;
}

const sucess = await sendResumeMessage(message);
if (sucess) {
cooldown.addCooldown(
message.author.id,
cooldownKey,
FIVE_MINUTES_IN_SECONDS,
);
await message.channel.sendTyping();

const images = await buildResumeImages(message);
if (images.length === 0) {
return;
}

cooldown.addCooldown(
message.author.id,
cooldownKey,
FIVE_MINUTES_IN_SECONDS,
);
await message.channel.send({
files: images,
components: [
// @ts-expect-error Discord.js types appear to be wrong
new ActionRowBuilder().addComponents(
new ButtonBuilder()
.setCustomId(REVIEW_COMMAND)
.setLabel("AI Review")
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId(DELETE_COMMAND)
.setLabel("Delete post")
.setStyle(ButtonStyle.Danger),
),
],
});
},
};

Expand Down
Loading
Loading