@fsvreddit/bot-bouncer-evaluation 0.7.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/allEvaluators.d.ts +16 -0
- package/dist/allEvaluators.js +72 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +6 -0
- package/dist/extendedDevvit.d.ts +36 -0
- package/dist/extendedDevvit.js +66 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +23 -0
- package/dist/userEvaluation/EvaluateBadDisplayname.d.ts +18 -0
- package/dist/userEvaluation/EvaluateBadDisplayname.js +81 -0
- package/dist/userEvaluation/EvaluateBadDisplaynameDefinedHandles.d.ts +16 -0
- package/dist/userEvaluation/EvaluateBadDisplaynameDefinedHandles.js +89 -0
- package/dist/userEvaluation/EvaluateBadUsername.d.ts +16 -0
- package/dist/userEvaluation/EvaluateBadUsername.js +75 -0
- package/dist/userEvaluation/EvaluateBioText.d.ts +18 -0
- package/dist/userEvaluation/EvaluateBioText.js +96 -0
- package/dist/userEvaluation/EvaluateBioTextDefinedHandles.d.ts +16 -0
- package/dist/userEvaluation/EvaluateBioTextDefinedHandles.js +99 -0
- package/dist/userEvaluation/EvaluateBotGroupAdvanced.d.ts +124 -0
- package/dist/userEvaluation/EvaluateBotGroupAdvanced.js +1360 -0
- package/dist/userEvaluation/EvaluateBotGroupAdvancedInternal.d.ts +6 -0
- package/dist/userEvaluation/EvaluateBotGroupAdvancedInternal.js +13 -0
- package/dist/userEvaluation/EvaluateBotGroupSubmitters.d.ts +8 -0
- package/dist/userEvaluation/EvaluateBotGroupSubmitters.js +23 -0
- package/dist/userEvaluation/EvaluateCommentPhrase.d.ts +16 -0
- package/dist/userEvaluation/EvaluateCommentPhrase.js +86 -0
- package/dist/userEvaluation/EvaluateDomainSharer.d.ts +18 -0
- package/dist/userEvaluation/EvaluateDomainSharer.js +138 -0
- package/dist/userEvaluation/EvaluateFirstCommentEmDash.d.ts +17 -0
- package/dist/userEvaluation/EvaluateFirstCommentEmDash.js +103 -0
- package/dist/userEvaluation/EvaluateFirstPostWithSelfComment.d.ts +14 -0
- package/dist/userEvaluation/EvaluateFirstPostWithSelfComment.js +53 -0
- package/dist/userEvaluation/EvaluateInconsistentAgeBot.d.ts +17 -0
- package/dist/userEvaluation/EvaluateInconsistentAgeBot.js +91 -0
- package/dist/userEvaluation/EvaluateInconsistentGenderBot.d.ts +17 -0
- package/dist/userEvaluation/EvaluateInconsistentGenderBot.js +99 -0
- package/dist/userEvaluation/EvaluateLinkReuse.d.ts +17 -0
- package/dist/userEvaluation/EvaluateLinkReuse.js +159 -0
- package/dist/userEvaluation/EvaluateMixedBot.d.ts +15 -0
- package/dist/userEvaluation/EvaluateMixedBot.js +82 -0
- package/dist/userEvaluation/EvaluateObfuscatedBioKeywords.d.ts +16 -0
- package/dist/userEvaluation/EvaluateObfuscatedBioKeywords.js +79 -0
- package/dist/userEvaluation/EvaluatePinnedPostTitle.d.ts +15 -0
- package/dist/userEvaluation/EvaluatePinnedPostTitle.js +77 -0
- package/dist/userEvaluation/EvaluatePostTitle.d.ts +16 -0
- package/dist/userEvaluation/EvaluatePostTitle.js +91 -0
- package/dist/userEvaluation/EvaluatePostTitleDefinedHandles.d.ts +15 -0
- package/dist/userEvaluation/EvaluatePostTitleDefinedHandles.js +109 -0
- package/dist/userEvaluation/EvaluatePostTitleMulti.d.ts +16 -0
- package/dist/userEvaluation/EvaluatePostTitleMulti.js +88 -0
- package/dist/userEvaluation/EvaluateRapidFireBot.d.ts +13 -0
- package/dist/userEvaluation/EvaluateRapidFireBot.js +48 -0
- package/dist/userEvaluation/EvaluateRepostBot.d.ts +19 -0
- package/dist/userEvaluation/EvaluateRepostBot.js +167 -0
- package/dist/userEvaluation/EvaluateSelfComment.d.ts +16 -0
- package/dist/userEvaluation/EvaluateSelfComment.js +74 -0
- package/dist/userEvaluation/EvaluateSocialLinks.d.ts +16 -0
- package/dist/userEvaluation/EvaluateSocialLinks.js +101 -0
- package/dist/userEvaluation/EvaluateSuspiciousFirstPost.d.ts +15 -0
- package/dist/userEvaluation/EvaluateSuspiciousFirstPost.js +68 -0
- package/dist/userEvaluation/EvaluateTGGroup.d.ts +16 -0
- package/dist/userEvaluation/EvaluateTGGroup.js +73 -0
- package/dist/userEvaluation/EvaluateTextInNsfwImages.d.ts +14 -0
- package/dist/userEvaluation/EvaluateTextInNsfwImages.js +169 -0
- package/dist/userEvaluation/EvaluateTitleCopyBot.d.ts +13 -0
- package/dist/userEvaluation/EvaluateTitleCopyBot.js +74 -0
- package/dist/userEvaluation/EvaluateWarmupBot.d.ts +15 -0
- package/dist/userEvaluation/EvaluateWarmupBot.js +89 -0
- package/dist/userEvaluation/EvaluateWorldTraveller.d.ts +18 -0
- package/dist/userEvaluation/EvaluateWorldTraveller.js +79 -0
- package/dist/userEvaluation/UserEvaluatorBase.d.ts +67 -0
- package/dist/userEvaluation/UserEvaluatorBase.js +109 -0
- package/dist/userEvaluation/evaluatorHelpers.d.ts +3 -0
- package/dist/userEvaluation/evaluatorHelpers.js +25 -0
- package/dist/userEvaluation/index.d.ts +26 -0
- package/dist/userEvaluation/index.js +42 -0
- package/dist/utility.d.ts +34 -0
- package/dist/utility.js +164 -0
- package/eslint.config.mjs +3 -0
- package/package.json +50 -0
- package/tsconfig.build.json +14 -0
- package/tsconfig.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Evaluation code for Bot Bouncer, a Dev Platform app that detects bots on Reddit.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EvaluatePinnedPostTitles } from "./userEvaluation/EvaluatePinnedPostTitle.js";
|
|
2
|
+
import { EvaluateBotGroupAdvanced } from "./userEvaluation/EvaluateBotGroupAdvanced.js";
|
|
3
|
+
import { EvaluateWarmupBot } from "./userEvaluation/EvaluateWarmupBot.js";
|
|
4
|
+
import { EvaluateBotGroupAdvancedInternal } from "./userEvaluation/EvaluateBotGroupAdvancedInternal.js";
|
|
5
|
+
import { EvaluateLinkReuse } from "./userEvaluation/EvaluateLinkReuse.js";
|
|
6
|
+
/**
|
|
7
|
+
* Array of all evaluators.
|
|
8
|
+
*
|
|
9
|
+
* In some scenarios, evaluators are run exactly in order, and may return true
|
|
10
|
+
* as soon as one evaluator detects a bot.
|
|
11
|
+
*
|
|
12
|
+
* As a result, order entries to prioritise faster evaluators that do not need to
|
|
13
|
+
* reference social links or account history first.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ALL_EVALUATORS: (typeof EvaluatePinnedPostTitles | typeof EvaluateBotGroupAdvanced | typeof EvaluateWarmupBot | typeof EvaluateLinkReuse)[];
|
|
16
|
+
export declare const ALL_INTERNAL_EVALUATORS: (typeof EvaluateBotGroupAdvancedInternal)[];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ALL_INTERNAL_EVALUATORS = exports.ALL_EVALUATORS = void 0;
|
|
4
|
+
const EvaluateDomainSharer_js_1 = require("./userEvaluation/EvaluateDomainSharer.js");
|
|
5
|
+
const EvaluateBadUsername_js_1 = require("./userEvaluation/EvaluateBadUsername.js");
|
|
6
|
+
const EvaluatePinnedPostTitle_js_1 = require("./userEvaluation/EvaluatePinnedPostTitle.js");
|
|
7
|
+
const EvaluateSelfComment_js_1 = require("./userEvaluation/EvaluateSelfComment.js");
|
|
8
|
+
const EvaluatePostTitle_js_1 = require("./userEvaluation/EvaluatePostTitle.js");
|
|
9
|
+
const EvaluateBioText_js_1 = require("./userEvaluation/EvaluateBioText.js");
|
|
10
|
+
const EvaluateObfuscatedBioKeywords_js_1 = require("./userEvaluation/EvaluateObfuscatedBioKeywords.js");
|
|
11
|
+
const EvaluateSocialLinks_js_1 = require("./userEvaluation/EvaluateSocialLinks.js");
|
|
12
|
+
const EvaluateSuspiciousFirstPost_js_1 = require("./userEvaluation/EvaluateSuspiciousFirstPost.js");
|
|
13
|
+
const EvaluateInconsistentAgeBot_js_1 = require("./userEvaluation/EvaluateInconsistentAgeBot.js");
|
|
14
|
+
const EvaluateInconsistentGenderBot_js_1 = require("./userEvaluation/EvaluateInconsistentGenderBot.js");
|
|
15
|
+
const EvaluateBadDisplayname_js_1 = require("./userEvaluation/EvaluateBadDisplayname.js");
|
|
16
|
+
const EvaluateWorldTraveller_js_1 = require("./userEvaluation/EvaluateWorldTraveller.js");
|
|
17
|
+
const EvaluateCommentPhrase_js_1 = require("./userEvaluation/EvaluateCommentPhrase.js");
|
|
18
|
+
const EvaluateTGGroup_js_1 = require("./userEvaluation/EvaluateTGGroup.js");
|
|
19
|
+
const EvaluateBotGroupAdvanced_js_1 = require("./userEvaluation/EvaluateBotGroupAdvanced.js");
|
|
20
|
+
const EvaluateBioTextDefinedHandles_js_1 = require("./userEvaluation/EvaluateBioTextDefinedHandles.js");
|
|
21
|
+
const EvaluatePostTitleDefinedHandles_js_1 = require("./userEvaluation/EvaluatePostTitleDefinedHandles.js");
|
|
22
|
+
const EvaluateBadDisplaynameDefinedHandles_js_1 = require("./userEvaluation/EvaluateBadDisplaynameDefinedHandles.js");
|
|
23
|
+
const EvaluatePostTitleMulti_js_1 = require("./userEvaluation/EvaluatePostTitleMulti.js");
|
|
24
|
+
const EvaluateWarmupBot_js_1 = require("./userEvaluation/EvaluateWarmupBot.js");
|
|
25
|
+
const EvaluateBotGroupAdvancedInternal_js_1 = require("./userEvaluation/EvaluateBotGroupAdvancedInternal.js");
|
|
26
|
+
const EvaluateTitleCopyBot_js_1 = require("./userEvaluation/EvaluateTitleCopyBot.js");
|
|
27
|
+
const EvaluateTextInNsfwImages_js_1 = require("./userEvaluation/EvaluateTextInNsfwImages.js");
|
|
28
|
+
const EvaluateRepostBot_js_1 = require("./userEvaluation/EvaluateRepostBot.js");
|
|
29
|
+
const EvaluateLinkReuse_js_1 = require("./userEvaluation/EvaluateLinkReuse.js");
|
|
30
|
+
/**
|
|
31
|
+
* Array of all evaluators.
|
|
32
|
+
*
|
|
33
|
+
* In some scenarios, evaluators are run exactly in order, and may return true
|
|
34
|
+
* as soon as one evaluator detects a bot.
|
|
35
|
+
*
|
|
36
|
+
* As a result, order entries to prioritise faster evaluators that do not need to
|
|
37
|
+
* reference social links or account history first.
|
|
38
|
+
*/
|
|
39
|
+
exports.ALL_EVALUATORS = [
|
|
40
|
+
// Evaluators that can work based on the UserExtended object only
|
|
41
|
+
EvaluateBadUsername_js_1.EvaluateBadUsername,
|
|
42
|
+
EvaluateBioText_js_1.EvaluateBioText,
|
|
43
|
+
EvaluateBioTextDefinedHandles_js_1.EvaluateBioTextDefinedHandles,
|
|
44
|
+
EvaluateBadDisplayname_js_1.EvaluateBadDisplayName,
|
|
45
|
+
EvaluateBadDisplaynameDefinedHandles_js_1.EvaluateBadDisplayNameDefinedHandles,
|
|
46
|
+
EvaluateObfuscatedBioKeywords_js_1.EvaluateObfuscatedBioKeywords,
|
|
47
|
+
// Evaluators that reference posts and comments, but not social links
|
|
48
|
+
EvaluateDomainSharer_js_1.EvaluateDomainSharer,
|
|
49
|
+
EvaluatePinnedPostTitle_js_1.EvaluatePinnedPostTitles,
|
|
50
|
+
EvaluateSelfComment_js_1.EvaluateSelfComment,
|
|
51
|
+
EvaluatePostTitle_js_1.EvaluatePostTitle,
|
|
52
|
+
EvaluatePostTitleDefinedHandles_js_1.EvaluatePostTitleDefinedHandles,
|
|
53
|
+
EvaluatePostTitleMulti_js_1.EvaluatePostTitleMulti,
|
|
54
|
+
EvaluateSuspiciousFirstPost_js_1.EvaluateSuspiciousFirstPost,
|
|
55
|
+
EvaluateInconsistentAgeBot_js_1.EvaluateInconsistentAgeBot,
|
|
56
|
+
EvaluateInconsistentGenderBot_js_1.EvaluateInconsistentGenderBot,
|
|
57
|
+
EvaluateWorldTraveller_js_1.EvaluateWorldTraveller,
|
|
58
|
+
EvaluateCommentPhrase_js_1.EvaluateCommentPhrase,
|
|
59
|
+
EvaluateTGGroup_js_1.EvaluateTGGroup,
|
|
60
|
+
// Evaluators that need social links or other complicated data should be at the end
|
|
61
|
+
EvaluateWarmupBot_js_1.EvaluateWarmupBot,
|
|
62
|
+
EvaluateSocialLinks_js_1.EvaluateSocialLinks,
|
|
63
|
+
EvaluateBotGroupAdvanced_js_1.EvaluateBotGroupAdvanced,
|
|
64
|
+
EvaluateTitleCopyBot_js_1.EvaluateTitleCopyBot,
|
|
65
|
+
EvaluateLinkReuse_js_1.EvaluateLinkReuse,
|
|
66
|
+
EvaluateTextInNsfwImages_js_1.EvaluateTextInNsfwImages,
|
|
67
|
+
EvaluateRepostBot_js_1.EvaluateRepostBot,
|
|
68
|
+
];
|
|
69
|
+
// Evaluators that will only run on internal tools and not subreddits that may be out of date.
|
|
70
|
+
exports.ALL_INTERNAL_EVALUATORS = [
|
|
71
|
+
EvaluateBotGroupAdvancedInternal_js_1.EvaluateBotGroupAdvancedInternal,
|
|
72
|
+
];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SUBMITTER_BOT_NAME = exports.MAIN_APP_NAME = exports.CONTROL_SUBREDDIT = void 0;
|
|
4
|
+
exports.CONTROL_SUBREDDIT = "BotBouncer";
|
|
5
|
+
exports.MAIN_APP_NAME = "bot-bouncer";
|
|
6
|
+
exports.SUBMITTER_BOT_NAME = "botgroupadvancedsubmitters";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Devvit, TriggerContext, User } from "@devvit/public-api";
|
|
2
|
+
import * as protos from "@devvit/protos";
|
|
3
|
+
export interface RedditAPIPlugins {
|
|
4
|
+
NewModmail: protos.NewModmail;
|
|
5
|
+
Widgets: protos.Widgets;
|
|
6
|
+
ModNote: protos.ModNote;
|
|
7
|
+
LinksAndComments: protos.LinksAndComments;
|
|
8
|
+
Moderation: protos.Moderation;
|
|
9
|
+
GraphQL: protos.GraphQL;
|
|
10
|
+
Listings: protos.Listings;
|
|
11
|
+
Flair: protos.Flair;
|
|
12
|
+
Wiki: protos.Wiki;
|
|
13
|
+
Users: protos.Users;
|
|
14
|
+
PrivateMessages: protos.PrivateMessages;
|
|
15
|
+
Subreddits: protos.Subreddits;
|
|
16
|
+
}
|
|
17
|
+
export type ExtendedDevvit = typeof Devvit & {
|
|
18
|
+
redditAPIPlugins: RedditAPIPlugins;
|
|
19
|
+
};
|
|
20
|
+
export declare function getExtendedDevvit(): ExtendedDevvit;
|
|
21
|
+
export interface UserExtended {
|
|
22
|
+
createdAt: Date;
|
|
23
|
+
commentKarma: number;
|
|
24
|
+
displayName?: string;
|
|
25
|
+
hasVerifiedEmail: boolean;
|
|
26
|
+
id: string;
|
|
27
|
+
isAdmin: boolean;
|
|
28
|
+
isGold: boolean;
|
|
29
|
+
isModerator: boolean;
|
|
30
|
+
linkKarma: number;
|
|
31
|
+
nsfw: boolean;
|
|
32
|
+
username: string;
|
|
33
|
+
userDescription?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function getUserExtended(username: string, context: TriggerContext): Promise<UserExtended | undefined>;
|
|
36
|
+
export declare function getUserExtendedFromUser(user: User, context: TriggerContext): Promise<UserExtended>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getExtendedDevvit = getExtendedDevvit;
|
|
4
|
+
exports.getUserExtended = getUserExtended;
|
|
5
|
+
exports.getUserExtendedFromUser = getUserExtendedFromUser;
|
|
6
|
+
const public_api_1 = require("@devvit/public-api");
|
|
7
|
+
function getExtendedDevvit() {
|
|
8
|
+
return public_api_1.Devvit; // The Devvit object already has the extended properties, they are simply not reflected in the public type definition.
|
|
9
|
+
}
|
|
10
|
+
async function getRawUserData(username, metadata) {
|
|
11
|
+
let userAboutResponse;
|
|
12
|
+
try {
|
|
13
|
+
userAboutResponse = await getExtendedDevvit().redditAPIPlugins.Users.UserAbout({ username }, metadata);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (error instanceof Error && (error.message.includes("404 Not Found") || error.message.includes("403 Forbidden"))) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
throw error; // Rethrow the error if it's not a 404 or 403
|
|
20
|
+
}
|
|
21
|
+
return userAboutResponse;
|
|
22
|
+
}
|
|
23
|
+
async function getUserExtended(username, context) {
|
|
24
|
+
const rawUserData = await getRawUserData(username, context.metadata);
|
|
25
|
+
if (!rawUserData?.data) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const userExtendedVal = {
|
|
29
|
+
createdAt: new Date((rawUserData.data.created ?? 0) * 1000),
|
|
30
|
+
commentKarma: rawUserData.data.commentKarma ?? 0,
|
|
31
|
+
displayName: rawUserData.data.subreddit?.title,
|
|
32
|
+
hasVerifiedEmail: rawUserData.data.hasVerifiedEmail ?? false,
|
|
33
|
+
id: `t2_${rawUserData.data.id ?? ""}`,
|
|
34
|
+
isAdmin: rawUserData.data.isEmployee ?? false,
|
|
35
|
+
isGold: rawUserData.data.isGold ?? false,
|
|
36
|
+
isModerator: rawUserData.data.isMod ?? false,
|
|
37
|
+
linkKarma: rawUserData.data.linkKarma ?? 0,
|
|
38
|
+
nsfw: rawUserData.data.subreddit?.over18 ?? false,
|
|
39
|
+
username: rawUserData.data.name ?? "",
|
|
40
|
+
userDescription: rawUserData.data.subreddit?.publicDescription,
|
|
41
|
+
};
|
|
42
|
+
return userExtendedVal;
|
|
43
|
+
}
|
|
44
|
+
async function getUserExtendedFromUser(user, context) {
|
|
45
|
+
try {
|
|
46
|
+
const userExtended = await getUserExtended(user.username, context);
|
|
47
|
+
if (userExtended) {
|
|
48
|
+
return userExtended;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
//
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
createdAt: user.createdAt,
|
|
56
|
+
commentKarma: user.commentKarma,
|
|
57
|
+
hasVerifiedEmail: user.hasVerifiedEmail,
|
|
58
|
+
id: user.id,
|
|
59
|
+
isAdmin: user.isAdmin,
|
|
60
|
+
isGold: false,
|
|
61
|
+
isModerator: false,
|
|
62
|
+
linkKarma: user.linkKarma,
|
|
63
|
+
nsfw: user.nsfw,
|
|
64
|
+
username: user.username,
|
|
65
|
+
};
|
|
66
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.getSocialLinksWithCache = exports.yamlToVariables = void 0;
|
|
18
|
+
__exportStar(require("./allEvaluators"), exports);
|
|
19
|
+
__exportStar(require("./userEvaluation"), exports);
|
|
20
|
+
var utility_1 = require("./utility");
|
|
21
|
+
Object.defineProperty(exports, "yamlToVariables", { enumerable: true, get: function () { return utility_1.yamlToVariables; } });
|
|
22
|
+
var evaluatorHelpers_1 = require("./userEvaluation/evaluatorHelpers");
|
|
23
|
+
Object.defineProperty(exports, "getSocialLinksWithCache", { enumerable: true, get: function () { return evaluatorHelpers_1.getSocialLinksWithCache; } });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Post } from "@devvit/public-api";
|
|
2
|
+
import { CommentCreate } from "@devvit/protos";
|
|
3
|
+
import { EvaluatorRegex, UserEvaluatorBase, ValidationIssue } from "./UserEvaluatorBase.js";
|
|
4
|
+
import { UserExtended } from "@fsvreddit/fsv-devvit-helpers";
|
|
5
|
+
export declare class EvaluateBadDisplayName extends UserEvaluatorBase {
|
|
6
|
+
name: string;
|
|
7
|
+
shortname: string;
|
|
8
|
+
banContentThreshold: number;
|
|
9
|
+
private badDisplayNameRegexes;
|
|
10
|
+
private getBadDisplayNameRegexes;
|
|
11
|
+
private isBadDisplayName;
|
|
12
|
+
gatherRegexes(): EvaluatorRegex[];
|
|
13
|
+
validateVariables(): ValidationIssue[];
|
|
14
|
+
preEvaluateComment(_: CommentCreate): boolean;
|
|
15
|
+
preEvaluatePost(_: Post): boolean;
|
|
16
|
+
preEvaluateUser(user: UserExtended): boolean;
|
|
17
|
+
evaluate(_user: UserExtended): boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EvaluateBadDisplayName = void 0;
|
|
7
|
+
const UserEvaluatorBase_js_1 = require("./UserEvaluatorBase.js");
|
|
8
|
+
const markdown_escape_1 = __importDefault(require("markdown-escape"));
|
|
9
|
+
const lodash_1 = require("lodash");
|
|
10
|
+
class EvaluateBadDisplayName extends UserEvaluatorBase_js_1.UserEvaluatorBase {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.name = "Bad Display Name Bot";
|
|
14
|
+
this.shortname = "baddisplayname";
|
|
15
|
+
this.banContentThreshold = 0;
|
|
16
|
+
}
|
|
17
|
+
getBadDisplayNameRegexes() {
|
|
18
|
+
if (this.badDisplayNameRegexes === undefined) {
|
|
19
|
+
const bannableDisplayNameRegexes = this.getVariable("regexes", []);
|
|
20
|
+
const ignoredDisplayNameRegexes = this.getVariable("ignoredRegexes", []);
|
|
21
|
+
this.badDisplayNameRegexes = bannableDisplayNameRegexes.filter(regex => !ignoredDisplayNameRegexes.includes(regex));
|
|
22
|
+
}
|
|
23
|
+
return this.badDisplayNameRegexes;
|
|
24
|
+
}
|
|
25
|
+
isBadDisplayName(displayName) {
|
|
26
|
+
if (!displayName) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const regexes = this.getBadDisplayNameRegexes();
|
|
30
|
+
const matchedRegex = regexes.find(regex => new RegExp(regex, "u").test(displayName));
|
|
31
|
+
if (matchedRegex) {
|
|
32
|
+
this.addHitReason(`Display name matches regex: ${(0, markdown_escape_1.default)(matchedRegex)}`);
|
|
33
|
+
}
|
|
34
|
+
return matchedRegex !== undefined;
|
|
35
|
+
}
|
|
36
|
+
gatherRegexes() {
|
|
37
|
+
const regexes = this.getVariable("regexes", []);
|
|
38
|
+
return (0, lodash_1.uniq)(regexes.map(regex => ({
|
|
39
|
+
evaluatorName: this.name,
|
|
40
|
+
regex,
|
|
41
|
+
flags: "u",
|
|
42
|
+
})));
|
|
43
|
+
}
|
|
44
|
+
validateVariables() {
|
|
45
|
+
const regexes = this.gatherRegexes().map(r => r.regex);
|
|
46
|
+
const results = [];
|
|
47
|
+
for (const regexVal of regexes) {
|
|
48
|
+
let regex;
|
|
49
|
+
try {
|
|
50
|
+
regex = new RegExp(regexVal, "u");
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
results.push({ severity: "error", message: `Invalid regex in baddisplayname: ${regexVal}` });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (regex.test("")) {
|
|
57
|
+
results.push({ severity: "error", message: `Display name regex is too greedy: ${regexVal}` });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
63
|
+
preEvaluateComment(_) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
67
|
+
preEvaluatePost(_) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
preEvaluateUser(user) {
|
|
71
|
+
if (!this.isBadDisplayName(user.displayName)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return user.commentKarma < 100;
|
|
75
|
+
}
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
77
|
+
evaluate(_user) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.EvaluateBadDisplayName = EvaluateBadDisplayName;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Post } from "@devvit/public-api";
|
|
2
|
+
import { CommentCreate } from "@devvit/protos";
|
|
3
|
+
import { EvaluatorRegex, UserEvaluatorBase, ValidationIssue } from "./UserEvaluatorBase.js";
|
|
4
|
+
import { UserExtended } from "@fsvreddit/fsv-devvit-helpers";
|
|
5
|
+
export declare class EvaluateBadDisplayNameDefinedHandles extends UserEvaluatorBase {
|
|
6
|
+
name: string;
|
|
7
|
+
shortname: string;
|
|
8
|
+
banContentThreshold: number;
|
|
9
|
+
private isBadDisplayName;
|
|
10
|
+
gatherRegexes(): EvaluatorRegex[];
|
|
11
|
+
validateVariables(): ValidationIssue[];
|
|
12
|
+
preEvaluateComment(_: CommentCreate): boolean;
|
|
13
|
+
preEvaluatePost(_: Post): boolean;
|
|
14
|
+
preEvaluateUser(user: UserExtended): boolean;
|
|
15
|
+
evaluate(_user: UserExtended): boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EvaluateBadDisplayNameDefinedHandles = void 0;
|
|
4
|
+
const UserEvaluatorBase_js_1 = require("./UserEvaluatorBase.js");
|
|
5
|
+
const lodash_1 = require("lodash");
|
|
6
|
+
const regjsparser_1 = require("regjsparser");
|
|
7
|
+
class EvaluateBadDisplayNameDefinedHandles extends UserEvaluatorBase_js_1.UserEvaluatorBase {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.name = "Bad Display Name Defined Handle Bot";
|
|
11
|
+
this.shortname = "baddisplaynamedefinedhandles";
|
|
12
|
+
this.banContentThreshold = 0;
|
|
13
|
+
}
|
|
14
|
+
isBadDisplayName(displayName) {
|
|
15
|
+
if (!displayName) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const regexes = this.gatherRegexes().map(r => r.regex);
|
|
19
|
+
const matchedRegexes = regexes.filter(regex => new RegExp(regex, "u").test(displayName));
|
|
20
|
+
if (matchedRegexes.length === 0) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
this.addHitReason(`Display name matches regexes: ${matchedRegexes.map(r => `\`${r}\``).join(", ")}`);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
gatherRegexes() {
|
|
27
|
+
const prefix = this.getVariable("prefix", "");
|
|
28
|
+
const suffix = this.getVariable("suffix", "");
|
|
29
|
+
const definedHandles = this.getModuleVariable("substitutions", "definedhandles", "");
|
|
30
|
+
if (!definedHandles) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
const parsed = (0, regjsparser_1.parse)(definedHandles, "u");
|
|
34
|
+
if (parsed.type !== "disjunction") {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const regexes = parsed.body.map(part => `${prefix}${part.raw}${suffix}`);
|
|
38
|
+
return (0, lodash_1.uniq)(regexes.map(regex => ({
|
|
39
|
+
evaluatorName: this.name,
|
|
40
|
+
regex,
|
|
41
|
+
flags: "u",
|
|
42
|
+
})));
|
|
43
|
+
}
|
|
44
|
+
validateVariables() {
|
|
45
|
+
const results = [];
|
|
46
|
+
let regexes;
|
|
47
|
+
try {
|
|
48
|
+
regexes = this.gatherRegexes().map(r => r.regex);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
52
|
+
results.push({ severity: "error", message: `Invalid defined handles list: ${message}` });
|
|
53
|
+
return results;
|
|
54
|
+
}
|
|
55
|
+
for (const regexVal of regexes) {
|
|
56
|
+
let regex;
|
|
57
|
+
try {
|
|
58
|
+
regex = new RegExp(regexVal, "u");
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
results.push({ severity: "error", message: `Invalid regex in baddisplaynamedefinedhandles: ${regexVal}` });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (regex.test("")) {
|
|
65
|
+
results.push({ severity: "error", message: `Display name defined handle regex is too greedy: ${regexVal}` });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
71
|
+
preEvaluateComment(_) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
75
|
+
preEvaluatePost(_) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
preEvaluateUser(user) {
|
|
79
|
+
if (!this.isBadDisplayName(user.displayName)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return user.commentKarma < 100;
|
|
83
|
+
}
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
85
|
+
evaluate(_user) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.EvaluateBadDisplayNameDefinedHandles = EvaluateBadDisplayNameDefinedHandles;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Post } from "@devvit/public-api";
|
|
2
|
+
import { CommentCreate } from "@devvit/protos";
|
|
3
|
+
import { EvaluatorRegex, UserEvaluatorBase, ValidationIssue } from "./UserEvaluatorBase.js";
|
|
4
|
+
import { UserExtended } from "@fsvreddit/fsv-devvit-helpers";
|
|
5
|
+
export declare class EvaluateBadUsername extends UserEvaluatorBase {
|
|
6
|
+
name: string;
|
|
7
|
+
shortname: string;
|
|
8
|
+
banContentThreshold: number;
|
|
9
|
+
private isBadUsername;
|
|
10
|
+
validateVariables(): ValidationIssue[];
|
|
11
|
+
gatherRegexes(): EvaluatorRegex[];
|
|
12
|
+
preEvaluateComment(event: CommentCreate): boolean;
|
|
13
|
+
preEvaluatePost(post: Post): boolean;
|
|
14
|
+
preEvaluateUser(user: UserExtended): boolean;
|
|
15
|
+
evaluate(_user: UserExtended): boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EvaluateBadUsername = void 0;
|
|
7
|
+
const UserEvaluatorBase_js_1 = require("./UserEvaluatorBase.js");
|
|
8
|
+
const date_fns_1 = require("date-fns");
|
|
9
|
+
const markdown_escape_1 = __importDefault(require("markdown-escape"));
|
|
10
|
+
const lodash_1 = require("lodash");
|
|
11
|
+
class EvaluateBadUsername extends UserEvaluatorBase_js_1.UserEvaluatorBase {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
this.name = "Bad Username Bot";
|
|
15
|
+
this.shortname = "badusername";
|
|
16
|
+
this.banContentThreshold = 0;
|
|
17
|
+
}
|
|
18
|
+
isBadUsername(username) {
|
|
19
|
+
if (!username) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const regexes = this.getVariable("regexes", []);
|
|
23
|
+
const matchedRegex = regexes.find(regex => new RegExp(regex).test(username));
|
|
24
|
+
if (matchedRegex) {
|
|
25
|
+
this.addHitReason(`Username matches regex: ${(0, markdown_escape_1.default)(matchedRegex)}`);
|
|
26
|
+
}
|
|
27
|
+
return matchedRegex !== undefined;
|
|
28
|
+
}
|
|
29
|
+
validateVariables() {
|
|
30
|
+
const results = [];
|
|
31
|
+
const regexes = this.getVariable("regexes", []);
|
|
32
|
+
for (const regexVal of regexes) {
|
|
33
|
+
let regex;
|
|
34
|
+
try {
|
|
35
|
+
regex = new RegExp(regexVal);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
results.push({ severity: "error", message: `Invalid regex in badusername: ${regexVal}` });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (regex.test("")) {
|
|
42
|
+
results.push({ severity: "error", message: `Bad username regex is too greedy: ${regexVal}` });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
gatherRegexes() {
|
|
48
|
+
const regexes = this.getVariable("regexes", []);
|
|
49
|
+
return (0, lodash_1.uniq)(regexes.map(regex => ({
|
|
50
|
+
evaluatorName: this.name,
|
|
51
|
+
regex,
|
|
52
|
+
})));
|
|
53
|
+
}
|
|
54
|
+
preEvaluateComment(event) {
|
|
55
|
+
return this.isBadUsername(event.author?.name);
|
|
56
|
+
}
|
|
57
|
+
preEvaluatePost(post) {
|
|
58
|
+
return this.isBadUsername(post.authorName);
|
|
59
|
+
}
|
|
60
|
+
preEvaluateUser(user) {
|
|
61
|
+
if (!this.isBadUsername(user.username)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const maxAgeWeeks = this.getVariable("maxageweeks", 4);
|
|
65
|
+
if (user.createdAt < (0, date_fns_1.subWeeks)(new Date(), maxAgeWeeks)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
71
|
+
evaluate(_user) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.EvaluateBadUsername = EvaluateBadUsername;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Post } from "@devvit/public-api";
|
|
2
|
+
import { CommentCreate } from "@devvit/protos";
|
|
3
|
+
import { EvaluatorRegex, UserEvaluatorBase, ValidationIssue } from "./UserEvaluatorBase.js";
|
|
4
|
+
import { UserExtended } from "@fsvreddit/fsv-devvit-helpers";
|
|
5
|
+
export declare class EvaluateBioText extends UserEvaluatorBase {
|
|
6
|
+
name: string;
|
|
7
|
+
shortname: string;
|
|
8
|
+
banContentThreshold: number;
|
|
9
|
+
private bioText;
|
|
10
|
+
private getBioText;
|
|
11
|
+
preEvaluateComment(event: CommentCreate): boolean;
|
|
12
|
+
validateVariables(): ValidationIssue[];
|
|
13
|
+
getVariableOverrides(): Record<string, unknown>;
|
|
14
|
+
gatherRegexes(): EvaluatorRegex[];
|
|
15
|
+
preEvaluatePost(_: Post): boolean;
|
|
16
|
+
preEvaluateUser(user: UserExtended): boolean;
|
|
17
|
+
evaluate(user: UserExtended): boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EvaluateBioText = void 0;
|
|
7
|
+
const UserEvaluatorBase_js_1 = require("./UserEvaluatorBase.js");
|
|
8
|
+
const markdown_escape_1 = __importDefault(require("markdown-escape"));
|
|
9
|
+
class EvaluateBioText extends UserEvaluatorBase_js_1.UserEvaluatorBase {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.name = "Bio Text Bot";
|
|
13
|
+
this.shortname = "biotext";
|
|
14
|
+
this.banContentThreshold = 0;
|
|
15
|
+
}
|
|
16
|
+
getBioText() {
|
|
17
|
+
if (this.bioText === undefined) {
|
|
18
|
+
const bannableBioText = this.getVariable("bantext", []);
|
|
19
|
+
const ignoredBanText = this.getVariable("ignoredBanText", []);
|
|
20
|
+
this.bioText = bannableBioText.filter(bioText => !ignoredBanText.includes(bioText));
|
|
21
|
+
}
|
|
22
|
+
return this.bioText;
|
|
23
|
+
}
|
|
24
|
+
preEvaluateComment(event) {
|
|
25
|
+
const problematicBioText = this.getBioText();
|
|
26
|
+
return problematicBioText.some(bioText => event.author?.description && new RegExp(bioText, "u").test(event.author.description));
|
|
27
|
+
}
|
|
28
|
+
validateVariables() {
|
|
29
|
+
const results = [];
|
|
30
|
+
const regexes = this.getVariable("bantext", []);
|
|
31
|
+
for (const regexVal of regexes) {
|
|
32
|
+
let regex;
|
|
33
|
+
try {
|
|
34
|
+
regex = new RegExp(regexVal);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
results.push({ severity: "error", message: `Invalid regex in biotext: ${regexVal}` });
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (regex.test("")) {
|
|
41
|
+
results.push({ severity: "error", message: `Bio Text regex is too greedy: ${regexVal}` });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (this.getVariable("reporttext", []).length > 0) {
|
|
45
|
+
results.push({ severity: "warning", message: "The reporttext variable is obsolete, and should be left empty." });
|
|
46
|
+
}
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
getVariableOverrides() {
|
|
50
|
+
const bannableBioText = this.getVariable("bantext", []);
|
|
51
|
+
const results = {};
|
|
52
|
+
if (bannableBioText.some(r => Array.isArray(r))) {
|
|
53
|
+
results.bantext = bannableBioText.flat();
|
|
54
|
+
}
|
|
55
|
+
return results;
|
|
56
|
+
}
|
|
57
|
+
gatherRegexes() {
|
|
58
|
+
const bannableBioText = this.getVariable("bantext", []);
|
|
59
|
+
return bannableBioText.map(regex => ({
|
|
60
|
+
evaluatorName: this.name,
|
|
61
|
+
regex,
|
|
62
|
+
flags: "u",
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
66
|
+
preEvaluatePost(_) {
|
|
67
|
+
const bannableBioText = this.getBioText();
|
|
68
|
+
return bannableBioText.length > 0;
|
|
69
|
+
}
|
|
70
|
+
preEvaluateUser(user) {
|
|
71
|
+
const bannableBioText = this.getBioText();
|
|
72
|
+
if (bannableBioText.length === 0) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (user.commentKarma > 2000 && user.linkKarma > 2000) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return bannableBioText.some(bioText => user.userDescription && new RegExp(bioText, "u").test(user.userDescription));
|
|
79
|
+
}
|
|
80
|
+
evaluate(user) {
|
|
81
|
+
const bannableBioText = this.getBioText();
|
|
82
|
+
if (bannableBioText.length === 0) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const bannableBioTextFound = bannableBioText.find(bio => user.userDescription && new RegExp(bio, "u").test(user.userDescription));
|
|
86
|
+
if (bannableBioTextFound) {
|
|
87
|
+
this.canAutoBan = true;
|
|
88
|
+
this.addHitReason(`Bio text matched regex: ${(0, markdown_escape_1.default)(bannableBioTextFound)}`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return user.nsfw || this.getPosts().some(post => post.isNsfw());
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.EvaluateBioText = EvaluateBioText;
|