Files
context-mod/src/Schema/Rule.json

1326 lines
69 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"anyOf": [
{
"$ref": "#/definitions/RecentActivityRuleJSONConfig"
},
{
"$ref": "#/definitions/RepeatActivityJSONConfig"
},
{
"$ref": "#/definitions/AuthorRuleJSONConfig"
},
{
"$ref": "#/definitions/AttributionJSONConfig"
},
{
"$ref": "#/definitions/HistoryJSONConfig"
},
{
"$ref": "#/definitions/RegexRuleJSONConfig"
},
{
"type": "string"
}
],
"definitions": {
"ActivityWindowCriteria": {
"additionalProperties": false,
"description": "Multiple properties that may be used to define what range of Activity to retrieve.\n\nMay specify one, or both properties along with the `satisfyOn` property, to affect the retrieval behavior.",
"examples": [
{
"count": 100,
"duration": {
"days": 90
}
}
],
"minProperties": 1,
"properties": {
"count": {
"description": "The number of activities (submission/comments) to consider",
"examples": [
15
],
"type": "number"
},
"duration": {
"anyOf": [
{
"$ref": "#/definitions/DurationObject"
},
{
"type": "string"
}
],
"description": "A value that specifies the amount of time to subtract from `NOW` to create a time range IE `NOW <---> [duration] ago`\n\nAcceptable values:\n\n**A `string` consisting of a value and a [Day.js](https://day.js.org/docs/en/durations/creating) time unit** ([test your value](https://regexr.com/61em3))\n\n* EX `9 days` => Range is `NOW <---> 9 days ago`\n\n**A [Day.js](https://day.js.org/docs/en/durations/creating) `object`**\n\n* EX `{\"days\": 90, \"minutes\": 15}` => Range is `NOW <---> 90 days and 15 minutes ago`\n\n**An [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) `string`** ([test your value](https://regexr.com/61em9))\n\n* EX `PT15M` => 15 minutes => Range is `NOW <----> 15 minutes ago`",
"examples": [
"90 days",
"PT15M",
{
"minutes": 15
}
]
},
"satisfyOn": {
"default": "any",
"description": "Define the condition under which both criteria are considered met\n\n**If `any` then it will retrieve Activities until one of the criteria is met, whichever occurs first**\n\nEX `{\"count\": 100, duration: \"90 days\"}`:\n* If 90 days of activities = 40 activities => returns 40 activities\n* If 100 activities is only 20 days => 100 activities\n\n**If `all` then both criteria must be met.**\n\nEffectively, whichever criteria produces the most Activities...\n\nEX `{\"count\": 100, duration: \"90 days\"}`:\n* If at 90 days of activities => 40 activities, continue retrieving results until 100 => results in >90 days of activities\n* If at 100 activities => 20 days of activities, continue retrieving results until 90 days => results in >100 activities",
"enum": [
"all",
"any"
],
"examples": [
"any"
],
"type": "string"
},
"subreddits": {
"description": "Filter which subreddits (case-insensitive) Activities are retrieved from.\n\n**Note:** Filtering occurs **before** `duration/count` checks are performed.",
"properties": {
"exclude": {
"description": "Exclude any results from these subreddits\n\n**Note:** `exclude` is ignored if `include` is present",
"examples": [
[
"mealtimevideos",
"askscience"
]
],
"items": {
"type": "string"
},
"type": "array"
},
"include": {
"description": "Include only results from these subreddits",
"examples": [
[
"mealtimevideos",
"askscience"
]
],
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "object"
},
"AttributionCriteria": {
"properties": {
"aggregateOn": {
"default": "undefined",
"description": "If `domains` is not specified this list determines which categories of domains should be aggregated on. All aggregated domains will be tested against `threshold`\n\n* If `media` is included then aggregate author's submission history which reddit recognizes as media (youtube, vimeo, etc.)\n* If `self` is included then aggregate on author's submission history which are self-post (`self.[subreddit]`) or reddit image/video (i.redd.it / v.redd.it)\n* If `link` is included then aggregate author's submission history which is external links but not media\n\nIf nothing is specified or list is empty (default) all domains are aggregated",
"examples": [
[
]
],
"items": {
"enum": [
"link",
"media",
"self"
],
"type": "string"
},
"type": "array"
},
"consolidateMediaDomains": {
"default": false,
"description": "Should the criteria consolidate recognized media domains into the parent domain?\n\nSubmissions to major media domains (youtube, vimeo) can be identified by individual Channel/Author...\n\n* If `false` then domains will be aggregated at the channel level IE Youtube Channel A (2 counts), Youtube Channel B (3 counts)\n* If `true` then then media domains will be consolidated at domain level and then aggregated IE youtube.com (5 counts)",
"examples": [
false
],
"type": "boolean"
},
"domains": {
"default": [
[
]
],
"description": "A list of domains whose Activities will be tested against `threshold`.\n\nIf this is present then `aggregateOn` is ignored.\n\nThe values are tested as partial strings so you do not need to include full URLs, just the part that matters.\n\nEX `[\"youtube\"]` will match submissions with the domain `https://youtube.com/c/aChannel`\nEX `[\"youtube.com/c/bChannel\"]` will NOT match submissions with the domain `https://youtube.com/c/aChannel`\n\nIf you wish to aggregate on self-posts for a subreddit use the syntax `self.[subreddit]` EX `self.AskReddit`\n\n**If this Rule is part of a Check for a Submission and you wish to aggregate on the domain of the Submission use the special string `AGG:SELF`**\n\nIf nothing is specified or list is empty (default) aggregate using `aggregateOn`",
"items": {
"type": "string"
},
"type": "array"
},
"domainsCombined": {
"default": false,
"description": "Set to `true` if you wish to combine all of the Activities from `domains` to test against `threshold` instead of testing each `domain` individually",
"examples": [
false
],
"type": "boolean"
},
"exclude": {
"description": "Do not include Activities from this list of Subreddits (by name, case-insensitive)\n\nWill be ignored if `include` is present.\n\nEX `[\"mealtimevideos\",\"askscience\"]`",
"examples": [
"mealtimevideos",
"askscience"
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"include": {
"description": "Only include Activities from this list of Subreddits (by name, case-insensitive)\n\n\nEX `[\"mealtimevideos\",\"askscience\"]`",
"examples": [
"mealtimevideos",
"askscience"
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"minActivityCount": {
"default": 5,
"description": "The minimum number of activities that must exist for this criteria to run",
"type": "number"
},
"name": {
"type": "string"
},
"threshold": {
"default": "> 10%",
"description": "A string containing a comparison operator and a value to compare comments against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 12` => greater than 12 activities originate from same attribution\n* EX `<= 10%` => less than 10% of all Activities have the same attribution",
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
},
"thresholdOn": {
"default": "all",
"description": "What activities to use for total count when determining what percentage an attribution comprises\n\nEX:\n\nAuthor has 100 activities, 40 are submissions and 60 are comments\n\n* If `submission` then if 10 submission are for Youtube Channel A then percentage => 10/40 = 25%\n* If `all` then if 10 submission are for Youtube Channel A then percentage => 10/100 = 10%",
"enum": [
"all",
"submissions"
],
"type": "string"
},
"window": {
"anyOf": [
{
"$ref": "#/definitions/ActivityWindowCriteria"
},
{
"$ref": "#/definitions/DurationObject"
},
{
"type": [
"string",
"number"
]
}
],
"description": "A value to define the range of Activities to retrieve.\n\nAcceptable values:\n\n**`ActivityWindowCriteria` object**\n\nAllows specify multiple range properties and more specific behavior\n\n**A `number` of Activities to retrieve**\n\n* EX `100` => 100 Activities\n\n*****\n\nAny of the below values that specify the amount of time to subtract from `NOW` to create a time range IE `NOW <---> [duration] ago`\n\nAcceptable values:\n\n**A `string` consisting of a value and a [Day.js](https://day.js.org/docs/en/durations/creating#list-of-all-available-units) time UNIT**\n\n* EX `9 days` => Range is `NOW <---> 9 days ago`\n\n**A [Day.js](https://day.js.org/docs/en/durations/creating) `object`**\n\n* EX `{\"days\": 90, \"minutes\": 15}` => Range is `NOW <---> 90 days and 15 minutes ago`\n\n**An [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) `string`**\n\n* EX `PT15M` => 15 minutes => Range is `NOW <----> 15 minutes ago`",
"examples": [
"90 days"
]
}
},
"required": [
"threshold",
"window"
],
"type": "object"
},
"AttributionJSONConfig": {
"description": "Aggregates all of the domain/media accounts attributed to an author's Submission history. If any domain is over the threshold the rule is triggered\n\nAvailable data for [Action templating](https://github.com/FoxxMD/context-mod#action-templating):\n\n```\ntriggeredDomainCount => Number of domains that met the threshold\nactivityTotal => Number of Activities considered from window\nwindow => The date range of the Activities considered\nlargestCount => The count from the largest aggregated domain\nlargestPercentage => The percentage of Activities the largest aggregated domain comprises\nsmallestCount => The count from the smallest aggregated domain\nsmallestPercentage => The percentage of Activities the smallest aggregated domain comprises\ncountRange => A convenience string displaying \"smallestCount - largestCount\" or just one number if both are the same\npercentRange => A convenience string displaying \"smallestPercentage - largestPercentage\" or just one percentage if both are the same\ndomains => An array of all the domain URLs that met the threshold\ndomainsDelim => A comma-delimited string of all the domain URLs that met the threshold\ntitles => The friendly-name of the domain if one is present, otherwise the URL (IE youtube.com/c/34ldfa343 => \"My Youtube Channel Title\")\ntitlesDelim => A comma-delimited string of all the domain friendly-names\nthreshold => The threshold you configured for this Rule to trigger\nurl => Url of the submission that triggered the rule\n```",
"properties": {
"authorIs": {
"$ref": "#/definitions/AuthorOptions",
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
]
},
"criteria": {
"description": "A list threshold-window values to test attribution against\n\nIf none is provided the default set used is:\n\n```\nthreshold: 10%\nwindow: 100\n```",
"items": {
"$ref": "#/definitions/AttributionCriteria"
},
"minItems": 1,
"type": "array"
},
"criteriaJoin": {
"description": "* If `OR` then any set of AttributionCriteria that produce an Attribution over the threshold will trigger the rule.\n* If `AND` then all AttributionCriteria sets must product an Attribution over the threshold to trigger the rule.",
"enum": [
"AND",
"OR"
],
"type": "string"
},
"itemIs": {
"anyOf": [
{
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
},
{
"items": {
"$ref": "#/definitions/CommentState"
},
"type": "array"
}
],
"description": "A list of criteria to test the state of the `Activity` against before running the Rule.\n\nIf any set of criteria passes the Rule will be run. If the criteria fails then the Rule is skipped."
},
"kind": {
"description": "The kind of rule to run",
"enum": [
"attribution"
],
"type": "string"
},
"name": {
"description": "An optional, but highly recommended, friendly name for this rule. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes\n\nname is used to reference Rule result data during Action content templating. See CommentAction or ReportAction for more details.",
"examples": [
"myNewRule"
],
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
"type": "string"
},
"useSubmissionAsReference": {
"default": true,
"description": "If activity is a Submission and is a link (not self-post) then only look at Submissions that contain this link, otherwise consider all activities.",
"type": "boolean"
}
},
"required": [
"kind"
],
"type": "object"
},
"AuthorCriteria": {
"additionalProperties": false,
"description": "Criteria with which to test against the author of an Activity. The outcome of the test is based on:\n\n1. All present properties passing and\n2. If a property is a list then any value from the list matching",
"examples": [
{
"flairText": [
"Contributor",
"Veteran"
],
"isMod": true,
"name": [
"FoxxMD",
"AnotherUser"
]
}
],
"minProperties": 1,
"properties": {
"age": {
"description": "Test the age of the Author's account (when it was created) against this comparison\n\nThe syntax is `(< OR > OR <= OR >=) <number> <unit>`\n\n* EX `> 100 days` => Passes if Author's account is older than 100 days\n* EX `<= 2 months` => Passes if Author's account is younger than or equal to 2 months\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"
},
"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*(%?)(.*)$",
"type": "string"
},
"flairCssClass": {
"description": "A list of (user) flair css class values from the subreddit to match against",
"examples": [
"red"
],
"items": {
"type": "string"
},
"type": "array"
},
"flairText": {
"description": "A list of (user) flair text values from the subreddit to match against",
"examples": [
"Approved"
],
"items": {
"type": "string"
},
"type": "array"
},
"isMod": {
"description": "Is the author a moderator?",
"type": "boolean"
},
"linkKarma": {
"description": "A string containing a comparison operator and a value to compare link karma against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 100` => greater than 100 link karma\n* EX `<= 75%` => link karma is less than or equal to 75% of **all karma**",
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
},
"name": {
"description": "A list of reddit usernames (case-insensitive) to match against. Do not include the \"u/\" prefix\n\n EX to match against /u/FoxxMD and /u/AnotherUser use [\"FoxxMD\",\"AnotherUser\"]",
"examples": [
"FoxxMD",
"AnotherUser"
],
"items": {
"type": "string"
},
"type": "array"
},
"totalKarma": {
"description": "A string containing a comparison operator and a value to compare against\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 100` => greater than 100",
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
},
"userNotes": {
"description": "A list of UserNote properties to check against the User Notes attached to this Author in this Subreddit (must have Toolbox enabled and used User Notes at least once)",
"items": {
"$ref": "#/definitions/UserNoteCriteria"
},
"type": "array"
},
"verified": {
"description": "Does Author's account have a verified email?",
"type": "boolean"
}
},
"type": "object"
},
"AuthorOptions": {
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
],
"properties": {
"exclude": {
"description": "Only runs if `include` is not present. Will \"pass\" if any of set of the AuthorCriteria **does not** pass",
"items": {
"$ref": "#/definitions/AuthorCriteria"
},
"type": "array"
},
"include": {
"description": "Will \"pass\" if any set of AuthorCriteria passes",
"items": {
"$ref": "#/definitions/AuthorCriteria"
},
"type": "array"
}
},
"type": "object"
},
"AuthorRuleJSONConfig": {
"properties": {
"authorIs": {
"$ref": "#/definitions/AuthorOptions",
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
]
},
"exclude": {
"description": "Only runs if include is not present. Will \"pass\" if any of set of the AuthorCriteria does not pass",
"items": {
"$ref": "#/definitions/AuthorCriteria"
},
"type": "array"
},
"include": {
"description": "Will \"pass\" if any set of AuthorCriteria passes",
"items": {
"$ref": "#/definitions/AuthorCriteria"
},
"type": "array"
},
"itemIs": {
"anyOf": [
{
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
},
{
"items": {
"$ref": "#/definitions/CommentState"
},
"type": "array"
}
],
"description": "A list of criteria to test the state of the `Activity` against before running the Rule.\n\nIf any set of criteria passes the Rule will be run. If the criteria fails then the Rule is skipped."
},
"kind": {
"description": "The kind of rule to run",
"enum": [
"author"
],
"type": "string"
},
"name": {
"description": "An optional, but highly recommended, friendly name for this rule. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes\n\nname is used to reference Rule result data during Action content templating. See CommentAction or ReportAction for more details.",
"examples": [
"myNewRule"
],
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
"type": "string"
}
},
"required": [
"exclude",
"include",
"kind"
],
"type": "object"
},
"CommentState": {
"description": "Different attributes a `Comment` can be in. Only include a property if you want to check it.",
"examples": [
{
"op": true,
"removed": false
}
],
"properties": {
"approved": {
"type": "boolean"
},
"deleted": {
"type": "boolean"
},
"distinguished": {
"type": "boolean"
},
"filtered": {
"type": "boolean"
},
"locked": {
"type": "boolean"
},
"op": {
"description": "Is this Comment Author also the Author of the Submission this comment is in?",
"type": "boolean"
},
"removed": {
"type": "boolean"
},
"spam": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"submissionState": {
"description": "A list of SubmissionState attributes to test the Submission this comment is in",
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
}
},
"type": "object"
},
"DurationObject": {
"additionalProperties": false,
"description": "A [Day.js duration object](https://day.js.org/docs/en/durations/creating)",
"examples": [
{
"hours": 1,
"minutes": 30
}
],
"minProperties": 1,
"properties": {
"days": {
"examples": [
7
],
"type": "number"
},
"hours": {
"examples": [
4
],
"type": "number"
},
"minutes": {
"examples": [
50
],
"type": "number"
},
"months": {
"examples": [
3
],
"type": "number"
},
"seconds": {
"examples": [
15
],
"type": "number"
},
"weeks": {
"examples": [
2
],
"type": "number"
},
"years": {
"examples": [
0
],
"type": "number"
}
},
"type": "object"
},
"HistoryCriteria": {
"description": "If both `submission` and `comment` are defined then criteria will only trigger if BOTH thresholds are met",
"properties": {
"comment": {
"description": "A string containing a comparison operator and a value to compare comments against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign] [OP]`\n\n* EX `> 100` => greater than 100 comments\n* EX `<= 75%` => comments are equal to or less than 75% of all Activities\n\nIf your string also contains the text `OP` somewhere **after** `<number>[percent sign]`...:\n\n* EX `> 100 OP` => greater than 100 comments as OP\n* EX `<= 25% as OP` => Comments as OP were less then or equal to 25% of **all Comments**",
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
},
"minActivityCount": {
"default": 5,
"description": "The minimum number of activities that must exist from the `window` results for this criteria to run",
"type": "number"
},
"name": {
"type": "string"
},
"submission": {
"description": "A string containing a comparison operator and a value to compare submissions against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 100` => greater than 100 submissions\n* EX `<= 75%` => submissions are equal to or less than 75% of all Activities",
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
},
"window": {
"anyOf": [
{
"$ref": "#/definitions/ActivityWindowCriteria"
},
{
"$ref": "#/definitions/DurationObject"
},
{
"type": [
"string",
"number"
]
}
],
"description": "A value to define the range of Activities to retrieve.\n\nAcceptable values:\n\n**`ActivityWindowCriteria` object**\n\nAllows specify multiple range properties and more specific behavior\n\n**A `number` of Activities to retrieve**\n\n* EX `100` => 100 Activities\n\n*****\n\nAny of the below values that specify the amount of time to subtract from `NOW` to create a time range IE `NOW <---> [duration] ago`\n\nAcceptable values:\n\n**A `string` consisting of a value and a [Day.js](https://day.js.org/docs/en/durations/creating#list-of-all-available-units) time UNIT**\n\n* EX `9 days` => Range is `NOW <---> 9 days ago`\n\n**A [Day.js](https://day.js.org/docs/en/durations/creating) `object`**\n\n* EX `{\"days\": 90, \"minutes\": 15}` => Range is `NOW <---> 90 days and 15 minutes ago`\n\n**An [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) `string`**\n\n* EX `PT15M` => 15 minutes => Range is `NOW <----> 15 minutes ago`",
"examples": [
"90 days"
]
}
},
"required": [
"window"
],
"type": "object"
},
"HistoryJSONConfig": {
"description": "Aggregates an Author's submission and comment history. Rule can be triggered on count/percent of total (for either or both comment/sub totals) as well as comment OP total.\n\nAvailable data for [Action templating](https://github.com/FoxxMD/context-mod#action-templating):\n\n```\nactivityTotal => Total number of activities\nsubmissionTotal => Total number of submissions\ncommentTotal => Total number of comments\nopTotal => Total number of comments as OP\nthresholdSummary => A text summary of the first Criteria triggered with totals/percentages\ncriteria => The ThresholdCriteria object\nwindow => A text summary of the range of Activities considered (# of Items if number, time range if Duration)\n```",
"properties": {
"authorIs": {
"$ref": "#/definitions/AuthorOptions",
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
]
},
"condition": {
"description": "* If `OR` then any set of Criteria that pass will trigger the Rule\n* If `AND` then all Criteria sets must pass to trigger the Rule",
"enum": [
"AND",
"OR"
],
"type": "string"
},
"criteria": {
"description": "A list threshold-window values to test activities against.",
"items": {
"$ref": "#/definitions/HistoryCriteria"
},
"minItems": 1,
"type": "array"
},
"exclude": {
"description": "Do not include Submissions from this list of Subreddits (by name, case-insensitive)\n\nEX `[\"mealtimevideos\",\"askscience\"]`",
"examples": [
"mealtimevideos",
"askscience"
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"include": {
"description": "Only include Submissions from this list of Subreddits (by name, case-insensitive)\n\nEX `[\"mealtimevideos\",\"askscience\"]`",
"examples": [
"mealtimevideos",
"askscience"
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"itemIs": {
"anyOf": [
{
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
},
{
"items": {
"$ref": "#/definitions/CommentState"
},
"type": "array"
}
],
"description": "A list of criteria to test the state of the `Activity` against before running the Rule.\n\nIf any set of criteria passes the Rule will be run. If the criteria fails then the Rule is skipped."
},
"kind": {
"description": "The kind of rule to run",
"enum": [
"history"
],
"type": "string"
},
"name": {
"description": "An optional, but highly recommended, friendly name for this rule. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes\n\nname is used to reference Rule result data during Action content templating. See CommentAction or ReportAction for more details.",
"examples": [
"myNewRule"
],
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
"type": "string"
}
},
"required": [
"criteria",
"kind"
],
"type": "object"
},
"RecentActivityRuleJSONConfig": {
"description": "Checks a user's history for any Activity (Submission/Comment) in the subreddits specified in thresholds\n\nAvailable data for [Action templating](https://github.com/FoxxMD/context-mod#action-templating):\n\n```\nsummary => comma-deliminated list of subreddits that hit the threshold and their count EX subredditA(1), subredditB(4),...\nsubCount => Total number of subreddits that hit the threshold\ntotalCount => Total number of all activity occurrences in subreddits\n```",
"properties": {
"authorIs": {
"$ref": "#/definitions/AuthorOptions",
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
]
},
"itemIs": {
"anyOf": [
{
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
},
{
"items": {
"$ref": "#/definitions/CommentState"
},
"type": "array"
}
],
"description": "A list of criteria to test the state of the `Activity` against before running the Rule.\n\nIf any set of criteria passes the Rule will be run. If the criteria fails then the Rule is skipped."
},
"kind": {
"description": "The kind of rule to run",
"enum": [
"recentActivity"
],
"examples": [
"recentActivity"
],
"type": "string"
},
"lookAt": {
"description": "If present restricts the activities that are considered for count from SubThreshold",
"enum": [
"comments",
"submissions"
],
"examples": [
"submissions",
"comments"
],
"type": "string"
},
"name": {
"description": "An optional, but highly recommended, friendly name for this rule. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes\n\nname is used to reference Rule result data during Action content templating. See CommentAction or ReportAction for more details.",
"examples": [
"myNewRule"
],
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
"type": "string"
},
"thresholds": {
"description": "A list of subreddits/count criteria that may trigger this rule. ANY SubThreshold will trigger this rule.",
"items": {
"$ref": "#/definitions/SubThreshold"
},
"minItems": 1,
"type": "array"
},
"useSubmissionAsReference": {
"default": true,
"description": "If activity is a Submission and is a link (not self-post) then only look at Submissions that contain this link, otherwise consider all activities.",
"type": "boolean"
},
"window": {
"anyOf": [
{
"$ref": "#/definitions/ActivityWindowCriteria"
},
{
"$ref": "#/definitions/DurationObject"
},
{
"type": [
"string",
"number"
]
}
],
"description": "A value to define the range of Activities to retrieve.\n\nAcceptable values:\n\n**`ActivityWindowCriteria` object**\n\nAllows specify multiple range properties and more specific behavior\n\n**A `number` of Activities to retrieve**\n\n* EX `100` => 100 Activities\n\n*****\n\nAny of the below values that specify the amount of time to subtract from `NOW` to create a time range IE `NOW <---> [duration] ago`\n\nAcceptable values:\n\n**A `string` consisting of a value and a [Day.js](https://day.js.org/docs/en/durations/creating#list-of-all-available-units) time UNIT**\n\n* EX `9 days` => Range is `NOW <---> 9 days ago`\n\n**A [Day.js](https://day.js.org/docs/en/durations/creating) `object`**\n\n* EX `{\"days\": 90, \"minutes\": 15}` => Range is `NOW <---> 90 days and 15 minutes ago`\n\n**An [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) `string`**\n\n* EX `PT15M` => 15 minutes => Range is `NOW <----> 15 minutes ago`",
"examples": [
"90 days"
]
}
},
"required": [
"kind",
"thresholds"
],
"type": "object"
},
"RegexCriteria": {
"properties": {
"activityMatchThreshold": {
"default": "> 0",
"description": "An string containing a comparison operator and a value to determine how many Activities need to be \"matched\" (based on `matchThreshold` condition) to trigger the rule\n\n**Only useful when used in conjunction with `window`**. If no `window` is specified only the Activity being checked is tested (so the default should/will be used).\n\nTo disable (you are only using `totalMatchThreshold`) set to `null`\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 3` => greater than 3 Activities met the `matchThreshold` condition, Rule is triggered\n* EX `<= 10%` => less than 10% of all Activities retrieved from `window` met the `matchThreshold` condition, Rule is triggered",
"examples": [
"> 0"
],
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
},
"lookAt": {
"default": "all",
"description": "**When used with `window`** determines what type of Activities to retrieve",
"enum": [
"all",
"comments",
"submissions"
],
"type": "string"
},
"matchThreshold": {
"default": "> 0",
"description": "A string containing a comparison operator and a value to determine when an Activity is determined \"matched\"\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 7 => greater than 7 matches found in the Activity, Activity is matched\n* EX `<= 3` => less than 3 matches found in the Activity, Activity is matched",
"examples": [
"> 0"
],
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)(\\s+.*)*$",
"type": "string"
},
"name": {
"description": "A descriptive name that will be used in logging and be available for templating",
"examples": [
"swear words"
],
"type": "string"
},
"regex": {
"description": "A valid Regular Expression to test content against\n\nDo not wrap expression in forward slashes\n\nEX For the expression `/reddit|FoxxMD/` use the value should be `reddit|FoxxMD`",
"examples": [
"reddit|FoxxMD"
],
"type": "string"
},
"regexFlags": {
"description": "Regex flags to use",
"type": "string"
},
"testOn": {
"default": [
"title",
"body"
],
"description": "Which content from an Activity to test the regex against\n\nOnly used if the Activity being tested is a Submission -- Comments are only tested against their content (duh)",
"items": {
"enum": [
"body",
"title",
"url"
],
"type": "string"
},
"type": "array"
},
"totalMatchThreshold": {
"default": "null",
"description": "A string containing a comparison operator and a value to determine how many total matches satisfies the criteria.\n\nIf both this and `activityMatchThreshold` are present then whichever is satisfied first will be used.\n\nIf not using `window` then this should not be used as running `matchThreshold` on one Activity is effectively the same behavior ( but I'm not gonna stop ya ¯\\\\\\_(ツ)\\_/¯ )\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 7` => greater than 7 matches found in Activity + Author history `window`\n* EX `<= 3` => less than 3 matches found in the Activity + Author history `window`",
"examples": [
"> 0"
],
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)(\\s+.*)*$",
"type": "string"
},
"window": {
"anyOf": [
{
"$ref": "#/definitions/ActivityWindowCriteria"
},
{
"$ref": "#/definitions/DurationObject"
},
{
"type": [
"string",
"number"
]
}
],
"description": "A value to define the range of Activities to retrieve.\n\nAcceptable values:\n\n**`ActivityWindowCriteria` object**\n\nAllows specify multiple range properties and more specific behavior\n\n**A `number` of Activities to retrieve**\n\n* EX `100` => 100 Activities\n\n*****\n\nAny of the below values that specify the amount of time to subtract from `NOW` to create a time range IE `NOW <---> [duration] ago`\n\nAcceptable values:\n\n**A `string` consisting of a value and a [Day.js](https://day.js.org/docs/en/durations/creating#list-of-all-available-units) time UNIT**\n\n* EX `9 days` => Range is `NOW <---> 9 days ago`\n\n**A [Day.js](https://day.js.org/docs/en/durations/creating) `object`**\n\n* EX `{\"days\": 90, \"minutes\": 15}` => Range is `NOW <---> 90 days and 15 minutes ago`\n\n**An [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) `string`**\n\n* EX `PT15M` => 15 minutes => Range is `NOW <----> 15 minutes ago`",
"examples": [
"90 days"
]
}
},
"required": [
"regex"
],
"type": "object"
},
"RegexRuleJSONConfig": {
"description": "Test a (list of) Regular Expression against the contents or title of an Activity\n\nOptionally, specify a `window` of the User's history to additionally test against\n\nAvailable data for [Action templating](https://github.com/FoxxMD/context-mod#action-templating):",
"properties": {
"authorIs": {
"$ref": "#/definitions/AuthorOptions",
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
]
},
"condition": {
"default": "OR",
"description": "* If `OR` then any set of Criteria that pass will trigger the Rule\n* If `AND` then all Criteria sets must pass to trigger the Rule",
"enum": [
"AND",
"OR"
],
"type": "string"
},
"criteria": {
"description": "A list of Regular Expressions and conditions under which tested Activity(ies) are matched",
"examples": [
{
"matchThreshold": "> 3",
"regex": "/reddit/"
}
],
"items": {
"$ref": "#/definitions/RegexCriteria"
},
"minItems": 1,
"type": "array"
},
"itemIs": {
"anyOf": [
{
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
},
{
"items": {
"$ref": "#/definitions/CommentState"
},
"type": "array"
}
],
"description": "A list of criteria to test the state of the `Activity` against before running the Rule.\n\nIf any set of criteria passes the Rule will be run. If the criteria fails then the Rule is skipped."
},
"kind": {
"description": "The kind of rule to run",
"enum": [
"regex"
],
"examples": [
"regex"
],
"type": "string"
},
"name": {
"description": "An optional, but highly recommended, friendly name for this rule. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes\n\nname is used to reference Rule result data during Action content templating. See CommentAction or ReportAction for more details.",
"examples": [
"myNewRule"
],
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
"type": "string"
}
},
"required": [
"criteria",
"kind"
],
"type": "object"
},
"RepeatActivityJSONConfig": {
"description": "Checks a user's history for Submissions with identical content\n\nAvailable data for [Action templating](https://github.com/FoxxMD/context-mod#action-templating):\n\n```\ncount => Total number of repeat Submissions\nthreshold => The threshold you configured for this Rule to trigger\nurl => Url of the submission that triggered the rule\n```",
"properties": {
"authorIs": {
"$ref": "#/definitions/AuthorOptions",
"description": "If present then these Author criteria are checked before running the rule. If criteria fails then the rule is skipped.",
"examples": [
{
"include": [
{
"flairText": [
"Contributor",
"Veteran"
]
},
{
"isMod": true
}
]
}
]
},
"exclude": {
"description": "Do not include Submissions from this list of Subreddits (by name, case-insensitive)\n\nEX `[\"mealtimevideos\",\"askscience\"]`",
"examples": [
"mealtimevideos",
"askscience"
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"gapAllowance": {
"description": "The number of allowed non-identical Submissions between identical Submissions that can be ignored when checking against the threshold value",
"type": "number"
},
"include": {
"description": "Only include Submissions from this list of Subreddits (by name, case-insensitive)\n\nEX `[\"mealtimevideos\",\"askscience\"]`",
"examples": [
"mealtimevideos",
"askscience"
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"itemIs": {
"anyOf": [
{
"items": {
"$ref": "#/definitions/SubmissionState"
},
"type": "array"
},
{
"items": {
"$ref": "#/definitions/CommentState"
},
"type": "array"
}
],
"description": "A list of criteria to test the state of the `Activity` against before running the Rule.\n\nIf any set of criteria passes the Rule will be run. If the criteria fails then the Rule is skipped."
},
"keepRemoved": {
"default": false,
"description": "Count submissions/comments that have previously been removed.\n\nBy default all `Submissions/Commments` that are in a `removed` state will be filtered from `window` (only applies to subreddits you mod).\n\nSetting to `true` could be useful if you also want to also detected removed repeat posts by a user like for example if automoderator removes multiple, consecutive submissions for not following title format correctly.",
"type": "boolean"
},
"kind": {
"description": "The kind of rule to run",
"enum": [
"repeatActivity"
],
"type": "string"
},
"lookAt": {
"default": "all",
"description": "If present determines which activities to consider for gapAllowance.\n\n* If `submissions` then only the author's submission history is considered IE gapAllowance = 2 ===> can have gap of two submissions between repeats\n* If `all` then the author's entire history (submissions/comments) is considered IE gapAllowance = 2 ===> can only have gap of two activities (submissions or comments) between repeats",
"enum": [
"all",
"submissions"
],
"type": "string"
},
"minWordCount": {
"default": 1,
"description": "For activities that are text-based this is the minimum number of words required for the activity to be considered for a repeat\n\nEX if `minimumWordCount=5` and a comment is `what about you` then it is ignored because `3 is less than 5`\n\n**For self-text submissions** -- title + body text\n\n**For comments* -- body text",
"type": "number"
},
"name": {
"description": "An optional, but highly recommended, friendly name for this rule. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes\n\nname is used to reference Rule result data during Action content templating. See CommentAction or ReportAction for more details.",
"examples": [
"myNewRule"
],
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
"type": "string"
},
"threshold": {
"default": ">= 5",
"description": "The number of repeat submissions that will trigger the rule",
"type": "string"
},
"useSubmissionAsReference": {
"default": true,
"description": "If activity is a Submission and is a link (not self-post) then only look at Submissions that contain this link, otherwise consider all activities.",
"type": "boolean"
},
"window": {
"anyOf": [
{
"$ref": "#/definitions/ActivityWindowCriteria"
},
{
"$ref": "#/definitions/DurationObject"
},
{
"type": [
"string",
"number"
]
}
],
"description": "A value to define the range of Activities to retrieve.\n\nAcceptable values:\n\n**`ActivityWindowCriteria` object**\n\nAllows specify multiple range properties and more specific behavior\n\n**A `number` of Activities to retrieve**\n\n* EX `100` => 100 Activities\n\n*****\n\nAny of the below values that specify the amount of time to subtract from `NOW` to create a time range IE `NOW <---> [duration] ago`\n\nAcceptable values:\n\n**A `string` consisting of a value and a [Day.js](https://day.js.org/docs/en/durations/creating#list-of-all-available-units) time UNIT**\n\n* EX `9 days` => Range is `NOW <---> 9 days ago`\n\n**A [Day.js](https://day.js.org/docs/en/durations/creating) `object`**\n\n* EX `{\"days\": 90, \"minutes\": 15}` => Range is `NOW <---> 90 days and 15 minutes ago`\n\n**An [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) `string`**\n\n* EX `PT15M` => 15 minutes => Range is `NOW <----> 15 minutes ago`",
"examples": [
"90 days"
]
}
},
"required": [
"kind"
],
"type": "object"
},
"SubThreshold": {
"additionalProperties": false,
"description": "At least one count property must be present. If both are present then either can trigger the rule",
"minProperties": 1,
"properties": {
"subreddits": {
"description": "A list of Subreddits (by name, case-insensitive) to look for.\n\nEX [\"mealtimevideos\",\"askscience\"]",
"examples": [
[
"mealtimevideos",
"askscience"
]
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"threshold": {
"default": ">= 1",
"description": "A string containing a comparison operator and a value to compare recent activities against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 3` => greater than 3 activities found in the listed subreddits\n* EX `<= 75%` => number of Activities in the subreddits listed are equal to or less than 75% of all Activities\n\n**Note:** If you use percentage comparison here as well as `useSubmissionAsReference` then \"all Activities\" is only pertains to Activities that had the Link of the Submission, rather than all Activities from this window.",
"examples": [
">= 1"
],
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
"type": "string"
}
},
"required": [
"subreddits"
],
"type": "object"
},
"SubmissionState": {
"description": "Different attributes a `Submission` can be in. Only include a property if you want to check it.",
"examples": [
{
"over_18": true,
"removed": false
}
],
"properties": {
"approved": {
"type": "boolean"
},
"deleted": {
"type": "boolean"
},
"distinguished": {
"type": "boolean"
},
"filtered": {
"type": "boolean"
},
"is_self": {
"type": "boolean"
},
"link_flair_css_class": {
"type": "string"
},
"link_flair_text": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"over_18": {
"description": "NSFW",
"type": "boolean"
},
"pinned": {
"type": "boolean"
},
"removed": {
"type": "boolean"
},
"spam": {
"type": "boolean"
},
"spoiler": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"title": {
"description": "A valid regular expression to match against the title of the submission",
"type": "string"
}
},
"type": "object"
},
"UserNoteCriteria": {
"properties": {
"count": {
"default": ">= 1",
"description": "Number of occurrences of this type. Ignored if `search` is `current`\n\nA string containing a comparison operator and/or a value to compare number of occurrences against\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign] [ascending|descending]`",
"examples": [
">= 1"
],
"pattern": "^\\s*(?<opStr>>|>=|<|<=)\\s*(?<value>\\d+)\\s*(?<percent>%?)\\s*(?<extra>asc.*|desc.*)*$",
"type": "string"
},
"search": {
"default": "current",
"description": "How to test the notes for this Author:\n\n### current\n\nOnly the most recent note is checked for `type`\n\n### total\n\nThe `count` comparison of `type` must be found within all notes\n\n* EX `count: > 3` => Must have more than 3 notes of `type`, total\n* EX `count: <= 25%` => Must have 25% or less of notes of `type`, total\n\n### consecutive\n\nThe `count` **number** of `type` notes must be found in a row.\n\nYou may also specify the time-based order in which to search the notes by specifying `ascending (asc)` or `descending (desc)` in the `count` value. Default is `descending`\n\n* EX `count: >= 3` => Must have 3 or more notes of `type` consecutively, in descending order\n* EX `count: < 2` => Must have less than 2 notes of `type` consecutively, in descending order\n* EX `count: > 4 asc` => Must have greater than 4 notes of `type` consecutively, in ascending order",
"enum": [
"consecutive",
"current",
"total"
],
"examples": [
"current"
],
"type": "string"
},
"type": {
"description": "User Note type key to search for",
"examples": [
"spamwarn"
],
"type": "string"
}
},
"required": [
"type"
],
"type": "object"
}
}
}