mirror of
https://github.com/FoxxMD/context-mod.git
synced 2026-01-14 07:57:57 -05:00
Compare commits
10 Commits
streamBuff
...
banCriteri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e36325278f | ||
|
|
8080a0b058 | ||
|
|
f7dc9222d6 | ||
|
|
021e5c524b | ||
|
|
e5fe4589e0 | ||
|
|
580a9c8fe6 | ||
|
|
ef372e531e | ||
|
|
fde2836208 | ||
|
|
021dd5b0c5 | ||
|
|
5bd38d367a |
@@ -61,13 +61,14 @@ All Actions with `content` have access to this data:
|
||||
|
||||
Additionally, `author` has these properties accessible:
|
||||
|
||||
| Name | Description | Example |
|
||||
|----------------|-------------------------------------|----------|
|
||||
| `age` | (Approximate) Age of account | 3 months |
|
||||
| `linkKarma` | Amount of link karma | 10 |
|
||||
| `commentKarma` | Amount of comment karma | 3 |
|
||||
| `totalKarma` | Combined link+comment karma | 13 |
|
||||
| `verified` | Does account have a verified email? | true |
|
||||
| Name | Description | Example |
|
||||
|----------------|-----------------------------------------------------------------------------------|------------|
|
||||
| `age` | (Approximate) Age of account | 3 months |
|
||||
| `linkKarma` | Amount of link karma | 10 |
|
||||
| `commentKarma` | Amount of comment karma | 3 |
|
||||
| `totalKarma` | Combined link+comment karma | 13 |
|
||||
| `verified` | Does account have a verified email? | true |
|
||||
| `flairText` | The text of the Flair assigned to the Author in this subreddit, if one is present | Test Flair |
|
||||
|
||||
NOTE: Accessing these properties may require an additional API call so use sparingly on high-volume comments
|
||||
|
||||
@@ -84,13 +85,14 @@ Produces:
|
||||
|
||||
If the **Activity** is a Submission these additional properties are accessible:
|
||||
|
||||
| Name | Description | Example |
|
||||
|---------------|-----------------------------------------------------------------|-------------------------|
|
||||
| `upvoteRatio` | The upvote ratio | 100% |
|
||||
| `nsfw` | If the submission is marked as NSFW | true |
|
||||
| `spoiler` | If the submission is marked as a spoiler | true |
|
||||
| `url` | If the submission was a link then this is the URL for that link | http://example.com |
|
||||
| `title` | The title of the submission | Test post please ignore |
|
||||
| Name | Description | Example |
|
||||
|-------------------|-----------------------------------------------------------------|-------------------------|
|
||||
| `upvoteRatio` | The upvote ratio | 100% |
|
||||
| `nsfw` | If the submission is marked as NSFW | true |
|
||||
| `spoiler` | If the submission is marked as a spoiler | true |
|
||||
| `url` | If the submission was a link then this is the URL for that link | http://example.com |
|
||||
| `title` | The title of the submission | Test post please ignore |
|
||||
| `link_flair_text` | The flair text assigned to this submission | Test Flair |
|
||||
|
||||
### Comments
|
||||
|
||||
|
||||
@@ -67,13 +67,15 @@ export class BanAction extends Action {
|
||||
// @ts-ignore
|
||||
const fetchedSub = await item.subreddit.fetch();
|
||||
const fetchedName = await item.author.name;
|
||||
const bannedUser = await fetchedSub.banUser({
|
||||
const banData = {
|
||||
name: fetchedName,
|
||||
banMessage: renderedContent === undefined ? undefined : renderedContent,
|
||||
banReason: renderedReason,
|
||||
banNote: renderedNote,
|
||||
duration: this.duration
|
||||
});
|
||||
};
|
||||
const bannedUser = await fetchedSub.banUser(banData);
|
||||
await this.resources.addUserToSubredditBannedUserCache(banData)
|
||||
touchedEntities.push(bannedUser);
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -43,11 +43,7 @@ export class FlairAction extends Action {
|
||||
if (item instanceof Submission) {
|
||||
if(!this.dryRun) {
|
||||
if (this.flair_template_id) {
|
||||
// typings are wrong for this function, flair_template_id should be accepted
|
||||
// assignFlair uses /api/flair (mod endpoint)
|
||||
// selectFlair uses /api/selectflair (self endpoint for user to choose their own flair for submission)
|
||||
// @ts-ignore
|
||||
await item.assignFlair({flair_template_id: this.flair_template_id}).then(() => {});
|
||||
await item.selectFlair({flair_template_id: this.flair_template_id}).then(() => {});
|
||||
item.link_flair_template_id = this.flair_template_id;
|
||||
} else {
|
||||
await item.assignFlair({text: renderedText, cssClass: renderedCss}).then(() => {});
|
||||
|
||||
@@ -408,3 +408,9 @@ export interface RuleResultsTemplateData {
|
||||
export interface GenericContentTemplateData extends BaseTemplateData, Partial<RuleResultsTemplateData>, Partial<ActionResultsTemplateData> {
|
||||
item?: (SubmissionTemplateData | CommentTemplateData)
|
||||
}
|
||||
|
||||
export type SubredditPlaceholderType = '{{subreddit}}';
|
||||
export const subredditPlaceholder: SubredditPlaceholderType = '{{subreddit}}';
|
||||
export const asSubredditPlaceholder = (val: any): val is SubredditPlaceholderType => {
|
||||
return typeof val === 'string' && val.toLowerCase() === '{{subreddit}}';
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
DurationComparor,
|
||||
ModeratorNameCriteria,
|
||||
ModeratorNames, ModActionType,
|
||||
ModUserNoteLabel, RelativeDateTimeMatch
|
||||
ModUserNoteLabel, RelativeDateTimeMatch, SubredditPlaceholderType
|
||||
} from "../Atomic";
|
||||
import {ActivityType, MaybeActivityType} from "../Reddit";
|
||||
import {GenericComparison, parseGenericValueComparison} from "../Comparisons";
|
||||
@@ -57,7 +57,7 @@ export interface SubredditCriteria {
|
||||
}
|
||||
|
||||
export interface StrongSubredditCriteria extends SubredditCriteria {
|
||||
name?: RegExp
|
||||
name?: RegExp | SubredditPlaceholderType
|
||||
}
|
||||
|
||||
export const defaultStrongSubredditCriteriaOptions = {
|
||||
@@ -289,7 +289,57 @@ export const toFullModLogCriteria = (val: ModLogCriteria): FullModLogCriteria =>
|
||||
}, {});
|
||||
}
|
||||
|
||||
export const authorCriteriaProperties = ['name', 'flairCssClass', 'flairText', 'flairTemplate', 'isMod', 'userNotes', 'modActions', 'age', 'linkKarma', 'commentKarma', 'totalKarma', 'verified', 'shadowBanned', 'description', 'isContributor'];
|
||||
export const authorCriteriaProperties = ['name', 'flairCssClass', 'flairText', 'flairTemplate', 'isMod', 'userNotes', 'modActions', 'age', 'linkKarma', 'commentKarma', 'totalKarma', 'verified', 'shadowBanned', 'description', 'isContributor', 'banned'];
|
||||
|
||||
export interface BanCriteria {
|
||||
/**
|
||||
* Test when the Author was banned against this comparison
|
||||
*
|
||||
* The syntax is `(< OR > OR <= OR >=) <number> <unit>`
|
||||
*
|
||||
* * EX `> 100 days` => Passes if Author was banned more than 100 days ago
|
||||
* * EX `<= 2 months` => Passes if Author was banned less than or equal to 2 months ago
|
||||
*
|
||||
* Unit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)
|
||||
*
|
||||
* [See] https://regexr.com/609n8 for example
|
||||
*
|
||||
* @pattern ^\s*(>|>=|<|<=)\s*(\d+)\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\s*$
|
||||
* */
|
||||
bannedAt?: DurationComparor
|
||||
|
||||
/**
|
||||
* A string or list of strings to match ban note against.
|
||||
*
|
||||
* If a list then ANY matched string makes this pass.
|
||||
*
|
||||
* String may be a regular expression enclosed in forward slashes. If it is not a regular expression then it is matched case-insensitive.
|
||||
* */
|
||||
note?: string | string[]
|
||||
|
||||
/**
|
||||
* Test how many days are left for Author's ban against this comparison
|
||||
*
|
||||
* If the ban is permanent then the number of days left is equivalent to **INFINITY**
|
||||
*
|
||||
* The syntax is `(< OR > OR <= OR >=) <number> <unit>`
|
||||
*
|
||||
* * EX `> 100 days` => Passes if the Author's ban has more than 100 days left
|
||||
* * EX `<= 2 months` => Passes if Author's ban has equal to or less than 2 months left
|
||||
*
|
||||
* Unit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)
|
||||
*
|
||||
* [See] https://regexr.com/609n8 for example
|
||||
*
|
||||
* @pattern ^\s*(>|>=|<|<=)\s*(\d+)\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\s*$
|
||||
* */
|
||||
daysLeft?: DurationComparor
|
||||
|
||||
/**
|
||||
* Is the ban permanent?
|
||||
* */
|
||||
permanent?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Criteria with which to test against the author of an Activity. The outcome of the test is based on:
|
||||
@@ -428,6 +478,19 @@ export interface AuthorCriteria {
|
||||
* Is the author an approved user (contributor)?
|
||||
* */
|
||||
isContributor?: boolean
|
||||
|
||||
/**
|
||||
* Is the Author banned or not?
|
||||
*
|
||||
* If user is not banned but BanCriteria(s) is present the test will fail
|
||||
*
|
||||
* * Use a boolean true/false for a simple yes or no
|
||||
* * Or use a BanCriteria to test for specifics of an existing ban
|
||||
* * Or use a list of BanCriteria -- if ANY BanCriteria passes the test passes
|
||||
*
|
||||
* NOTE: USE WITH CARE! This criteria usually incurs 1 API call
|
||||
* */
|
||||
banned?: boolean | BanCriteria | BanCriteria[]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,6 +518,7 @@ export const orderedAuthorCriteriaProps: (keyof AuthorCriteria)[] = [
|
||||
'isMod', // requires fetching mods for subreddit
|
||||
'isContributor', // requires fetching contributors for subreddit
|
||||
'modActions', // requires fetching mod notes/actions for author (shortest cache TTL)
|
||||
'banned', // requires fetching /about/banned for every user not cached
|
||||
];
|
||||
|
||||
export interface ActivityState {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import {Comment, RedditUser, Submission, Subreddit} from "snoowrap/dist/objects";
|
||||
import { BannedUser } from "snoowrap/dist/objects/Subreddit";
|
||||
import { ValueOf } from "ts-essentials";
|
||||
import {CMError} from "../../Utils/Errors";
|
||||
import {Dayjs} from "dayjs";
|
||||
import {Duration} from "dayjs/plugin/duration.js";
|
||||
|
||||
export type ActivityType = 'submission' | 'comment';
|
||||
export type MaybeActivityType = ActivityType | false;
|
||||
@@ -166,3 +169,16 @@ export interface RedditRemovalMessageOptions {
|
||||
title?: string
|
||||
lock?: boolean
|
||||
}
|
||||
|
||||
export interface CMBannedUser extends Omit<SnoowrapBannedUser, 'days_left' | 'date'> {
|
||||
user: RedditUser
|
||||
date: Dayjs
|
||||
days_left: undefined | Duration
|
||||
}
|
||||
|
||||
export interface SnoowrapBannedUser extends Omit<BannedUser, 'id'> {
|
||||
days_left: number | null
|
||||
rel_id?: string
|
||||
|
||||
id?: string
|
||||
}
|
||||
|
||||
@@ -59,6 +59,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -77,6 +83,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -100,6 +109,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -121,6 +139,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -180,6 +201,23 @@
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"banned": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"description": "Is the Author banned or not?\n\nIf user is not banned but BanCriteria(s) is present the test will fail\n\n* Use a boolean true/false for a simple yes or no\n* Or use a BanCriteria to test for specifics of an existing ban\n* Or use a list of BanCriteria -- if ANY BanCriteria passes the test passes\n\nNOTE: USE WITH CARE! This criteria usually incurs 1 API call"
|
||||
},
|
||||
"commentKarma": {
|
||||
"description": "A string containing a comparison operator and a value to compare karma against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 100` => greater than 100 comment karma\n* EX `<= 75%` => comment karma is less than or equal to 75% of **all karma**",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
@@ -345,6 +383,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -363,6 +407,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -409,6 +456,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -430,6 +486,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -478,11 +537,50 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"BanCriteria": {
|
||||
"properties": {
|
||||
"bannedAt": {
|
||||
"description": "Test when the Author was banned against this comparison\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if Author was banned more than 100 days ago\n* EX `<= 2 months` => Passes if Author was banned less than or equal to 2 months ago\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"daysLeft": {
|
||||
"description": "Test how many days are left for Author's ban against this comparison\n\nIf the ban is permanent then the number of days left is equivalent to **INFINITY**\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if the Author's ban has more than 100 days left\n* EX `<= 2 months` => Passes if Author's ban has equal to or less than 2 months left\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"note": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A string or list of strings to match ban note against.\n\nIf a list then ANY matched string makes this pass.\n\nString may be a regular expression enclosed in forward slashes. If it is not a regular expression then it is matched case-insensitive."
|
||||
},
|
||||
"permanent": {
|
||||
"description": "Is the ban permanent?",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"CancelDispatchActionJson": {
|
||||
"description": "Remove the Activity",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -501,6 +599,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -540,6 +641,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -561,6 +671,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -613,8 +726,18 @@
|
||||
"CommentActionJson": {
|
||||
"description": "Reply to the Activity. For a submission the reply will be a top-level comment.",
|
||||
"properties": {
|
||||
"asModTeam": {
|
||||
"description": "Comment \"as subreddit\" using the \"/u/subreddit-ModTeam\" account\n\nRESTRICTIONS:\n\n* Target activity must ALREADY BE REMOVED\n* Will always distinguish and sticky the created comment",
|
||||
"type": "boolean"
|
||||
},
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -633,6 +756,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -678,6 +804,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -699,6 +834,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -969,6 +1107,12 @@
|
||||
},
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -987,6 +1131,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1010,6 +1157,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1031,6 +1187,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1069,6 +1228,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1087,6 +1252,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1172,6 +1340,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1193,6 +1370,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1425,6 +1605,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1443,6 +1629,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1474,6 +1663,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1495,6 +1693,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1564,6 +1765,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1582,6 +1789,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1605,6 +1815,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1626,6 +1845,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1660,6 +1882,12 @@
|
||||
},
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1678,6 +1906,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1719,6 +1950,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1740,6 +1980,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1903,6 +2146,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1921,6 +2170,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1968,6 +2220,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1989,6 +2250,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2222,6 +2486,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2240,6 +2510,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2263,6 +2536,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2284,6 +2566,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2326,6 +2611,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2344,6 +2635,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2376,6 +2670,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2397,6 +2700,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2427,6 +2733,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2445,6 +2757,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2503,6 +2818,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2524,6 +2848,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2885,6 +3212,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2903,6 +3236,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2934,6 +3270,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2955,6 +3300,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2997,6 +3345,12 @@
|
||||
},
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3015,6 +3369,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -3062,6 +3419,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3083,6 +3449,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,23 @@
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"banned": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"description": "Is the Author banned or not?\n\nIf user is not banned but BanCriteria(s) is present the test will fail\n\n* Use a boolean true/false for a simple yes or no\n* Or use a BanCriteria to test for specifics of an existing ban\n* Or use a list of BanCriteria -- if ANY BanCriteria passes the test passes\n\nNOTE: USE WITH CARE! This criteria usually incurs 1 API call"
|
||||
},
|
||||
"commentKarma": {
|
||||
"description": "A string containing a comparison operator and a value to compare karma against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 100` => greater than 100 comment karma\n* EX `<= 75%` => comment karma is less than or equal to 75% of **all karma**",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
@@ -184,6 +201,39 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"BanCriteria": {
|
||||
"properties": {
|
||||
"bannedAt": {
|
||||
"description": "Test when the Author was banned against this comparison\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if Author was banned more than 100 days ago\n* EX `<= 2 months` => Passes if Author was banned less than or equal to 2 months ago\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"daysLeft": {
|
||||
"description": "Test how many days are left for Author's ban against this comparison\n\nIf the ban is permanent then the number of days left is equivalent to **INFINITY**\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if the Author's ban has more than 100 days left\n* EX `<= 2 months` => Passes if Author's ban has equal to or less than 2 months left\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"note": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A string or list of strings to match ban note against.\n\nIf a list then ANY matched string makes this pass.\n\nString may be a regular expression enclosed in forward slashes. If it is not a regular expression then it is matched case-insensitive."
|
||||
},
|
||||
"permanent": {
|
||||
"description": "Is the ban permanent?",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"BotConnection": {
|
||||
"description": "Configuration required to connect to a CM Server",
|
||||
"properties": {
|
||||
|
||||
@@ -432,10 +432,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -461,6 +461,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -479,6 +485,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -501,6 +510,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -522,6 +540,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -570,6 +591,23 @@
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"banned": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"description": "Is the Author banned or not?\n\nIf user is not banned but BanCriteria(s) is present the test will fail\n\n* Use a boolean true/false for a simple yes or no\n* Or use a BanCriteria to test for specifics of an existing ban\n* Or use a list of BanCriteria -- if ANY BanCriteria passes the test passes\n\nNOTE: USE WITH CARE! This criteria usually incurs 1 API call"
|
||||
},
|
||||
"commentKarma": {
|
||||
"description": "A string containing a comparison operator and a value to compare karma against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 100` => greater than 100 comment karma\n* EX `<= 75%` => comment karma is less than or equal to 75% of **all karma**",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
@@ -734,6 +772,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -752,6 +796,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -786,6 +833,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -807,6 +863,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -832,6 +891,39 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"BanCriteria": {
|
||||
"properties": {
|
||||
"bannedAt": {
|
||||
"description": "Test when the Author was banned against this comparison\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if Author was banned more than 100 days ago\n* EX `<= 2 months` => Passes if Author was banned less than or equal to 2 months ago\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"daysLeft": {
|
||||
"description": "Test how many days are left for Author's ban against this comparison\n\nIf the ban is permanent then the number of days left is equivalent to **INFINITY**\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if the Author's ban has more than 100 days left\n* EX `<= 2 months` => Passes if Author's ban has equal to or less than 2 months left\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"note": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A string or list of strings to match ban note against.\n\nIf a list then ANY matched string makes this pass.\n\nString may be a regular expression enclosed in forward slashes. If it is not a regular expression then it is matched case-insensitive."
|
||||
},
|
||||
"permanent": {
|
||||
"description": "Is the ban permanent?",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"CommentState": {
|
||||
"description": "Different attributes a `Comment` can be in. Only include a property if you want to check it.",
|
||||
"examples": [
|
||||
@@ -1526,10 +1618,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1580,10 +1672,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1630,10 +1722,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1667,10 +1759,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1720,6 +1812,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1738,6 +1836,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1808,6 +1909,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1829,6 +1939,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1999,6 +2112,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2017,6 +2136,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2031,6 +2153,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2052,6 +2183,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2557,6 +2691,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2575,6 +2715,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2585,6 +2728,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2606,6 +2758,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2657,10 +2812,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -2802,10 +2957,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -2830,6 +2985,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2848,6 +3009,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2877,6 +3041,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2898,6 +3071,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2932,6 +3108,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2950,6 +3132,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -3013,6 +3198,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3034,6 +3228,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -3097,10 +3294,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -3232,10 +3429,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -3257,6 +3454,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3275,6 +3478,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -3304,6 +3510,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3325,6 +3540,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -3435,10 +3653,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -3463,6 +3681,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3481,6 +3705,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -3509,6 +3736,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3530,6 +3766,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
|
||||
@@ -397,10 +397,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -426,6 +426,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -444,6 +450,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -466,6 +475,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -487,6 +505,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -535,6 +556,23 @@
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"banned": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"$ref": "#/definitions/BanCriteria"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"description": "Is the Author banned or not?\n\nIf user is not banned but BanCriteria(s) is present the test will fail\n\n* Use a boolean true/false for a simple yes or no\n* Or use a BanCriteria to test for specifics of an existing ban\n* Or use a list of BanCriteria -- if ANY BanCriteria passes the test passes\n\nNOTE: USE WITH CARE! This criteria usually incurs 1 API call"
|
||||
},
|
||||
"commentKarma": {
|
||||
"description": "A string containing a comparison operator and a value to compare karma against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 100` => greater than 100 comment karma\n* EX `<= 75%` => comment karma is less than or equal to 75% of **all karma**",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
@@ -699,6 +737,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -717,6 +761,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -751,6 +798,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -772,6 +828,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -797,6 +856,39 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"BanCriteria": {
|
||||
"properties": {
|
||||
"bannedAt": {
|
||||
"description": "Test when the Author was banned against this comparison\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if Author was banned more than 100 days ago\n* EX `<= 2 months` => Passes if Author was banned less than or equal to 2 months ago\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"daysLeft": {
|
||||
"description": "Test how many days are left for Author's ban against this comparison\n\nIf the ban is permanent then the number of days left is equivalent to **INFINITY**\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if the Author's ban has more than 100 days left\n* EX `<= 2 months` => Passes if Author's ban has equal to or less than 2 months left\n\nUnit must be one of [DayJS Duration units](https://day.js.org/docs/en/durations/creating)\n\n[See] https://regexr.com/609n8 for example",
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(days?|weeks?|months?|years?|hours?|minutes?|seconds?|milliseconds?)\\s*$",
|
||||
"type": "string"
|
||||
},
|
||||
"note": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A string or list of strings to match ban note against.\n\nIf a list then ANY matched string makes this pass.\n\nString may be a regular expression enclosed in forward slashes. If it is not a regular expression then it is matched case-insensitive."
|
||||
},
|
||||
"permanent": {
|
||||
"description": "Is the ban permanent?",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"CommentState": {
|
||||
"description": "Different attributes a `Comment` can be in. Only include a property if you want to check it.",
|
||||
"examples": [
|
||||
@@ -1491,10 +1583,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1545,10 +1637,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1595,10 +1687,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1632,10 +1724,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -1685,6 +1777,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1703,6 +1801,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1773,6 +1874,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1794,6 +1904,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -1964,6 +2077,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -1982,6 +2101,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -1996,6 +2118,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2017,6 +2148,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2522,6 +2656,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2540,6 +2680,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2550,6 +2693,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2571,6 +2723,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2622,10 +2777,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -2767,10 +2922,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -2795,6 +2950,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2813,6 +2974,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2842,6 +3006,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2863,6 +3036,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -2897,6 +3073,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2915,6 +3097,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -2978,6 +3163,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -2999,6 +3193,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -3062,10 +3259,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -3197,10 +3394,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -3222,6 +3419,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3240,6 +3443,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -3269,6 +3475,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3290,6 +3505,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
@@ -3400,10 +3618,10 @@
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
@@ -3428,6 +3646,12 @@
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3446,6 +3670,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
@@ -3474,6 +3701,15 @@
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
@@ -3495,6 +3731,9 @@
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "A list of criteria to test the state of the `Activity` against before running the check.\n\nIf any set of criteria passes the Check will be run. If the criteria fails then the Check will fail.\n\n* @examples [[{\"over_18\": true, \"removed': false}]]"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@ import {
|
||||
generateFullWikiUrl,
|
||||
generateItemFilterHelpers,
|
||||
getActivityAuthorName,
|
||||
getActivitySubredditName,
|
||||
getActivitySubredditName, humanizeBanDetails,
|
||||
isComment,
|
||||
isCommentState,
|
||||
isRuleSetResult,
|
||||
@@ -56,7 +56,7 @@ import {
|
||||
} from "../util";
|
||||
import {
|
||||
ActivityDispatch,
|
||||
CacheConfig,
|
||||
CacheConfig, CacheOptions,
|
||||
Footer,
|
||||
HistoricalStatsDisplay,
|
||||
ResourceStats, StrongTTLConfig,
|
||||
@@ -88,7 +88,7 @@ import cloneDeep from "lodash/cloneDeep";
|
||||
import {
|
||||
asModLogCriteria,
|
||||
asModNoteCriteria,
|
||||
AuthorCriteria,
|
||||
AuthorCriteria, BanCriteria,
|
||||
cmToSnoowrapActivityMap, cmToSnoowrapAuthorMap,
|
||||
CommentState,
|
||||
ModLogCriteria,
|
||||
@@ -104,7 +104,7 @@ import {
|
||||
UserNoteCriteria
|
||||
} from "../Common/Infrastructure/Filters/FilterCriteria";
|
||||
import {
|
||||
ActivitySourceValue,
|
||||
ActivitySourceValue, asSubredditPlaceholder,
|
||||
ConfigFragmentParseFunc,
|
||||
DurationVal,
|
||||
EventRetentionPolicyRange,
|
||||
@@ -115,7 +115,7 @@ import {
|
||||
ModUserNoteLabel,
|
||||
RelativeDateTimeMatch,
|
||||
statFrequencies,
|
||||
StatisticFrequencyOption,
|
||||
StatisticFrequencyOption, SubredditPlaceholderType,
|
||||
WikiContext
|
||||
} from "../Common/Infrastructure/Atomic";
|
||||
import {
|
||||
@@ -136,9 +136,9 @@ import {Duration} from "dayjs/plugin/duration";
|
||||
import {
|
||||
ActivityType,
|
||||
AuthorHistorySort,
|
||||
CachedFetchedActivitiesResult,
|
||||
CachedFetchedActivitiesResult, CMBannedUser,
|
||||
FetchedActivitiesResult, MaybeActivityType, RedditUserLike,
|
||||
SnoowrapActivity,
|
||||
SnoowrapActivity, SnoowrapBannedUser,
|
||||
SubredditLike,
|
||||
SubredditRemovalReason
|
||||
} from "../Common/Infrastructure/Reddit";
|
||||
@@ -161,7 +161,9 @@ import {ActionResultEntity} from "../Common/Entities/ActionResultEntity";
|
||||
import {ActivitySource} from "../Common/ActivitySource";
|
||||
import {SubredditResourceOptions} from "../Common/Subreddit/SubredditResourceInterfaces";
|
||||
import {SubredditStats} from "./Stats";
|
||||
import {CMCache} from "../Common/Cache";
|
||||
import {CMCache, createCacheManager} from "../Common/Cache";
|
||||
import {BannedUser, BanOptions} from "snoowrap/dist/objects/Subreddit";
|
||||
import {testBanCriteria} from "../Utils/Criteria/AuthorCritUtils";
|
||||
|
||||
export const DEFAULT_FOOTER = '\r\n*****\r\nThis action was performed by [a bot.]({{botLink}}) Mention a moderator or [send a modmail]({{modmailLink}}) if you have any ideas, questions, or concerns about this action.';
|
||||
|
||||
@@ -187,6 +189,7 @@ export class SubredditResources {
|
||||
database: DataSource
|
||||
client: ExtendedSnoowrap
|
||||
cache: CMCache
|
||||
memoryCache: CMCache
|
||||
cacheSettingsHash?: string;
|
||||
thirdPartyCredentials: ThirdPartyCredentialsJsonConfig;
|
||||
delayedItems: ActivityDispatch[] = [];
|
||||
@@ -244,6 +247,12 @@ export class SubredditResources {
|
||||
}
|
||||
this.cache = cache;
|
||||
this.cache.setLogger(this.logger);
|
||||
const memoryCacheOpts: CacheOptions = {
|
||||
store: 'memory',
|
||||
max: 10,
|
||||
ttl: 10
|
||||
};
|
||||
this.memoryCache = new CMCache(createCacheManager(memoryCacheOpts), memoryCacheOpts, false, undefined, {}, this.logger);
|
||||
|
||||
this.subredditStats = new SubredditStats(database, managerEntity, cache, statFrequency, this.logger);
|
||||
|
||||
@@ -861,6 +870,47 @@ export class SubredditResources {
|
||||
}
|
||||
}
|
||||
|
||||
async getSubredditBannedUser(val: string | RedditUser): Promise<CMBannedUser | undefined> {
|
||||
const subName = this.subreddit.display_name;
|
||||
const name = getActivityAuthorName(val);
|
||||
const hash = `sub-${subName}-banned-${name}`;
|
||||
|
||||
if (this.ttl.authorTTL !== false) {
|
||||
const cachedBanData = (await this.cache.get(hash)) as undefined | null | false | SnoowrapBannedUser;
|
||||
if (cachedBanData !== undefined && cachedBanData !== null) {
|
||||
this.logger.debug(`Cache Hit: Subreddit Banned User ${subName} ${name}`);
|
||||
if(cachedBanData === false) {
|
||||
return undefined;
|
||||
}
|
||||
return {...cachedBanData, date: dayjs.unix(cachedBanData.date), days_left: cachedBanData.days_left === null ? undefined : dayjs.duration({days: cachedBanData.days_left}), user: new RedditUser({name: cachedBanData.name}, this.client, false)};
|
||||
}
|
||||
}
|
||||
|
||||
let bannedUsers = await this.subreddit.getBannedUsers({name});
|
||||
let bannedUser: CMBannedUser | undefined;
|
||||
if(bannedUsers.length > 0) {
|
||||
const banData = bannedUsers[0] as SnoowrapBannedUser;
|
||||
bannedUser = {...banData, date: dayjs.unix(banData.date), days_left: banData.days_left === null ? undefined : dayjs.duration({days: banData.days_left}), user: new RedditUser({name: banData.name}, this.client, false)};
|
||||
}
|
||||
|
||||
if (this.ttl.authorTTL !== false) {
|
||||
// @ts-ignore
|
||||
await this.cache.set(hash, bannedUsers.length > 0 ? bannedUsers[0] as SnoowrapBannedUser : false, {ttl: this.ttl.subredditTTL});
|
||||
}
|
||||
|
||||
return bannedUser;
|
||||
}
|
||||
|
||||
async addUserToSubredditBannedUserCache(data: BanOptions) {
|
||||
if (this.ttl.authorTTL !== false) {
|
||||
const subName = this.subreddit.display_name;
|
||||
const name = getActivityAuthorName(data.name);
|
||||
const hash = `sub-${subName}-banned-${name}`;
|
||||
const banData: SnoowrapBannedUser = {date: dayjs().unix(), name: data.name, days_left: data.duration ?? null, note: data.banNote ?? ''};
|
||||
await this.cache.set(hash, banData, {ttl: this.ttl.authorTTL})
|
||||
}
|
||||
}
|
||||
|
||||
async hasSubreddit(name: string) {
|
||||
if (this.ttl.subredditTTL !== false) {
|
||||
const hash = `sub-${name}`;
|
||||
@@ -1080,6 +1130,9 @@ export class SubredditResources {
|
||||
|
||||
async getActivities(user: RedditUser, options: ActivityWindowCriteria, listingData: NamedListing, prefetchedActivities: SnoowrapActivity[] = []): Promise<FetchedActivitiesResult> {
|
||||
|
||||
let cacheKey: string | undefined;
|
||||
let fromCache = false;
|
||||
|
||||
try {
|
||||
|
||||
let pre: SnoowrapActivity[] = [];
|
||||
@@ -1087,7 +1140,6 @@ export class SubredditResources {
|
||||
let apiCount = 1;
|
||||
let preMaxTrigger: undefined | string;
|
||||
let rawCount: number = 0;
|
||||
let fromCache = false;
|
||||
|
||||
const hashObj = cloneDeep(options);
|
||||
|
||||
@@ -1100,13 +1152,23 @@ export class SubredditResources {
|
||||
const userName = getActivityAuthorName(user);
|
||||
|
||||
const hash = objectHash.sha1(hashObj);
|
||||
const cacheKey = `${userName}-${listingData.name}-${hash}`;
|
||||
cacheKey = `${userName}-${listingData.name}-${hash}`;
|
||||
|
||||
if (this.ttl.authorTTL !== false) {
|
||||
if (this.useSubredditAuthorCache) {
|
||||
hashObj.subreddit = this.subreddit;
|
||||
}
|
||||
|
||||
// check for cached request error!
|
||||
//
|
||||
// we cache reddit API request errors for 403/404 (suspended/shadowban) in memory so that
|
||||
// we don't waste API calls making the same call repetitively since we know what the result will always be
|
||||
const cachedRequestError = await this.memoryCache.get(cacheKey) as undefined | null | Error;
|
||||
if(cachedRequestError !== undefined && cachedRequestError !== null) {
|
||||
fromCache = true;
|
||||
this.logger.debug(`In-memory cache found reddit request error for key ${cacheKey}. Must have been <5 sec ago. Throwing to save API calls!`);
|
||||
throw cachedRequestError;
|
||||
}
|
||||
const cacheVal = await this.cache.get(cacheKey);
|
||||
|
||||
if(cacheVal === undefined || cacheVal === null) {
|
||||
@@ -1343,9 +1405,14 @@ export class SubredditResources {
|
||||
} catch (err: any) {
|
||||
if(isStatusError(err)) {
|
||||
switch(err.statusCode) {
|
||||
case 404:
|
||||
throw new SimpleError('Reddit returned a 404 for user history. Likely this user is shadowbanned.', {isSerious: false});
|
||||
case 403:
|
||||
case 404:
|
||||
if(!fromCache && cacheKey !== undefined) {
|
||||
await this.memoryCache.set(cacheKey, err, {ttl: 5});
|
||||
}
|
||||
if(err.statusCode === 404) {
|
||||
throw new SimpleError('Reddit returned a 404 for user history. Likely this user is shadowbanned.', {isSerious: false});
|
||||
}
|
||||
throw new MaybeSeriousErrorWithCause('Reddit returned a 403 for user history, likely this user is suspended.', {cause: err, isSerious: false});
|
||||
default:
|
||||
throw err;
|
||||
@@ -1891,8 +1958,14 @@ export class SubredditResources {
|
||||
if (crit[k] !== undefined) {
|
||||
switch (k) {
|
||||
case 'name':
|
||||
const nameReg = crit[k] as RegExp;
|
||||
if(!nameReg.test(subreddit.display_name)) {
|
||||
const nameReg = crit[k] as RegExp | SubredditPlaceholderType;
|
||||
// placeholder {{subreddit}} tests as true if the given subreddit matches the subreddit this bot is processing the activity from
|
||||
if (asSubredditPlaceholder(nameReg)) {
|
||||
if (this.subreddit.display_name !== subreddit.display_name) {
|
||||
log.debug(`Failed: Expected => ${k}:${crit[k]} (${this.subreddit.display_name}) | Found => ${k}:${subreddit.display_name}`)
|
||||
return false
|
||||
}
|
||||
} else if (!nameReg.test(subreddit.display_name)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -2715,6 +2788,33 @@ export class SubredditResources {
|
||||
shouldContinue = false;
|
||||
}
|
||||
break;
|
||||
case 'banned':
|
||||
const banDetails = await this.getSubredditBannedUser(item.author);
|
||||
const isBanned = banDetails !== undefined;
|
||||
propResultsMap.banned!.found = humanizeBanDetails(banDetails);
|
||||
|
||||
if(typeof authorOpts.banned === 'boolean') {
|
||||
propResultsMap.banned!.passed = criteriaPassWithIncludeBehavior(isBanned === authorOpts.banned, include);
|
||||
} else if(!isBanned) {
|
||||
// since banned criteria is not boolean it must be criteria(s)
|
||||
// and if user is not banned then no criteria will pass
|
||||
propResultsMap.banned!.passed = criteriaPassWithIncludeBehavior(false, include);
|
||||
} else {
|
||||
const bCritVal = authorOpts.banned as BanCriteria | BanCriteria[];
|
||||
const bCritArr = !Array.isArray(bCritVal) ? [bCritVal] : bCritVal;
|
||||
let anyBanCritPassed = false;
|
||||
for(const bCrit of bCritArr) {
|
||||
anyBanCritPassed = testBanCriteria(bCrit, banDetails);
|
||||
if(anyBanCritPassed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
propResultsMap.banned!.passed = criteriaPassWithIncludeBehavior(anyBanCritPassed, include);
|
||||
}
|
||||
if (!propResultsMap.banned!.passed) {
|
||||
shouldContinue = false;
|
||||
}
|
||||
break;
|
||||
case 'userNotes':
|
||||
const unCriterias = (authorOpts[k] as UserNoteCriteria[]).map(x => toFullUserNoteCriteria(x));
|
||||
const notes = await this.userNotes.getUserNotes(item.author);
|
||||
|
||||
79
src/Utils/Criteria/AuthorCritUtils.ts
Normal file
79
src/Utils/Criteria/AuthorCritUtils.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import {BanCriteria} from "../../Common/Infrastructure/Filters/FilterCriteria";
|
||||
import {boolToString, testMaybeStringRegex} from "../../util";
|
||||
import {CMBannedUser} from "../../Common/Infrastructure/Reddit";
|
||||
import {compareDurationValue, parseDurationComparison} from "../../Common/Infrastructure/Comparisons";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export const humanizeBanCriteria = (crit: BanCriteria): string => {
|
||||
const parts: string[] = [];
|
||||
for (const [k, v] of Object.entries(crit)) {
|
||||
switch (k.toLowerCase()) {
|
||||
case 'note':
|
||||
parts.push(`has notes matching: "${Array.isArray(v) ? v.join(' || ') : v}"`);
|
||||
break;
|
||||
default:
|
||||
parts.push(`${k}: ${typeof v === 'boolean' ? boolToString(v) : v.toString()}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parts.join(' AND ');
|
||||
}
|
||||
|
||||
export const testBanCriteria = (crit: BanCriteria, banUser: CMBannedUser): boolean => {
|
||||
if (crit.permanent !== undefined) {
|
||||
// easiest to test for
|
||||
if ((banUser.days_left === undefined && !crit.permanent) || (banUser.days_left !== undefined && crit.permanent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (crit.note !== undefined) {
|
||||
let anyPassed = false;
|
||||
const expectedValues = Array.isArray(crit.note) ? crit.note : [crit.note];
|
||||
for (const expectedVal of expectedValues) {
|
||||
try {
|
||||
const [regPassed] = testMaybeStringRegex(expectedVal, banUser.note);
|
||||
if (regPassed) {
|
||||
anyPassed = true;
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.message.includes('Could not convert test value')) {
|
||||
// fallback to simple comparison
|
||||
anyPassed = expectedVal.toLowerCase() === banUser.note.toLowerCase();
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
if (anyPassed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!anyPassed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (crit.bannedAt !== undefined) {
|
||||
const ageTest = compareDurationValue(parseDurationComparison(crit.bannedAt), banUser.date);
|
||||
if (!ageTest) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (crit.daysLeft !== undefined) {
|
||||
const daysLeftCompare = parseDurationComparison(crit.daysLeft);
|
||||
if (banUser.days_left === undefined) {
|
||||
if (daysLeftCompare.operator.includes('<')) {
|
||||
// permaban, will never be less than some finite duration
|
||||
return false;
|
||||
}
|
||||
// otherwise will always pass since any finite duration is less than infinity
|
||||
} else {
|
||||
const dayTest = compareDurationValue(daysLeftCompare, dayjs().add(banUser.days_left));
|
||||
if (!dayTest) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -46,83 +46,6 @@ import {ActionResultEntity} from "../Common/Entities/ActionResultEntity";
|
||||
|
||||
export const BOT_LINK = 'https://www.reddit.com/r/ContextModBot/comments/otz396/introduction_to_contextmodbot';
|
||||
|
||||
export interface AuthorTypedActivitiesOptions extends ActivityWindowCriteria {
|
||||
type?: 'comment' | 'submission',
|
||||
}
|
||||
|
||||
export const isSubreddit = async (subreddit: Subreddit, stateCriteria: SubredditCriteria | StrongSubredditCriteria, logger?: Logger) => {
|
||||
delete stateCriteria.stateDescription;
|
||||
|
||||
if (Object.keys(stateCriteria).length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const crit = isStrongSubredditState(stateCriteria) ? stateCriteria : toStrongSubredditState(stateCriteria, {defaultFlags: 'i'});
|
||||
|
||||
const log: Logger | undefined = logger !== undefined ? logger.child({leaf: 'Subreddit Check'}, mergeArr) : undefined;
|
||||
|
||||
return await (async () => {
|
||||
for (const k of Object.keys(crit)) {
|
||||
// @ts-ignore
|
||||
if (crit[k] !== undefined) {
|
||||
switch (k) {
|
||||
case 'name':
|
||||
const nameReg = crit[k] as RegExp;
|
||||
if(!nameReg.test(subreddit.display_name)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'isUserProfile':
|
||||
const entity = parseRedditEntity(subreddit.display_name);
|
||||
const entityIsUserProfile = entity.type === 'user';
|
||||
if(crit[k] !== entityIsUserProfile) {
|
||||
|
||||
if(log !== undefined) {
|
||||
log.debug(`Failed: Expected => ${k}:${crit[k]} | Found => ${k}:${entityIsUserProfile}`)
|
||||
}
|
||||
return false
|
||||
}
|
||||
break;
|
||||
case 'over18':
|
||||
case 'over_18':
|
||||
// handling an edge case where user may have confused Comment/Submission state "over_18" with SubredditState "over18"
|
||||
|
||||
// @ts-ignore
|
||||
if (crit[k] !== subreddit.over18) {
|
||||
if(log !== undefined) {
|
||||
// @ts-ignore
|
||||
log.debug(`Failed: Expected => ${k}:${crit[k]} | Found => ${k}:${subreddit.over18}`)
|
||||
}
|
||||
return false
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// @ts-ignore
|
||||
if (subreddit[k] !== undefined) {
|
||||
// @ts-ignore
|
||||
if (crit[k] !== subreddit[k]) {
|
||||
if(log !== undefined) {
|
||||
// @ts-ignore
|
||||
log.debug(`Failed: Expected => ${k}:${crit[k]} | Found => ${k}:${subreddit[k]}`)
|
||||
}
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if(log !== undefined) {
|
||||
log.warn(`Tried to test for Subreddit property '${k}' but it did not exist`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(log !== undefined) {
|
||||
log.debug(`Passed: ${JSON.stringify(stateCriteria)}`);
|
||||
}
|
||||
return true;
|
||||
})() as boolean;
|
||||
}
|
||||
|
||||
const renderContentCommentTruncate = truncateStringToLength(50);
|
||||
const shortTitleTruncate = truncateStringToLength(15);
|
||||
|
||||
@@ -177,6 +100,7 @@ export const renderContent = async (template: string, data: TemplateContext = {}
|
||||
conditional.spoiler = activity.spoiler;
|
||||
conditional.op = true;
|
||||
conditional.upvoteRatio = `${activity.upvote_ratio * 100}%`;
|
||||
conditional.link_flair_text = activity.link_flair_text;
|
||||
} else {
|
||||
conditional.op = activity.is_submitter;
|
||||
}
|
||||
@@ -199,6 +123,7 @@ export const renderContent = async (template: string, data: TemplateContext = {}
|
||||
author.commentKarma = auth.comment_karma;
|
||||
author.totalKarma = auth.comment_karma + auth.link_karma;
|
||||
author.verified = auth.has_verified_email;
|
||||
author.flairText = activity.author_flair_text;
|
||||
}
|
||||
|
||||
const templateData: any = {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {Logger} from "winston";
|
||||
import {WebSetting} from "../../Common/WebEntities/WebSetting";
|
||||
import {ErrorWithCause} from "pony-cause";
|
||||
import {createCacheManager} from "../../Common/Cache";
|
||||
import {MysqlDriver} from "typeorm/driver/mysql/MysqlDriver";
|
||||
|
||||
export interface CacheManagerStoreOptions {
|
||||
prefix?: string
|
||||
@@ -103,7 +104,12 @@ export class DatabaseStorageProvider extends StorageProvider {
|
||||
}
|
||||
|
||||
createSessionStore(options?: TypeormStoreOptions): Store {
|
||||
return new TypeormStore(options).connect(this.clientSessionRepo)
|
||||
// https://github.com/freshgiammi-lab/connect-typeorm#implement-the-session-entity
|
||||
// https://github.com/freshgiammi-lab/connect-typeorm/issues/8
|
||||
// usage of LIMIT in subquery is not supported by mariadb/mysql
|
||||
// limitSubquery: false -- turns off LIMIT usage
|
||||
const realOptions = this.database.driver instanceof MysqlDriver ? {...options, limitSubquery: false} : options;
|
||||
return new TypeormStore(realOptions).connect(this.clientSessionRepo)
|
||||
}
|
||||
|
||||
async getSessionSecret(): Promise<string | undefined> {
|
||||
|
||||
70
src/util.ts
70
src/util.ts
@@ -46,7 +46,14 @@ import {ErrorWithCause, stackWithCauses} from "pony-cause";
|
||||
import stringSimilarity from 'string-similarity';
|
||||
import calculateCosineSimilarity from "./Utils/StringMatching/CosineSimilarity";
|
||||
import levenSimilarity from "./Utils/StringMatching/levenSimilarity";
|
||||
import {isRateLimitError, isRequestError, isScopeError, isStatusError, SimpleError} from "./Utils/Errors";
|
||||
import {
|
||||
isRateLimitError,
|
||||
isRequestError,
|
||||
isScopeError,
|
||||
isSeriousError,
|
||||
isStatusError,
|
||||
SimpleError
|
||||
} from "./Utils/Errors";
|
||||
import merge from "deepmerge";
|
||||
import {RulePremise} from "./Common/Entities/RulePremise";
|
||||
import {RuleResultEntity as RuleResultEntity} from "./Common/Entities/RuleResultEntity";
|
||||
@@ -70,7 +77,7 @@ import {
|
||||
import {
|
||||
ActivitySourceData,
|
||||
ActivitySourceTypes,
|
||||
ActivitySourceValue,
|
||||
ActivitySourceValue, asSubredditPlaceholder,
|
||||
ConfigFormat,
|
||||
DurationVal,
|
||||
ExternalUrlContext,
|
||||
@@ -83,7 +90,7 @@ import {
|
||||
RelativeDateTimeMatch,
|
||||
statFrequencies,
|
||||
StatisticFrequency,
|
||||
StatisticFrequencyOption,
|
||||
StatisticFrequencyOption, subredditPlaceholder, SubredditPlaceholderType,
|
||||
UrlContext,
|
||||
WikiContext
|
||||
} from "./Common/Infrastructure/Atomic";
|
||||
@@ -104,7 +111,7 @@ import {
|
||||
} from "./Common/Infrastructure/Filters/FilterShapes";
|
||||
import {
|
||||
ActivityType,
|
||||
AuthorHistoryType,
|
||||
AuthorHistoryType, CMBannedUser,
|
||||
FullNameTypes,
|
||||
PermalinkRedditThings,
|
||||
RedditThing,
|
||||
@@ -1096,16 +1103,22 @@ export const createRetryHandler = (opts: RetryOptions, logger: Logger) => {
|
||||
// if it's a request error but not a known "oh probably just a reddit blip" status code treat it as other, which should usually have a lower retry max
|
||||
}
|
||||
|
||||
// linear backoff
|
||||
otherRetryCount++;
|
||||
let prefix = '';
|
||||
if(isSeriousError(err)) {
|
||||
// linear backoff
|
||||
otherRetryCount++;
|
||||
} else {
|
||||
prefix = 'NON-SERIOUS ';
|
||||
}
|
||||
|
||||
let msg = redditApiError ? `Error occurred while making a request to Reddit (${otherRetryCount}/${maxOtherRetry} in ${clearRetryCountAfter} minutes) but it was NOT a well-known "reddit blip" error.` : `Non-request error occurred (${otherRetryCount}/${maxOtherRetry} in ${clearRetryCountAfter} minutes).`;
|
||||
if (maxOtherRetry < otherRetryCount) {
|
||||
logger.warn(`${msg} Exceeded max allowed.`);
|
||||
logger.warn(`${prefix}${msg} Exceeded max allowed.`);
|
||||
return false;
|
||||
}
|
||||
if(waitOnRetry) {
|
||||
const ms = (4 * 1000) * otherRetryCount;
|
||||
logger.warn(`${msg} Will wait ${formatNumber(ms / 1000)} seconds before retrying`);
|
||||
logger.warn(`${prefix}${msg} Will wait ${formatNumber(ms / 1000)} seconds before retrying`);
|
||||
await sleep(ms);
|
||||
}
|
||||
return true;
|
||||
@@ -1557,7 +1570,7 @@ export const testMaybeStringRegex = (test: string, subject: string, defaultFlags
|
||||
}
|
||||
|
||||
export const isStrongSubredditState = (value: SubredditCriteria | StrongSubredditCriteria) => {
|
||||
return value.name === undefined || value.name instanceof RegExp;
|
||||
return value.name === undefined || value.name instanceof RegExp || asSubredditPlaceholder(value.name);
|
||||
}
|
||||
|
||||
export const asStrongSubredditState = (value: any): value is StrongSubredditCriteria => {
|
||||
@@ -1575,21 +1588,26 @@ export const toStrongSubredditState = (s: SubredditCriteria, opts?: StrongSubred
|
||||
|
||||
let nameValOriginallyRegex = false;
|
||||
|
||||
let nameReg: RegExp | undefined;
|
||||
let nameReg: RegExp | undefined | SubredditPlaceholderType;
|
||||
if (nameValRaw !== undefined) {
|
||||
if (!(nameValRaw instanceof RegExp)) {
|
||||
let nameVal = nameValRaw.trim();
|
||||
nameReg = parseStringToRegex(nameVal, defaultFlags);
|
||||
if (nameReg === undefined) {
|
||||
// if sub state has `isUserProfile=true` and config did not provide a regex then
|
||||
// assume the user wants to use the value in "name" to look for a user profile so we prefix created regex with u_
|
||||
const parsedEntity = parseRedditEntity(nameVal, isUserProfile !== undefined && isUserProfile ? 'user' : 'subreddit');
|
||||
// technically they could provide "u_Username" as the value for "name" and we will then match on it regardless of isUserProfile
|
||||
// but like...why would they do that? There shouldn't be any subreddits that start with u_ that aren't user profiles anyway(?)
|
||||
const regPrefix = parsedEntity.type === 'user' ? 'u_' : '';
|
||||
nameReg = parseStringToRegex(`/^${regPrefix}${nameVal}$/`, defaultFlags);
|
||||
if(asSubredditPlaceholder(nameVal)) {
|
||||
nameReg = subredditPlaceholder;
|
||||
nameValOriginallyRegex = false;
|
||||
} else {
|
||||
nameValOriginallyRegex = true;
|
||||
nameReg = parseStringToRegex(nameVal, defaultFlags);
|
||||
if (nameReg === undefined) {
|
||||
// if sub state has `isUserProfile=true` and config did not provide a regex then
|
||||
// assume the user wants to use the value in "name" to look for a user profile so we prefix created regex with u_
|
||||
const parsedEntity = parseRedditEntity(nameVal, isUserProfile !== undefined && isUserProfile ? 'user' : 'subreddit');
|
||||
// technically they could provide "u_Username" as the value for "name" and we will then match on it regardless of isUserProfile
|
||||
// but like...why would they do that? There shouldn't be any subreddits that start with u_ that aren't user profiles anyway(?)
|
||||
const regPrefix = parsedEntity.type === 'user' ? 'u_' : '';
|
||||
nameReg = parseStringToRegex(`/^${regPrefix}${nameVal}$/`, defaultFlags);
|
||||
} else {
|
||||
nameValOriginallyRegex = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nameValOriginallyRegex = true;
|
||||
@@ -3098,3 +3116,15 @@ export const toPollOn = (val: string | PollOn): PollOn => {
|
||||
}
|
||||
throw new SimpleError(`'${val}' is not a valid polling source. Valid sources: ${pollOnTypes.join(' | ')}`);
|
||||
}
|
||||
|
||||
export const humanizeBanDetails = (banDetails: CMBannedUser | undefined): string => {
|
||||
if(banDetails === undefined) {
|
||||
return 'Not Banned';
|
||||
}
|
||||
const timeSinceBan = dayjs.duration(dayjs().diff(banDetails.date)).humanize(true);
|
||||
if(banDetails.days_left === undefined) {
|
||||
return `Banned permanently ${timeSinceBan}`;
|
||||
}
|
||||
|
||||
return `Banned ${timeSinceBan} with ${banDetails.days_left?.days()} days left`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user