mirror of
https://github.com/FoxxMD/context-mod.git
synced 2026-04-19 03:00:07 -04:00
feat: Implement rule that tests activity content against moderatehatespeech.com ML model using api #110
* Add mhs rule type and MHS credentials interface * Implement MHS rule with similar criteria options to sentiment * Allow testing against author history content
This commit is contained in:
15
src/Common/Migrations/Database/Server/1663609045418-mhs.ts
Normal file
15
src/Common/Migrations/Database/Server/1663609045418-mhs.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
import {RuleType} from "../../../Entities/RuleType";
|
||||
|
||||
export class mhs1663609045418 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.manager.getRepository(RuleType).save([
|
||||
new RuleType('mhs'),
|
||||
]);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1585,6 +1585,9 @@ export interface ThirdPartyCredentialsJsonConfig {
|
||||
youtube?: {
|
||||
apiKey: string
|
||||
}
|
||||
mhs?: {
|
||||
apiKey: string
|
||||
}
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,11 @@ import {DispatchActionJson} from "../Action/DispatchAction";
|
||||
import {CancelDispatchActionJson} from "../Action/CancelDispatchAction";
|
||||
import {ContributorActionJson} from "../Action/ContributorAction";
|
||||
import {SentimentRuleJSONConfig} from "../Rule/SentimentRule";
|
||||
import {MHSRuleJSONConfig} from "../Rule/MHSRule";
|
||||
import {ModNoteActionJson} from "../Action/ModNoteAction";
|
||||
import {IncludesData} from "./Infrastructure/Includes";
|
||||
import { SubmissionActionJson } from "../Action/SubmissionAction";
|
||||
|
||||
export type RuleObjectJsonTypes = RecentActivityRuleJSONConfig | RepeatActivityJSONConfig | AuthorRuleJSONConfig | AttributionJSONConfig | HistoryJSONConfig | RegexRuleJSONConfig | RepostRuleJSONConfig | SentimentRuleJSONConfig
|
||||
export type RuleObjectJsonTypes = RecentActivityRuleJSONConfig | RepeatActivityJSONConfig | AuthorRuleJSONConfig | AttributionJSONConfig | HistoryJSONConfig | RegexRuleJSONConfig | RepostRuleJSONConfig | SentimentRuleJSONConfig | MHSRuleJSONConfig
|
||||
|
||||
export type ActionJson = CommentActionJson | SubmissionActionJson | FlairActionJson | ReportActionJson | LockActionJson | RemoveActionJson | ApproveActionJson | BanActionJson | UserNoteActionJson | MessageActionJson | UserFlairActionJson | DispatchActionJson | CancelDispatchActionJson | ContributorActionJson | ModNoteActionJson | string | IncludesData;
|
||||
|
||||
420
src/Rule/MHSRule.ts
Normal file
420
src/Rule/MHSRule.ts
Normal file
@@ -0,0 +1,420 @@
|
||||
import {Rule, RuleJSONConfig, RuleOptions} from "./index";
|
||||
import {Comment} from "snoowrap";
|
||||
import Submission from "snoowrap/dist/objects/Submission";
|
||||
import {
|
||||
asComment, boolToString,
|
||||
formatNumber,
|
||||
triggeredIndicator, windowConfigToWindowCriteria
|
||||
} from "../util";
|
||||
import got, {HTTPError} from 'got';
|
||||
import dayjs from 'dayjs';
|
||||
import {map as mapAsync} from 'async';
|
||||
import {
|
||||
comparisonTextOp,
|
||||
GenericComparison,
|
||||
parseGenericValueOrPercentComparison,
|
||||
} from "../Common/Infrastructure/Comparisons";
|
||||
import {ActivityWindowConfig, ActivityWindowCriteria} from "../Common/Infrastructure/ActivityWindow";
|
||||
import {RuleResult} from "../Common/interfaces";
|
||||
import {SnoowrapActivity} from "../Common/Infrastructure/Reddit";
|
||||
import {CMError} from "../Utils/Errors";
|
||||
import objectHash from "object-hash";
|
||||
|
||||
const formatConfidence = (val: number) => formatNumber(val * 100, {
|
||||
suffix: '%',
|
||||
toFixed: 2
|
||||
});
|
||||
|
||||
export class MHSRule extends Rule {
|
||||
|
||||
criteria: MHSCriteria
|
||||
|
||||
historical?: HistoricalMHS;
|
||||
|
||||
ogConfig: MHSConfig
|
||||
|
||||
constructor(options: MHSRuleOptions) {
|
||||
super(options);
|
||||
|
||||
if (this.resources.thirdPartyCredentials.mhs?.apiKey === undefined) {
|
||||
throw new CMError(`MHS (moderatehatespeech.com) API Key has not been specified. It must be present in the bot config or top-level subreddit 'credentials' property.`);
|
||||
}
|
||||
|
||||
const {
|
||||
criteria,
|
||||
historical,
|
||||
} = options;
|
||||
|
||||
this.ogConfig = {
|
||||
criteria,
|
||||
historical
|
||||
};
|
||||
|
||||
const {
|
||||
flagged = true,
|
||||
confidence,
|
||||
testOn = ['body']
|
||||
} = criteria || {};
|
||||
|
||||
this.criteria = {
|
||||
flagged,
|
||||
confidence: confidence !== undefined ? parseGenericValueOrPercentComparison(confidence) : undefined,
|
||||
testOn,
|
||||
}
|
||||
|
||||
if (options.historical !== undefined) {
|
||||
const {
|
||||
window,
|
||||
criteria: historyCriteria,
|
||||
mustMatchCurrent = false,
|
||||
totalMatching = '> 0',
|
||||
} = options.historical
|
||||
|
||||
let usedCriteria: MHSCriteria;
|
||||
if (historyCriteria === undefined) {
|
||||
usedCriteria = this.criteria;
|
||||
} else {
|
||||
const {
|
||||
flagged: historyFlagged = true,
|
||||
confidence: historyConfidence,
|
||||
testOn: historyTestOn = ['body']
|
||||
} = historyCriteria || {};
|
||||
usedCriteria = {
|
||||
flagged: historyFlagged,
|
||||
confidence: historyConfidence !== undefined ? parseGenericValueOrPercentComparison(historyConfidence) : undefined,
|
||||
testOn: historyTestOn,
|
||||
}
|
||||
}
|
||||
|
||||
this.historical = {
|
||||
criteria: usedCriteria,
|
||||
window: windowConfigToWindowCriteria(window),
|
||||
mustMatchCurrent,
|
||||
totalMatching: parseGenericValueOrPercentComparison(totalMatching),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getKind(): string {
|
||||
return 'mhs';
|
||||
}
|
||||
|
||||
getSpecificPremise(): object {
|
||||
return this.ogConfig;
|
||||
}
|
||||
|
||||
protected async process(item: Submission | Comment): Promise<[boolean, RuleResult]> {
|
||||
|
||||
let ogResult = await this.testActivity(item, this.criteria);
|
||||
let historicResults: MHSCriteriaResult[] | undefined;
|
||||
let historicalCriteriaTest: string | undefined;
|
||||
|
||||
if (this.historical !== undefined && (!this.historical.mustMatchCurrent || ogResult.passed)) {
|
||||
const {
|
||||
criteria,
|
||||
window,
|
||||
} = this.historical;
|
||||
const history = await this.resources.getAuthorActivities(item.author, window);
|
||||
|
||||
historicResults = await mapAsync(history, async (x: SnoowrapActivity) => await this.testActivity(x, criteria)); // history.map(x => this.testActivity(x, sentiment));
|
||||
}
|
||||
|
||||
const logSummary: string[] = [];
|
||||
|
||||
let triggered = false;
|
||||
let humanWindow: string | undefined;
|
||||
let historicalPassed: string | undefined;
|
||||
let totalMatchingText: string | undefined;
|
||||
|
||||
if (historicResults === undefined) {
|
||||
triggered = ogResult.passed;
|
||||
logSummary.push(`Current Activity MHS Test: ${ogResult.summary}`);
|
||||
if (!triggered && this.historical !== undefined && this.historical.mustMatchCurrent) {
|
||||
logSummary.push(`Did not check Historical because 'mustMatchCurrent' is true`);
|
||||
}
|
||||
} else {
|
||||
const {
|
||||
totalMatching,
|
||||
criteria,
|
||||
} = this.historical as HistoricalMHS;
|
||||
|
||||
historicalCriteriaTest = mhsCriteriaTestDisplay(criteria);
|
||||
|
||||
totalMatchingText = totalMatching.displayText;
|
||||
const allResults = historicResults
|
||||
const passed = allResults.filter(x => x.passed);
|
||||
|
||||
const firstActivity = allResults[0].activity;
|
||||
const lastActivity = allResults[allResults.length - 1].activity;
|
||||
|
||||
const humanRange = dayjs.duration(dayjs(firstActivity.created_utc * 1000).diff(dayjs(lastActivity.created_utc * 1000))).humanize();
|
||||
|
||||
humanWindow = `${allResults.length} Activities (${humanRange})`;
|
||||
|
||||
const {operator, value, isPercent} = totalMatching;
|
||||
if (isPercent) {
|
||||
const passPercentVal = passed.length / allResults.length
|
||||
triggered = comparisonTextOp(passPercentVal, operator, (value / 100));
|
||||
historicalPassed = `${passed.length} (${formatNumber(passPercentVal)}%)`;
|
||||
} else {
|
||||
triggered = comparisonTextOp(passed.length, operator, value);
|
||||
historicalPassed = `${passed.length}`;
|
||||
}
|
||||
logSummary.push(`${triggeredIndicator(triggered)} ${historicalPassed} historical activities of ${humanWindow} passed MHS criteria '${historicalCriteriaTest}' which ${triggered ? 'MET' : 'DID NOT MEET'} threshold '${totalMatching.displayText}'`);
|
||||
}
|
||||
|
||||
const result = logSummary.join(' || ');
|
||||
this.logger.verbose(result);
|
||||
|
||||
return Promise.resolve([triggered, this.getResult(triggered, {
|
||||
result,
|
||||
data: {
|
||||
results: {
|
||||
triggered,
|
||||
criteriaTest: mhsCriteriaTestDisplay(this.criteria),
|
||||
historicalCriteriaTest,
|
||||
window: humanWindow,
|
||||
totalMatching: totalMatchingText
|
||||
}
|
||||
}
|
||||
})]);
|
||||
}
|
||||
|
||||
protected async testActivity(a: SnoowrapActivity, criteria: MHSCriteria): Promise<MHSCriteriaResult> {
|
||||
const content = [];
|
||||
if (asComment(a)) {
|
||||
content.push(a.body);
|
||||
} else {
|
||||
if (criteria.testOn.includes('title')) {
|
||||
content.push(a.title);
|
||||
}
|
||||
if (criteria.testOn.includes('body') && a.is_self) {
|
||||
content.push(a.selftext);
|
||||
}
|
||||
}
|
||||
const mhsResult = await this.getMHSResponse(content.join(' '));
|
||||
|
||||
const {
|
||||
flagged,
|
||||
confidence
|
||||
} = criteria;
|
||||
|
||||
let flaggedPassed: boolean | undefined;
|
||||
let confPassed: boolean | undefined;
|
||||
|
||||
let summary = [];
|
||||
|
||||
if (confidence !== undefined) {
|
||||
const {operator, value} = confidence;
|
||||
confPassed = comparisonTextOp(mhsResult.confidence * 100, operator, value);
|
||||
summary.push(`Confidence test (${confidence.displayText}) ${confPassed ? 'PASSED' : 'DID NOT PASS'} MHS confidence of ${formatConfidence(mhsResult.confidence)}`)
|
||||
}
|
||||
|
||||
if (flagged !== undefined) {
|
||||
flaggedPassed = flagged ? mhsResult.class === 'flag' : mhsResult.class === 'normal';
|
||||
summary.push(`Flagged pass condition of ${flagged} (${flagged ? 'toxic' : 'normal'}) ${flaggedPassed ? 'MATCHED' : 'DID NOT MATCH'} MHS flag '${mhsResult.class === 'flag' ? 'toxic' : 'normal'}' ${confidence === undefined ? ` (${formatConfidence(mhsResult.confidence)} confidence)` : ''}`);
|
||||
}
|
||||
|
||||
const passed = (flaggedPassed === undefined || flaggedPassed) && (confPassed === undefined || confPassed);
|
||||
|
||||
return {
|
||||
activity: a,
|
||||
criteria,
|
||||
mhsResult,
|
||||
passed,
|
||||
summary: `${triggeredIndicator(passed)} ${summary.join(' | ')}`
|
||||
}
|
||||
}
|
||||
|
||||
protected async getMHSResponse(content: string): Promise<MHSResponse> {
|
||||
const hash = objectHash.sha1({content});
|
||||
const key = `mhs-${hash}`;
|
||||
if (this.resources.wikiTTL !== false) {
|
||||
let res = await this.resources.cache.get(key) as undefined | null | MHSResponse;
|
||||
if(res !== undefined && res !== null) {
|
||||
// don't cache bad responses
|
||||
if(res.response.toLowerCase() === 'success')
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
res = await this.callMHS(content);
|
||||
if(res.response.toLowerCase() === 'success') {
|
||||
await this.resources.cache.set(key, res, {ttl: this.resources.wikiTTL});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return this.callMHS(content);
|
||||
}
|
||||
|
||||
protected async callMHS(content: string): Promise<MHSResponse> {
|
||||
try {
|
||||
return await got.post(`https://api.moderatehatespeech.com/api/v1/moderate/`, {
|
||||
headers: {
|
||||
'Content-Type': `application/json`,
|
||||
},
|
||||
json: {
|
||||
token: this.resources.thirdPartyCredentials.mhs?.apiKey,
|
||||
text: content
|
||||
},
|
||||
}).json() as MHSResponse;
|
||||
} catch (err: any) {
|
||||
let error: string | undefined = undefined;
|
||||
if (err instanceof HTTPError) {
|
||||
error = err.response.statusMessage;
|
||||
if (typeof err.response.body === 'string') {
|
||||
error = `(${err.response.statusCode}) ${err.response.body}`;
|
||||
}
|
||||
}
|
||||
throw new CMError(`MHS request failed${error !== undefined ? ` with error: ${error}` : ''}`, {cause: err});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mhsCriteriaTestDisplay = (criteria: MHSCriteria) => {
|
||||
const summary = [];
|
||||
if (criteria.flagged !== undefined) {
|
||||
summary.push(`${criteria.flagged ? 'IS FLAGGED' : 'IS NOT FLAGGED'} as toxic`);
|
||||
}
|
||||
if (criteria.confidence !== undefined) {
|
||||
summary.push(`MHS confidence is ${criteria.confidence.displayText}`);
|
||||
}
|
||||
return summary.join(' AND ');
|
||||
}
|
||||
|
||||
interface MHSResponse {
|
||||
confidence: number
|
||||
response: string
|
||||
class: 'flag' | 'normal'
|
||||
}
|
||||
|
||||
interface MHSCriteriaResult {
|
||||
mhsResult: MHSResponse
|
||||
criteria: MHSCriteria
|
||||
passed: boolean
|
||||
summary: string,
|
||||
activity: SnoowrapActivity
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the content of Activities from the Author history against MHS criteria
|
||||
*
|
||||
* If this is defined then the `totalMatching` threshold must pass for the Rule to trigger
|
||||
*
|
||||
* If `criteria` is defined here it overrides the top-level `criteria` value
|
||||
*
|
||||
* */
|
||||
interface HistoricalMHSConfig {
|
||||
window: ActivityWindowConfig
|
||||
|
||||
criteria?: MHSCriteriaConfig
|
||||
|
||||
/**
|
||||
* When `true` the original Activity being checked MUST pass its criteria before the Rule considers any history
|
||||
*
|
||||
* @default false
|
||||
* */
|
||||
mustMatchCurrent?: boolean
|
||||
|
||||
/**
|
||||
* A string containing a comparison operator and a value to compare Activities from history that pass the given `criteria` test
|
||||
*
|
||||
* The syntax is `(< OR > OR <= OR >=) <number>[percent sign]`
|
||||
*
|
||||
* * EX `> 12` => greater than 12 activities passed given `criteria` test
|
||||
* * EX `<= 10%` => less than 10% of all Activities from history passed given `criteria` test
|
||||
*
|
||||
* @pattern ^\s*(>|>=|<|<=)\s*(\d+)\s*(%?)(.*)$
|
||||
* @default "> 0"
|
||||
* @examples ["> 0","> 10%"]
|
||||
* */
|
||||
totalMatching: string
|
||||
}
|
||||
|
||||
interface HistoricalMHS extends Omit<HistoricalMHSConfig, | 'window' | 'totalMatching' | 'criteria'> {
|
||||
window: ActivityWindowCriteria
|
||||
criteria: MHSCriteria
|
||||
totalMatching: GenericComparison
|
||||
}
|
||||
|
||||
/**
|
||||
* Criteria used to trigger based on MHS results
|
||||
*
|
||||
* If both `flagged` and `confidence` are specified then both conditions must pass.
|
||||
*
|
||||
* By default, only `flagged` is defined as `true`
|
||||
* */
|
||||
interface MHSCriteriaConfig {
|
||||
/**
|
||||
* Test if MHS considers content flagged as toxic or not
|
||||
*
|
||||
* @default true
|
||||
* */
|
||||
flagged?: boolean
|
||||
|
||||
/**
|
||||
* A string containing a comparison operator and a value to compare against the confidence returned from MHS
|
||||
*
|
||||
* The syntax is `(< OR > OR <= OR >=) <number>`
|
||||
*
|
||||
* * EX `> 50` => MHS confidence is greater than 50%
|
||||
*
|
||||
* @pattern ^\s*(>|>=|<|<=)\s*(\d+)\s*(%?)(.*)$
|
||||
* @examples ["> 50"]
|
||||
* */
|
||||
confidence?: string
|
||||
/**
|
||||
* Which content from an Activity to send to MHS
|
||||
*
|
||||
* Only used if the Activity being tested is a Submission -- Comments can be only tested against their body
|
||||
*
|
||||
* If more than one type of content is specified then all text is tested together as one string
|
||||
*
|
||||
* @default ["body"]
|
||||
* */
|
||||
testOn?: ('title' | 'body')[]
|
||||
}
|
||||
|
||||
interface MHSCriteria extends Omit<MHSCriteriaConfig, 'confidence'> {
|
||||
confidence?: GenericComparison
|
||||
testOn: ('title' | 'body')[]
|
||||
}
|
||||
|
||||
interface MHSConfig {
|
||||
|
||||
criteria?: MHSCriteriaConfig
|
||||
|
||||
/**
|
||||
* run MHS on Activities from the Author history
|
||||
*
|
||||
* If this is defined then the `totalMatching` threshold must pass for the Rule to trigger
|
||||
*
|
||||
* If `criteria` is defined here it overrides the top-level `criteria` value
|
||||
*
|
||||
* */
|
||||
historical?: HistoricalMHSConfig
|
||||
}
|
||||
|
||||
export interface MHSRuleOptions extends MHSConfig, RuleOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test content of an Activity against the MHS toxicity model for reddit content
|
||||
*
|
||||
* Running this Rule with no configuration will use a default configuration that will cause the Rule to trigger if MHS flags the content of the Activity as toxic.
|
||||
*
|
||||
* More info:
|
||||
*
|
||||
* * https://moderatehatespeech.com/docs/
|
||||
* * https://moderatehatespeech.com/
|
||||
*
|
||||
* */
|
||||
export interface MHSRuleJSONConfig extends MHSConfig, RuleJSONConfig {
|
||||
/**
|
||||
* @examples ["mhs"]
|
||||
* @default mhs
|
||||
* */
|
||||
kind: 'mhs'
|
||||
}
|
||||
|
||||
export default MHSRule;
|
||||
@@ -12,6 +12,7 @@ import {RepostRule, RepostRuleJSONConfig} from "./RepostRule";
|
||||
import {StructuredFilter} from "../Common/Infrastructure/Filters/FilterShapes";
|
||||
import {SentimentRule, SentimentRuleJSONConfig} from "./SentimentRule";
|
||||
import {StructuredRuleConfigObject} from "../Common/Infrastructure/RuleShapes";
|
||||
import {MHSRuleJSONConfig, MHSRule} from "./MHSRule";
|
||||
|
||||
export function ruleFactory
|
||||
(config: StructuredRuleConfigObject, logger: Logger, subredditName: string, resources: SubredditResources, client: Snoowrap): Rule {
|
||||
@@ -42,6 +43,9 @@ export function ruleFactory
|
||||
case 'sentiment':
|
||||
cfg = config as StructuredFilter<SentimentRuleJSONConfig>;
|
||||
return new SentimentRule({...cfg, logger, subredditName, resources, client});
|
||||
case 'mhs':
|
||||
cfg = config as StructuredFilter<MHSRuleJSONConfig>;
|
||||
return new MHSRule({...cfg, logger, subredditName, resources, client});
|
||||
default:
|
||||
throw new Error(`Rule with kind '${config.kind}' was not recognized.`);
|
||||
}
|
||||
|
||||
@@ -185,5 +185,5 @@ export interface RuleJSONConfig extends IRule {
|
||||
* The kind of rule to run
|
||||
* @examples ["recentActivity", "repeatActivity", "author", "attribution", "history"]
|
||||
*/
|
||||
kind: 'recentActivity' | 'repeatActivity' | 'author' | 'attribution' | 'history' | 'regex' | 'repost' | 'sentiment'
|
||||
kind: 'recentActivity' | 'repeatActivity' | 'author' | 'attribution' | 'history' | 'regex' | 'repost' | 'sentiment' | 'mhs'
|
||||
}
|
||||
|
||||
@@ -1650,6 +1650,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleSetConfigData"
|
||||
},
|
||||
@@ -2782,6 +2785,55 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalMHSConfig": {
|
||||
"description": "Test the content of Activities from the Author history against MHS criteria\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value",
|
||||
"properties": {
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"mustMatchCurrent": {
|
||||
"default": false,
|
||||
"description": "When `true` the original Activity being checked MUST pass its criteria before the Rule considers any history",
|
||||
"type": "boolean"
|
||||
},
|
||||
"totalMatching": {
|
||||
"default": "> 0",
|
||||
"description": "A string containing a comparison operator and a value to compare Activities from history that pass the given `criteria` test\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 12` => greater than 12 activities passed given `criteria` test\n* EX `<= 10%` => less than 10% of all Activities from history passed given `criteria` test",
|
||||
"examples": [
|
||||
"> 0",
|
||||
"> 10%"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"totalMatching",
|
||||
"window"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalSentimentConfig": {
|
||||
"description": "Test the Sentiment of Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `sentiment` is defined here it overrides the top-level `sentiment` value",
|
||||
"properties": {
|
||||
@@ -3251,6 +3303,126 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MHSCriteriaConfig": {
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`",
|
||||
"properties": {
|
||||
"confidence": {
|
||||
"description": "A string containing a comparison operator and a value to compare against the confidence returned from MHS\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 50` => MHS confidence is greater than 50%",
|
||||
"examples": [
|
||||
"> 50"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"flagged": {
|
||||
"default": true,
|
||||
"description": "Test if MHS considers content flagged as toxic or not",
|
||||
"type": "boolean"
|
||||
},
|
||||
"testOn": {
|
||||
"default": [
|
||||
"body"
|
||||
],
|
||||
"description": "Which content from an Activity to send to MHS\n\nOnly used if the Activity being tested is a Submission -- Comments can be only tested against their body\n\nIf more than one type of content is specified then all text is tested together as one string",
|
||||
"items": {
|
||||
"enum": [
|
||||
"body",
|
||||
"title"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MHSRuleJSONConfig": {
|
||||
"description": "Test content of an Activity against the MHS toxicity model for reddit content\n\nRunning this Rule with no configuration will use a default configuration that will cause the Rule to trigger if MHS flags the content of the Activity as toxic.\n\nMore info:\n\n* https://moderatehatespeech.com/docs/\n* https://moderatehatespeech.com/",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
},
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"historical": {
|
||||
"$ref": "#/definitions/HistoricalMHSConfig",
|
||||
"description": "run MHS on Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value"
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
}
|
||||
],
|
||||
"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}]]"
|
||||
},
|
||||
"kind": {
|
||||
"default": "mhs",
|
||||
"description": "The kind of rule to run",
|
||||
"enum": [
|
||||
"mhs"
|
||||
],
|
||||
"examples": [
|
||||
"mhs"
|
||||
],
|
||||
"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": [
|
||||
"kind"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MessageActionJson": {
|
||||
"description": "Send a private message to the Author of the Activity.",
|
||||
"properties": {
|
||||
@@ -5196,6 +5368,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
@@ -5989,6 +6164,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleSetConfigData"
|
||||
},
|
||||
@@ -6265,6 +6443,17 @@
|
||||
"ThirdPartyCredentialsJsonConfig": {
|
||||
"additionalProperties": {},
|
||||
"properties": {
|
||||
"mhs": {
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"youtube": {
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
|
||||
@@ -1473,6 +1473,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleSetConfigData"
|
||||
},
|
||||
@@ -2496,6 +2499,55 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalMHSConfig": {
|
||||
"description": "Test the content of Activities from the Author history against MHS criteria\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value",
|
||||
"properties": {
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"mustMatchCurrent": {
|
||||
"default": false,
|
||||
"description": "When `true` the original Activity being checked MUST pass its criteria before the Rule considers any history",
|
||||
"type": "boolean"
|
||||
},
|
||||
"totalMatching": {
|
||||
"default": "> 0",
|
||||
"description": "A string containing a comparison operator and a value to compare Activities from history that pass the given `criteria` test\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 12` => greater than 12 activities passed given `criteria` test\n* EX `<= 10%` => less than 10% of all Activities from history passed given `criteria` test",
|
||||
"examples": [
|
||||
"> 0",
|
||||
"> 10%"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"totalMatching",
|
||||
"window"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalSentimentConfig": {
|
||||
"description": "Test the Sentiment of Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `sentiment` is defined here it overrides the top-level `sentiment` value",
|
||||
"properties": {
|
||||
@@ -2965,6 +3017,126 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MHSCriteriaConfig": {
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`",
|
||||
"properties": {
|
||||
"confidence": {
|
||||
"description": "A string containing a comparison operator and a value to compare against the confidence returned from MHS\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 50` => MHS confidence is greater than 50%",
|
||||
"examples": [
|
||||
"> 50"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"flagged": {
|
||||
"default": true,
|
||||
"description": "Test if MHS considers content flagged as toxic or not",
|
||||
"type": "boolean"
|
||||
},
|
||||
"testOn": {
|
||||
"default": [
|
||||
"body"
|
||||
],
|
||||
"description": "Which content from an Activity to send to MHS\n\nOnly used if the Activity being tested is a Submission -- Comments can be only tested against their body\n\nIf more than one type of content is specified then all text is tested together as one string",
|
||||
"items": {
|
||||
"enum": [
|
||||
"body",
|
||||
"title"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MHSRuleJSONConfig": {
|
||||
"description": "Test content of an Activity against the MHS toxicity model for reddit content\n\nRunning this Rule with no configuration will use a default configuration that will cause the Rule to trigger if MHS flags the content of the Activity as toxic.\n\nMore info:\n\n* https://moderatehatespeech.com/docs/\n* https://moderatehatespeech.com/",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
},
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"historical": {
|
||||
"$ref": "#/definitions/HistoricalMHSConfig",
|
||||
"description": "run MHS on Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value"
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
}
|
||||
],
|
||||
"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}]]"
|
||||
},
|
||||
"kind": {
|
||||
"default": "mhs",
|
||||
"description": "The kind of rule to run",
|
||||
"enum": [
|
||||
"mhs"
|
||||
],
|
||||
"examples": [
|
||||
"mhs"
|
||||
],
|
||||
"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": [
|
||||
"kind"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MessageActionJson": {
|
||||
"description": "Send a private message to the Author of the Activity.",
|
||||
"properties": {
|
||||
@@ -4770,6 +4942,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
@@ -5433,6 +5608,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleSetConfigData"
|
||||
},
|
||||
|
||||
@@ -187,6 +187,17 @@
|
||||
},
|
||||
"BotCredentialsJsonConfig": {
|
||||
"properties": {
|
||||
"mhs": {
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"reddit": {
|
||||
"$ref": "#/definitions/RedditCredentials"
|
||||
},
|
||||
@@ -949,7 +960,7 @@
|
||||
"file": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Omit<DailyRotateFileTransportOptions,\"stream\"|\"log\"|\"dirname\"|\"options\"|\"handleRejections\"|\"format\"|\"handleExceptions\"|\"logv\"|\"close\">"
|
||||
"$ref": "#/definitions/Omit<DailyRotateFileTransportOptions,\"stream\"|\"log\"|\"options\"|\"dirname\"|\"handleRejections\"|\"format\"|\"handleExceptions\"|\"logv\"|\"close\">"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
@@ -1396,7 +1407,7 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Omit<DailyRotateFileTransportOptions,\"stream\"|\"log\"|\"dirname\"|\"options\"|\"handleRejections\"|\"format\"|\"handleExceptions\"|\"logv\"|\"close\">": {
|
||||
"Omit<DailyRotateFileTransportOptions,\"stream\"|\"log\"|\"options\"|\"dirname\"|\"handleRejections\"|\"format\"|\"handleExceptions\"|\"logv\"|\"close\">": {
|
||||
"properties": {
|
||||
"auditFile": {
|
||||
"description": "A string representing the name of the name of the audit file. (default: './hash-audit.json')",
|
||||
@@ -2077,6 +2088,17 @@
|
||||
"ThirdPartyCredentialsJsonConfig": {
|
||||
"additionalProperties": {},
|
||||
"properties": {
|
||||
"mhs": {
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"youtube": {
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
@@ -1345,6 +1348,55 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalMHSConfig": {
|
||||
"description": "Test the content of Activities from the Author history against MHS criteria\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value",
|
||||
"properties": {
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"mustMatchCurrent": {
|
||||
"default": false,
|
||||
"description": "When `true` the original Activity being checked MUST pass its criteria before the Rule considers any history",
|
||||
"type": "boolean"
|
||||
},
|
||||
"totalMatching": {
|
||||
"default": "> 0",
|
||||
"description": "A string containing a comparison operator and a value to compare Activities from history that pass the given `criteria` test\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 12` => greater than 12 activities passed given `criteria` test\n* EX `<= 10%` => less than 10% of all Activities from history passed given `criteria` test",
|
||||
"examples": [
|
||||
"> 0",
|
||||
"> 10%"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"totalMatching",
|
||||
"window"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalSentimentConfig": {
|
||||
"description": "Test the Sentiment of Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `sentiment` is defined here it overrides the top-level `sentiment` value",
|
||||
"properties": {
|
||||
@@ -1722,6 +1774,126 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MHSCriteriaConfig": {
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`",
|
||||
"properties": {
|
||||
"confidence": {
|
||||
"description": "A string containing a comparison operator and a value to compare against the confidence returned from MHS\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 50` => MHS confidence is greater than 50%",
|
||||
"examples": [
|
||||
"> 50"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"flagged": {
|
||||
"default": true,
|
||||
"description": "Test if MHS considers content flagged as toxic or not",
|
||||
"type": "boolean"
|
||||
},
|
||||
"testOn": {
|
||||
"default": [
|
||||
"body"
|
||||
],
|
||||
"description": "Which content from an Activity to send to MHS\n\nOnly used if the Activity being tested is a Submission -- Comments can be only tested against their body\n\nIf more than one type of content is specified then all text is tested together as one string",
|
||||
"items": {
|
||||
"enum": [
|
||||
"body",
|
||||
"title"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MHSRuleJSONConfig": {
|
||||
"description": "Test content of an Activity against the MHS toxicity model for reddit content\n\nRunning this Rule with no configuration will use a default configuration that will cause the Rule to trigger if MHS flags the content of the Activity as toxic.\n\nMore info:\n\n* https://moderatehatespeech.com/docs/\n* https://moderatehatespeech.com/",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
},
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"historical": {
|
||||
"$ref": "#/definitions/HistoricalMHSConfig",
|
||||
"description": "run MHS on Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value"
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
}
|
||||
],
|
||||
"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}]]"
|
||||
},
|
||||
"kind": {
|
||||
"default": "mhs",
|
||||
"description": "The kind of rule to run",
|
||||
"enum": [
|
||||
"mhs"
|
||||
],
|
||||
"examples": [
|
||||
"mhs"
|
||||
],
|
||||
"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": [
|
||||
"kind"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModLogCriteria": {
|
||||
"properties": {
|
||||
"action": {
|
||||
|
||||
@@ -1313,6 +1313,55 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalMHSConfig": {
|
||||
"description": "Test the content of Activities from the Author history against MHS criteria\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value",
|
||||
"properties": {
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"mustMatchCurrent": {
|
||||
"default": false,
|
||||
"description": "When `true` the original Activity being checked MUST pass its criteria before the Rule considers any history",
|
||||
"type": "boolean"
|
||||
},
|
||||
"totalMatching": {
|
||||
"default": "> 0",
|
||||
"description": "A string containing a comparison operator and a value to compare Activities from history that pass the given `criteria` test\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 12` => greater than 12 activities passed given `criteria` test\n* EX `<= 10%` => less than 10% of all Activities from history passed given `criteria` test",
|
||||
"examples": [
|
||||
"> 0",
|
||||
"> 10%"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"totalMatching",
|
||||
"window"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalSentimentConfig": {
|
||||
"description": "Test the Sentiment of Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `sentiment` is defined here it overrides the top-level `sentiment` value",
|
||||
"properties": {
|
||||
@@ -1690,6 +1739,126 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MHSCriteriaConfig": {
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`",
|
||||
"properties": {
|
||||
"confidence": {
|
||||
"description": "A string containing a comparison operator and a value to compare against the confidence returned from MHS\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 50` => MHS confidence is greater than 50%",
|
||||
"examples": [
|
||||
"> 50"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"flagged": {
|
||||
"default": true,
|
||||
"description": "Test if MHS considers content flagged as toxic or not",
|
||||
"type": "boolean"
|
||||
},
|
||||
"testOn": {
|
||||
"default": [
|
||||
"body"
|
||||
],
|
||||
"description": "Which content from an Activity to send to MHS\n\nOnly used if the Activity being tested is a Submission -- Comments can be only tested against their body\n\nIf more than one type of content is specified then all text is tested together as one string",
|
||||
"items": {
|
||||
"enum": [
|
||||
"body",
|
||||
"title"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MHSRuleJSONConfig": {
|
||||
"description": "Test content of an Activity against the MHS toxicity model for reddit content\n\nRunning this Rule with no configuration will use a default configuration that will cause the Rule to trigger if MHS flags the content of the Activity as toxic.\n\nMore info:\n\n* https://moderatehatespeech.com/docs/\n* https://moderatehatespeech.com/",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
},
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"historical": {
|
||||
"$ref": "#/definitions/HistoricalMHSConfig",
|
||||
"description": "run MHS on Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value"
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
}
|
||||
],
|
||||
"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}]]"
|
||||
},
|
||||
"kind": {
|
||||
"default": "mhs",
|
||||
"description": "The kind of rule to run",
|
||||
"enum": [
|
||||
"mhs"
|
||||
],
|
||||
"examples": [
|
||||
"mhs"
|
||||
],
|
||||
"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": [
|
||||
"kind"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModLogCriteria": {
|
||||
"properties": {
|
||||
"action": {
|
||||
@@ -3552,6 +3721,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
@@ -1470,6 +1470,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleSetConfigData"
|
||||
},
|
||||
@@ -2563,6 +2566,55 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalMHSConfig": {
|
||||
"description": "Test the content of Activities from the Author history against MHS criteria\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value",
|
||||
"properties": {
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"mustMatchCurrent": {
|
||||
"default": false,
|
||||
"description": "When `true` the original Activity being checked MUST pass its criteria before the Rule considers any history",
|
||||
"type": "boolean"
|
||||
},
|
||||
"totalMatching": {
|
||||
"default": "> 0",
|
||||
"description": "A string containing a comparison operator and a value to compare Activities from history that pass the given `criteria` test\n\nThe syntax is `(< OR > OR <= OR >=) <number>[percent sign]`\n\n* EX `> 12` => greater than 12 activities passed given `criteria` test\n* EX `<= 10%` => less than 10% of all Activities from history passed given `criteria` test",
|
||||
"examples": [
|
||||
"> 0",
|
||||
"> 10%"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"window": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationObject"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FullActivityWindowConfig"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"totalMatching",
|
||||
"window"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HistoricalSentimentConfig": {
|
||||
"description": "Test the Sentiment of Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `sentiment` is defined here it overrides the top-level `sentiment` value",
|
||||
"properties": {
|
||||
@@ -3032,6 +3084,126 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MHSCriteriaConfig": {
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`",
|
||||
"properties": {
|
||||
"confidence": {
|
||||
"description": "A string containing a comparison operator and a value to compare against the confidence returned from MHS\n\nThe syntax is `(< OR > OR <= OR >=) <number>`\n\n* EX `> 50` => MHS confidence is greater than 50%",
|
||||
"examples": [
|
||||
"> 50"
|
||||
],
|
||||
"pattern": "^\\s*(>|>=|<|<=)\\s*(\\d+)\\s*(%?)(.*)$",
|
||||
"type": "string"
|
||||
},
|
||||
"flagged": {
|
||||
"default": true,
|
||||
"description": "Test if MHS considers content flagged as toxic or not",
|
||||
"type": "boolean"
|
||||
},
|
||||
"testOn": {
|
||||
"default": [
|
||||
"body"
|
||||
],
|
||||
"description": "Which content from an Activity to send to MHS\n\nOnly used if the Activity being tested is a Submission -- Comments can be only tested against their body\n\nIf more than one type of content is specified then all text is tested together as one string",
|
||||
"items": {
|
||||
"enum": [
|
||||
"body",
|
||||
"title"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MHSRuleJSONConfig": {
|
||||
"description": "Test content of an Activity against the MHS toxicity model for reddit content\n\nRunning this Rule with no configuration will use a default configuration that will cause the Rule to trigger if MHS flags the content of the Activity as toxic.\n\nMore info:\n\n* https://moderatehatespeech.com/docs/\n* https://moderatehatespeech.com/",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AuthorCriteria"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<AuthorCriteria>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<AuthorCriteria>"
|
||||
}
|
||||
],
|
||||
"description": "If present then these Author criteria are checked before running the Check. If criteria fails then the Check will fail."
|
||||
},
|
||||
"criteria": {
|
||||
"$ref": "#/definitions/MHSCriteriaConfig",
|
||||
"description": "Criteria used to trigger based on MHS results\n\nIf both `flagged` and `confidence` are specified then both conditions must pass.\n\nBy default, only `flagged` is defined as `true`"
|
||||
},
|
||||
"historical": {
|
||||
"$ref": "#/definitions/HistoricalMHSConfig",
|
||||
"description": "run MHS on Activities from the Author history\n\nIf this is defined then the `totalMatching` threshold must pass for the Rule to trigger\n\nIf `criteria` is defined here it overrides the top-level `criteria` value"
|
||||
},
|
||||
"itemIs": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentState"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/NamedCriteria<TypedActivityState>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/FilterOptionsJson<TypedActivityState>"
|
||||
}
|
||||
],
|
||||
"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}]]"
|
||||
},
|
||||
"kind": {
|
||||
"default": "mhs",
|
||||
"description": "The kind of rule to run",
|
||||
"enum": [
|
||||
"mhs"
|
||||
],
|
||||
"examples": [
|
||||
"mhs"
|
||||
],
|
||||
"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": [
|
||||
"kind"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MessageActionJson": {
|
||||
"description": "Send a private message to the Author of the Activity.",
|
||||
"properties": {
|
||||
@@ -4837,6 +5009,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
@@ -5630,6 +5805,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SentimentRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MHSRuleJSONConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleSetConfigData"
|
||||
},
|
||||
|
||||
@@ -223,7 +223,7 @@ export class SubredditResources {
|
||||
protected useSubredditAuthorCache!: boolean;
|
||||
protected authorTTL: number | false = cacheTTLDefaults.authorTTL;
|
||||
protected subredditTTL: number | false = cacheTTLDefaults.subredditTTL;
|
||||
protected wikiTTL: number | false = cacheTTLDefaults.wikiTTL;
|
||||
public wikiTTL: number | false = cacheTTLDefaults.wikiTTL;
|
||||
protected submissionTTL: number | false = cacheTTLDefaults.submissionTTL;
|
||||
protected commentTTL: number | false = cacheTTLDefaults.commentTTL;
|
||||
protected filterCriteriaTTL: number | false = cacheTTLDefaults.filterCriteriaTTL;
|
||||
|
||||
Reference in New Issue
Block a user