Skip to content

Commit d740d2c

Browse files
committed
Revert "Fix a couple of long-standing bugs in job board validation logic (#428)"
This reverts commit 75961f9.
1 parent 75961f9 commit d740d2c

File tree

7 files changed

+40
-90
lines changed

7 files changed

+40
-90
lines changed

src/features/jobs-moderation.ts

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,8 @@ const jobModeration = async (bot: Client) => {
109109
const { channel } = message;
110110
if (
111111
message.author.bot ||
112-
(message.channelId !== CHANNELS.jobBoard &&
113-
channel.isThread() &&
114-
channel.parentId !== CHANNELS.jobBoard) ||
112+
message.channelId !== CHANNELS.jobBoard ||
113+
(channel.isThread() && channel.parentId !== CHANNELS.jobBoard) ||
115114
// Don't treat newly fetched old messages as new posts
116115
differenceInHours(new Date(), message.createdAt) >= 1
117116
) {
@@ -124,7 +123,7 @@ const jobModeration = async (bot: Client) => {
124123
channel.ownerId === bot.user?.id &&
125124
channel.parentId === CHANNELS.jobBoard
126125
) {
127-
await validationRepl(message);
126+
validationRepl(message);
128127
return;
129128
}
130129
// If this is a staff member, bail early
@@ -136,50 +135,46 @@ const jobModeration = async (bot: Client) => {
136135
console.log(
137136
`[DEBUG] validating new job post from @${
138137
message.author.username
139-
}, errors: ${JSON.stringify(errors)}`,
138+
}, errors: [${JSON.stringify(errors)}]`,
140139
);
141140
if (errors) {
142141
await handleErrors(channel, message, errors);
143142
}
144143
});
145144

146-
bot.on("messageUpdate", async (_, message) => {
147-
const { channel } = message;
148-
if (message.author?.bot) {
145+
bot.on("messageUpdate", async (_, newMessage) => {
146+
const { channel } = newMessage;
147+
if (newMessage.author?.bot) {
148+
return;
149+
}
150+
if (channel.type === ChannelType.PrivateThread) {
151+
validationRepl(await newMessage.fetch());
149152
return;
150153
}
151154
if (
152-
message.channelId !== CHANNELS.jobBoard ||
155+
newMessage.channelId !== CHANNELS.jobBoard ||
153156
channel.type !== ChannelType.GuildText ||
154-
isStaff(message.member)
157+
isStaff(newMessage.member)
155158
) {
156159
return;
157160
}
158-
if (message.partial) {
159-
message = await message.fetch();
160-
}
161+
const message = await newMessage.fetch();
161162
const posts = parseContent(message.content);
163+
// Don't validate hiring posts
164+
if (posts.every((p) => p.tags.includes(PostType.hiring))) {
165+
return;
166+
}
162167
// You can't post too frequently when editing a message, so filter those out
163168
const errors = validate(posts, message).filter(
164169
(e) => e.type !== POST_FAILURE_REASONS.tooFrequent,
165170
);
166171

167172
if (errors) {
168-
const isRecentEdit =
169-
differenceInMinutes(new Date(), message.createdAt) < REPOST_THRESHOLD;
170-
errors.unshift({
171-
type: POST_FAILURE_REASONS.circumventedRules,
172-
recentEdit: isRecentEdit,
173-
});
174-
if (isRecentEdit) {
175-
removeSpecificJob(message);
176-
console.log(
177-
`[INFO] Deleting a recently edited post from ${message.author.username}`,
178-
);
179-
}
180-
await handleErrors(channel, message, errors);
181173
if (posts.some((p) => p.tags.includes(PostType.forHire))) {
182174
reportUser({ reason: ReportReasons.jobCircumvent, message });
175+
// await newMessage.delete();
176+
} else {
177+
await handleErrors(channel, message, errors);
183178
}
184179
}
185180
});

src/features/jobs-moderation/job-mod-helpers.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@ import {
2929
PostFailures,
3030
PostType,
3131
PostFailureLinkRequired,
32-
CircumventedRules,
3332
} from "../../types/jobs-moderation";
3433

35-
export const failedCircumventedRules = (
36-
e: PostFailures,
37-
): e is CircumventedRules => e.type === POST_FAILURE_REASONS.circumventedRules;
34+
export class RuleViolation extends Error {
35+
reasons: POST_FAILURE_REASONS[];
36+
constructor(reasons: POST_FAILURE_REASONS[]) {
37+
super("Job Mod Rule violation");
38+
this.reasons = reasons;
39+
}
40+
}
41+
3842
export const failedMissingType = (
3943
e: PostFailures,
4044
): e is PostFailureMissingType => e.type === POST_FAILURE_REASONS.missingType;
@@ -264,7 +268,7 @@ export const removeSpecificJob = (message: Message) => {
264268
const index = jobBoardMessageCache.hiring.findIndex(
265269
(m) => m.message.id === message.id,
266270
);
267-
if (index !== -1) {
271+
if (index) {
268272
jobBoardMessageCache.hiring.splice(index);
269273
} else
270274
jobBoardMessageCache.forHire.splice(

src/features/jobs-moderation/parse-content.test.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -108,28 +108,6 @@ many long lines of text`,
108108
expect(parsed[0]).toMatchObject({ tags: ["hiring"], description: "" });
109109
});
110110

111-
it("correctly pulls description off tags line", () => {
112-
let parsed = parseContent(`[hiring]Lorem ipsum dolor sit amet`);
113-
expect(parsed[0]).toMatchObject({
114-
tags: ["hiring"],
115-
description: "Lorem ipsum dolor sit amet",
116-
});
117-
118-
parsed = parseContent(`[hiring][remote][visa]Lorem ipsum dolor sit amet`);
119-
expect(parsed[0]).toMatchObject({
120-
tags: ["hiring", "remote", "visa"],
121-
description: "Lorem ipsum dolor sit amet",
122-
});
123-
124-
parsed = parseContent(
125-
`[hiring] [remote] [visa] Lorem ipsum dolor sit amet`,
126-
);
127-
expect(parsed[0]).toMatchObject({
128-
tags: ["hiring", "remote", "visa"],
129-
description: "Lorem ipsum dolor sit amet",
130-
});
131-
});
132-
133111
// Disable this, not relevant right now. Also broken as of May '23
134112
it.skip("parses contact", () => {
135113
const makePost = (contact: string) => `|

src/features/jobs-moderation/parse-content.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,12 @@ export const parseTags = (tags: string) => {
2525
.filter((tag) => tag !== "");
2626
};
2727

28-
const splitTagsFromDescription = (
29-
inputString: string,
30-
): { heading: string; body: string[] } => {
31-
const [tagsLine, ...lines] = inputString.trim().split("\n");
32-
33-
if (tagsLine.includes("[")) {
34-
const cleanedTags = tagsLine.replace(/\]\w+\[/, "][");
35-
const match = cleanedTags.match(/(.*)\](.*)/);
36-
const trailingText = match?.[2] || "";
37-
lines.unshift(trailingText.trim());
38-
return { heading: match?.[1] || "", body: lines };
39-
}
40-
return { heading: tagsLine, body: lines };
41-
};
42-
4328
export const parseContent = (inputString: string): Post[] => {
44-
const { heading, body } = splitTagsFromDescription(inputString);
45-
// TODO: Replace above .split() with some more logic around detecting tags
46-
// If |, treat the complete line as tags
47-
// if [], check for trailing text with no wrapper and add it to the description
48-
29+
const [tagsLine, ...lines] = inputString.trim().split("\n");
4930
return [
5031
{
51-
tags: parseTags(heading),
52-
description: body.reduce((description, line) => {
32+
tags: parseTags(tagsLine),
33+
description: lines.reduce((description, line) => {
5334
if (line === "") {
5435
return description;
5536
}

src/features/jobs-moderation/validation-messages.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import {
2-
CircumventedRules,
32
POST_FAILURE_REASONS,
43
PostFailures,
54
PostFailureTooFrequent,
65
PostFailureTooLong,
76
PostFailureTooManyLines,
87
} from "../../types/jobs-moderation";
98
import {
10-
failedCircumventedRules,
119
failedMissingType,
1210
failedReplyOrMention,
1311
failedTooManyLines,
@@ -20,8 +18,6 @@ import {
2018
} from "./job-mod-helpers";
2119

2220
const ValidationMessages = {
23-
[POST_FAILURE_REASONS.circumventedRules]: (e: CircumventedRules) =>
24-
`Your message was removed after you edited it so that it no longer complies with our formatting rules. ${e.recentEdit ? "Please re-post." : ""}`,
2521
[POST_FAILURE_REASONS.missingType]:
2622
"Your post does not include our required `[HIRING]` or `[FOR HIRE]` tag. Make sure the first line of your post includes `[HIRING]` if you’re looking to pay someone for their work, and `[FOR HIRE]` if you’re offering your services.",
2723
[POST_FAILURE_REASONS.inconsistentType]:
@@ -37,13 +33,10 @@ const ValidationMessages = {
3733
[POST_FAILURE_REASONS.tooFrequent]: (e: PostFailureTooFrequent) =>
3834
`You’re posting too frequently. You last posted ${e.lastSent} days ago, please wait at least 7 days.`,
3935
[POST_FAILURE_REASONS.replyOrMention]:
40-
"Messages in this channel may not be replies or include @-mentions of users due to a history of posters incorrectly attempting to 'apply' by replying within a thread or reply.",
36+
"Messages in this channel may not be replies or include @-mentions of users, to ensure the channel isn’t being used to discuss postings.",
4137
};
4238

4339
export const getValidationMessage = (reason: PostFailures): string => {
44-
if (failedCircumventedRules(reason)) {
45-
return ValidationMessages[reason.type](reason);
46-
}
4740
if (failedMissingType(reason)) {
4841
return ValidationMessages[reason.type];
4942
}

src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ export const bot = new discord.Client({
4848
IntentsBitField.Flags.DirectMessageReactions,
4949
IntentsBitField.Flags.MessageContent,
5050
],
51-
partials: [Partials.Channel, Partials.Reaction, Partials.GuildMember],
51+
partials: [
52+
Partials.Channel,
53+
Partials.Message,
54+
Partials.Reaction,
55+
Partials.GuildMember,
56+
],
5257
});
5358

5459
registerCommand(resetJobCacheCommand);

src/types/jobs-moderation.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,11 @@ export const enum POST_FAILURE_REASONS {
2828
tooManyGaps = "tooManyGaps",
2929
tooFrequent = "tooFrequent",
3030
replyOrMention = "replyOrMention",
31-
circumventedRules = "circumventedRules",
3231
// invalidContact = 'invalidContact',
3332
// unknownLocation = 'unknownLocation',
3433
// invalidPostType = 'invalidPostType',
3534
}
3635

37-
export interface CircumventedRules {
38-
type: POST_FAILURE_REASONS.circumventedRules;
39-
recentEdit: boolean;
40-
}
4136
export interface PostFailureMissingType {
4237
type: POST_FAILURE_REASONS.missingType;
4338
}
@@ -69,7 +64,6 @@ export interface PostFailureReplyOrMention {
6964
type: POST_FAILURE_REASONS.replyOrMention;
7065
}
7166
export type PostFailures =
72-
| CircumventedRules
7367
| PostFailureMissingType
7468
| PostFailureInconsistentType
7569
| PostFailureTooFrequent

0 commit comments

Comments
 (0)