Compare commits

..

1 Commits

Author SHA1 Message Date
FoxxMD
e36325278f feat: Add banned author criteria
* Test simple true/false is banned?
* Test against ban criteria -- bannedAt date, days left, mod note(s), and permanent bool
  * Test list of ban criteria with OR condition
2023-05-17 13:11:59 -04:00
22 changed files with 3105 additions and 207 deletions

View File

@@ -36,7 +36,7 @@ configuration.
* **FILE** -- Values specified in a YAML/JSON configuration file using the structure [in the schema](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FOperatorConfig.json)
* When reading the **schema** if the variable is available at a level of configuration other than **FILE** it will be
noted with the same symbol as above. The value shown is the default.
* **ARG** -- Values specified as CLI arguments to the program (see [CLI Usage](#cli-usage) below)
* **ARG** -- Values specified as CLI arguments to the program (see [ClI Usage](#cli-usage) below)
## File Configuration (Recommended)

28
package-lock.json generated
View File

@@ -31,7 +31,6 @@
"body-parser": "^1.19.0",
"cache-manager": "^3.4.4",
"cache-manager-redis-store": "^2.0.0",
"cacheable-lookup": "^6.1.0",
"command-exists": "^1.2.9",
"commander": "^8.0.0",
"comment-json": "^4.1.1",
@@ -2396,9 +2395,9 @@
}
},
"node_modules/cacheable-lookup": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz",
"integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==",
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
"engines": {
"node": ">=10.6.0"
}
@@ -4422,14 +4421,6 @@
"url": "https://github.com/sindresorhus/got?sponsor=1"
}
},
"node_modules/got/node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
"engines": {
"node": ">=10.6.0"
}
},
"node_modules/graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@@ -12333,9 +12324,9 @@
}
},
"cacheable-lookup": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz",
"integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww=="
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="
},
"cacheable-request": {
"version": "7.0.2",
@@ -13909,13 +13900,6 @@
"lowercase-keys": "^2.0.0",
"p-cancelable": "^2.0.0",
"responselike": "^2.0.0"
},
"dependencies": {
"cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="
}
}
},
"graceful-fs": {

View File

@@ -53,7 +53,6 @@
"body-parser": "^1.19.0",
"cache-manager": "^3.4.4",
"cache-manager-redis-store": "^2.0.0",
"cacheable-lookup": "^6.1.0",
"command-exists": "^1.2.9",
"commander": "^8.0.0",
"comment-json": "^4.1.1",

View File

@@ -57,18 +57,8 @@ export class ModNoteAction extends Action {
// nothing to do!
noteCheckResult = 'existingNoteCheck=false so no existing note checks were performed.';
} else {
const contextualCheck = {...this.existingNoteCheck};
let contextualNotes: string[] | undefined = undefined;
if(this.existingNoteCheck.note !== undefined && this.existingNoteCheck.note !== null) {
contextualNotes = [];
const notes = Array.isArray(this.existingNoteCheck.note) ? this.existingNoteCheck.note : [this.existingNoteCheck.note];
for(const n of notes) {
contextualNotes.push((await this.renderContent(n, item, ruleResults, actionResults) as string))
}
contextualCheck.note = contextualNotes;
}
const noteCheckCriteriaResult = await this.resources.isAuthor(item, {
modActions: [contextualCheck]
modActions: [this.existingNoteCheck]
});
noteCheckPassed = noteCheckCriteriaResult.passed;
const {details} = buildFilterCriteriaSummary(noteCheckCriteriaResult);

View File

@@ -54,18 +54,8 @@ export class UserNoteAction extends Action {
// nothing to do!
noteCheckResult = 'existingNoteCheck=false so no existing note checks were performed.';
} else {
const contextualCheck = {...this.existingNoteCheck};
let contextualNotes: string[] | undefined = undefined;
if(this.existingNoteCheck.note !== undefined && this.existingNoteCheck.note !== null) {
contextualNotes = [];
const notes = Array.isArray(this.existingNoteCheck.note) ? this.existingNoteCheck.note : [this.existingNoteCheck.note];
for(const n of notes) {
contextualNotes.push((await this.renderContent(n, item, ruleResults, actionResults) as string))
}
contextualCheck.note = contextualNotes;
}
const noteCheckCriteriaResult = await this.resources.isAuthor(item, {
userNotes: [contextualCheck]
userNotes: [this.existingNoteCheck]
});
noteCheckPassed = noteCheckCriteriaResult.passed;
const {details} = buildFilterCriteriaSummary(noteCheckCriteriaResult);

View File

@@ -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 {

View File

@@ -2,6 +2,8 @@ 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;
@@ -168,8 +170,10 @@ export interface RedditRemovalMessageOptions {
lock?: boolean
}
export interface CMBannedUser extends SnoowrapBannedUser {
export interface CMBannedUser extends Omit<SnoowrapBannedUser, 'days_left' | 'date'> {
user: RedditUser
date: Dayjs
days_left: undefined | Duration
}
export interface SnoowrapBannedUser extends Omit<BannedUser, 'id'> {

View File

@@ -311,24 +311,21 @@ export class HistoryRule extends Rule {
let criteriaMet = false;
let failCriteriaResult: string = '';
const criteriaResultsSummary = criteriaResults.map(x => this.generateResultDataFromCriteria(x, true).result).join(this.condition === 'OR' ? ' OR ' : ' AND ');
if (this.condition === 'OR') {
criteriaMet = criteriaResults.some(x => x.triggered);
if(!criteriaMet) {
failCriteriaResult = `${FAIL} No criteria was met => ${criteriaResultsSummary}`;
failCriteriaResult = `${FAIL} No criteria was met`;
}
} else {
criteriaMet = criteriaResults.every(x => x.triggered);
if(!criteriaMet) {
if(criteriaResults.some(x => x.triggered)) {
const met = criteriaResults.filter(x => x.triggered);
failCriteriaResult = `${FAIL} ${met.length} out of ${criteriaResults.length} criteria met but Rule required all be met => ${criteriaResultsSummary}`;
failCriteriaResult = `${FAIL} ${met.length} out of ${criteriaResults.length} criteria met but Rule required all be met. Set log level to debug to see individual results`;
const results = criteriaResults.map(x => this.generateResultDataFromCriteria(x, true));
this.logger.debug(`\r\n ${results.map(x => x.result).join('\r\n')}`);
} else {
failCriteriaResult = `${FAIL} No criteria was met => ${criteriaResultsSummary}`;
failCriteriaResult = `${FAIL} No criteria was met`;
}
}
}
@@ -338,8 +335,8 @@ export class HistoryRule extends Rule {
const refCriteriaResults = criteriaResults.find(x => x.triggered);
const resultData = this.generateResultDataFromCriteria(refCriteriaResults);
this.logger.verbose(`${PASS} ${criteriaResultsSummary}`);
return Promise.resolve([true, this.getResult(true, {data: resultData.data, result: criteriaResultsSummary})]);
this.logger.verbose(`${PASS} ${resultData.result}`);
return Promise.resolve([true, this.getResult(true, resultData)]);
} else {
// log failures for easier debugging
for(const res of criteriaResults) {

View File

@@ -241,8 +241,6 @@ export class MHSRule extends Rule {
res = await this.callMHS(content);
if(res.response.toLowerCase() === 'success') {
await this.resources.cache.set(key, res, {ttl: this.resources.ttl.wikiTTL});
} else if(res.response.toLowerCase().includes('authentication failure')) {
throw new CMError(`MHS Request failed with Authentication failure. You most likely need to generate a new API key.`);
}
return res;
}

View File

@@ -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

View File

@@ -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": {

View File

@@ -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}]]"

View File

@@ -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

View File

@@ -167,15 +167,7 @@ export class ModNote {
if (referenceItem === undefined) {
throw new CMError('Criteria wants to check if mod note references activity but not activity was given.');
}
let isCurrentActivity = false;
if(referenceItem !== undefined) {
if(this.action.actedOn !== undefined) {
isCurrentActivity = this.action.actedOn.name === referenceItem.name;
}
if(isCurrentActivity === false && this.note !== undefined && this.note.actedOn !== undefined) {
isCurrentActivity = this.note.actedOn.name === referenceItem.name;
}
}
const isCurrentActivity = this.action.actedOn !== undefined && referenceItem !== undefined && this.action.actedOn.name === referenceItem.name;
if ((referencesCurrentActivity === true && !isCurrentActivity) || (referencesCurrentActivity === false && isCurrentActivity)) {
return false;
}

View File

@@ -33,19 +33,9 @@ export class ModUserNote {
}
toRaw(): ModUserNoteRaw {
let id = undefined;
if(this.actedOn !== undefined) {
if(this.actedOn instanceof Submission) {
id = `t3_${this.actedOn.id}`;
} else if(this.actedOn instanceof Comment) {
id = `t1_${this.actedOn.id}`;
} else if(this.actedOn instanceof RedditUser) {
id = `t2_${this.actedOn.id}`;
}
}
return {
note: this.note,
reddit_id: id,
reddit_id: this.actedOn !== undefined ? this.actedOn.id : undefined,
label: this.label
}
}

View File

@@ -29,7 +29,7 @@ import {
generateFullWikiUrl,
generateItemFilterHelpers,
getActivityAuthorName,
getActivitySubredditName,
getActivitySubredditName, humanizeBanDetails,
isComment,
isCommentState,
isRuleSetResult,
@@ -88,7 +88,7 @@ import cloneDeep from "lodash/cloneDeep";
import {
asModLogCriteria,
asModNoteCriteria,
AuthorCriteria,
AuthorCriteria, BanCriteria,
cmToSnoowrapActivityMap, cmToSnoowrapAuthorMap,
CommentState,
ModLogCriteria,
@@ -163,6 +163,7 @@ import {SubredditResourceOptions} from "../Common/Subreddit/SubredditResourceInt
import {SubredditStats} from "./Stats";
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.';
@@ -881,7 +882,7 @@ export class SubredditResources {
if(cachedBanData === false) {
return undefined;
}
return {...cachedBanData, user: new RedditUser({name: cachedBanData.name}, this.client, false)};
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)};
}
}
@@ -889,7 +890,7 @@ export class SubredditResources {
let bannedUser: CMBannedUser | undefined;
if(bannedUsers.length > 0) {
const banData = bannedUsers[0] as SnoowrapBannedUser;
bannedUser = {...banData, user: new RedditUser({name: banData.name}, this.client, false)};
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) {
@@ -1287,7 +1288,7 @@ export class SubredditResources {
}
preFilteredPrefetchedActivities = await this.filterListingWithHistoryOptions(preFilteredPrefetchedActivities, user, options.filterOn?.pre);
}
let unFilteredItems: SnoowrapActivity[] | undefined = undefined;
let unFilteredItems: SnoowrapActivity[] | undefined = [...preFilteredPrefetchedActivities];
pre = pre.concat(preFilteredPrefetchedActivities);
const { func: listingFunc } = listingData;
@@ -1346,7 +1347,7 @@ export class SubredditResources {
if(satisfiedPreEndtime !== undefined || satisfiedPreCount !== undefined) {
if(unFilteredItems === undefined) {
unFilteredItems = [...preFilteredPrefetchedActivities];
unFilteredItems = [];
}
// window has pre filtering, need to check if fallback max would be hit
if(satisfiedPreEndtime !== undefined) {
@@ -2787,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);

View 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;
}

View File

@@ -1,9 +1,6 @@
import winston from 'winston';
import 'winston-daily-rotate-file';
import dayjs from 'dayjs';
import http from 'http';
import https from 'https';
import CacheableLookup from 'cacheable-lookup';
import utc from 'dayjs/plugin/utc.js';
import advancedFormat from 'dayjs/plugin/advancedFormat';
import tz from 'dayjs/plugin/timezone';
@@ -12,6 +9,7 @@ import relTime from 'dayjs/plugin/relativeTime.js';
import sameafter from 'dayjs/plugin/isSameOrAfter.js';
import samebefore from 'dayjs/plugin/isSameOrBefore.js';
import weekOfYear from 'dayjs/plugin/weekOfYear.js';
import {Manager} from "./Subreddit/Manager";
import {Command, Argument} from 'commander';
import {
@@ -42,17 +40,6 @@ dayjs.extend(tz);
dayjs.extend(advancedFormat);
dayjs.extend(weekOfYear);
const cacheable = new CacheableLookup({
// cache dns entries for 60 seconds
maxTtl: 60,
// fallback to node lookup for 10 minutes in the event of a failure for 10 minutes
fallbackDuration: 600
});
// replace node native request agents, globally, so they used cached dns lookup
cacheable.install(http.globalAgent);
cacheable.install(https.globalAgent);
const commentReg = parseLinkIdentifier([COMMENT_URL_ID]);
const submissionReg = parseLinkIdentifier([SUBMISSION_URL_ID]);

View File

@@ -111,7 +111,7 @@ import {
} from "./Common/Infrastructure/Filters/FilterShapes";
import {
ActivityType,
AuthorHistoryType,
AuthorHistoryType, CMBannedUser,
FullNameTypes,
PermalinkRedditThings,
RedditThing,
@@ -3116,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`;
}