{ "$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 >=) [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 >=) `\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 >=) [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 >=) [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 >=) `\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 >=) [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** `[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 >=) [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 >=) [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 >=) `\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 >=) `\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 >=) [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 >=) [percent sign] [ascending|descending]`", "examples": [ ">= 1" ], "pattern": "^\\s*(?>|>=|<|<=)\\s*(?\\d+)\\s*(?%?)\\s*(?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" } } }