mirror of
https://github.com/FoxxMD/context-mod.git
synced 2026-05-11 03:00:42 -04:00
Merge pull request #62 from rysie/user-flair-action
UserFlairAction added
This commit is contained in:
@@ -10,10 +10,11 @@ import ApproveAction, {ApproveActionConfig} from "./ApproveAction";
|
||||
import BanAction, {BanActionJson} from "./BanAction";
|
||||
import {MessageAction, MessageActionJson} from "./MessageAction";
|
||||
import {SubredditResources} from "../Subreddit/SubredditResources";
|
||||
import Snoowrap from "snoowrap";
|
||||
import {UserFlairAction, UserFlairActionJson} from './UserFlairAction';
|
||||
import {ExtendedSnoowrap} from '../Utils/SnoowrapClients';
|
||||
|
||||
export function actionFactory
|
||||
(config: ActionJson, logger: Logger, subredditName: string, resources: SubredditResources, client: Snoowrap): Action {
|
||||
(config: ActionJson, logger: Logger, subredditName: string, resources: SubredditResources, client: ExtendedSnoowrap): Action {
|
||||
switch (config.kind) {
|
||||
case 'comment':
|
||||
return new CommentAction({...config as CommentActionJson, logger, subredditName, resources, client});
|
||||
@@ -25,6 +26,8 @@ export function actionFactory
|
||||
return new ReportAction({...config as ReportActionJson, logger, subredditName, resources, client});
|
||||
case 'flair':
|
||||
return new FlairAction({...config as FlairActionJson, logger, subredditName, resources, client});
|
||||
case 'userflair':
|
||||
return new UserFlairAction({...config as UserFlairActionJson, logger, subredditName, resources, client});
|
||||
case 'approve':
|
||||
return new ApproveAction({...config as ApproveActionConfig, logger, subredditName, resources, client});
|
||||
case 'usernote':
|
||||
|
||||
109
src/Action/UserFlairAction.ts
Normal file
109
src/Action/UserFlairAction.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import Action, {ActionConfig, ActionJson, ActionOptions} from './index';
|
||||
import {Comment, RedditUser, Submission} from 'snoowrap';
|
||||
import {RuleResult} from '../Rule';
|
||||
import {ActionProcessResult} from '../Common/interfaces';
|
||||
|
||||
export class UserFlairAction extends Action {
|
||||
text?: string;
|
||||
css?: string;
|
||||
flair_template_id?: string;
|
||||
|
||||
constructor(options: UserFlairActionOptions) {
|
||||
super(options);
|
||||
|
||||
this.text = options.text === null || options.text === '' ? undefined : options.text;
|
||||
this.css = options.css === null || options.text === '' ? undefined : options.text;
|
||||
this.flair_template_id = options.flair_template_id === null || options.flair_template_id === '' ? undefined : options.flair_template_id;
|
||||
}
|
||||
|
||||
getKind() {
|
||||
return 'User Flair';
|
||||
}
|
||||
|
||||
async process(item: Comment | Submission, ruleResults: RuleResult[], runtimeDryrun?: boolean): Promise<ActionProcessResult> {
|
||||
const dryRun = runtimeDryrun || this.dryRun;
|
||||
let flairParts = [];
|
||||
|
||||
if (this.flair_template_id !== undefined) {
|
||||
flairParts.push(`Flair template ID: ${this.flair_template_id}`)
|
||||
if(this.text !== undefined || this.css !== undefined) {
|
||||
this.logger.warn('Text/CSS properties will be ignored since a flair template is specified');
|
||||
}
|
||||
} else {
|
||||
if (this.text !== undefined) {
|
||||
flairParts.push(`Text: ${this.text}`);
|
||||
}
|
||||
if (this.css !== undefined) {
|
||||
flairParts.push(`CSS: ${this.css}`);
|
||||
}
|
||||
}
|
||||
|
||||
const flairSummary = flairParts.length === 0 ? 'Unflair user' : flairParts.join(' | ');
|
||||
this.logger.verbose(flairSummary);
|
||||
|
||||
if (!this.dryRun) {
|
||||
if (this.flair_template_id !== undefined) {
|
||||
try {
|
||||
// @ts-ignore
|
||||
await this.client.assignUserFlairByTemplateId({
|
||||
subredditName: item.subreddit.display_name,
|
||||
flairTemplateId: this.flair_template_id,
|
||||
username: item.author.name,
|
||||
});
|
||||
} catch (err: any) {
|
||||
this.logger.error('Either the flair template ID is incorrect or you do not have permission to access it.');
|
||||
throw err;
|
||||
}
|
||||
} else if (this.text === undefined && this.css === undefined) {
|
||||
// @ts-ignore
|
||||
await item.subreddit.deleteUserFlair(item.author.name);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
await item.author.assignFlair({
|
||||
subredditName: item.subreddit.display_name,
|
||||
cssClass: this.css,
|
||||
text: this.text,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
dryRun,
|
||||
success: true,
|
||||
result: flairSummary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flair the Author of an Activity
|
||||
*
|
||||
* Leave all properties blank or null to remove a User's existing flair
|
||||
* */
|
||||
export interface UserFlairActionConfig extends ActionConfig {
|
||||
/**
|
||||
* The text of the flair to apply
|
||||
* */
|
||||
text?: string,
|
||||
/**
|
||||
* The text of the css class of the flair to apply
|
||||
* */
|
||||
css?: string,
|
||||
/**
|
||||
* Flair template to pick.
|
||||
*
|
||||
* **Note:** If this template is used text/css are ignored
|
||||
* */
|
||||
flair_template_id?: string;
|
||||
}
|
||||
|
||||
export interface UserFlairActionOptions extends UserFlairActionConfig, ActionOptions {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Flair the Submission
|
||||
* */
|
||||
export interface UserFlairActionJson extends UserFlairActionConfig, ActionJson {
|
||||
kind: 'userflair'
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import Snoowrap, {Comment, Submission} from "snoowrap";
|
||||
import {Comment, Submission} from "snoowrap";
|
||||
import {Logger} from "winston";
|
||||
import {RuleResult} from "../Rule";
|
||||
import {SubredditResources} from "../Subreddit/SubredditResources";
|
||||
@@ -6,12 +6,13 @@ import {ActionProcessResult, ActionResult, ChecksActivityState, TypedActivitySta
|
||||
import Author, {AuthorOptions} from "../Author/Author";
|
||||
import {mergeArr} from "../util";
|
||||
import LoggedError from "../Utils/LoggedError";
|
||||
import {ExtendedSnoowrap} from '../Utils/SnoowrapClients';
|
||||
|
||||
export abstract class Action {
|
||||
name?: string;
|
||||
logger: Logger;
|
||||
resources: SubredditResources;
|
||||
client: Snoowrap
|
||||
client: ExtendedSnoowrap;
|
||||
authorIs: AuthorOptions;
|
||||
itemIs: TypedActivityStates;
|
||||
dryRun: boolean;
|
||||
@@ -114,8 +115,8 @@ export abstract class Action {
|
||||
export interface ActionOptions extends ActionConfig {
|
||||
logger: Logger;
|
||||
subredditName: string;
|
||||
resources: SubredditResources
|
||||
client: Snoowrap
|
||||
resources: SubredditResources;
|
||||
client: ExtendedSnoowrap;
|
||||
}
|
||||
|
||||
export interface ActionConfig extends ChecksActivityState {
|
||||
@@ -162,7 +163,7 @@ export interface ActionJson extends ActionConfig {
|
||||
/**
|
||||
* The type of action that will be performed
|
||||
*/
|
||||
kind: 'comment' | 'lock' | 'remove' | 'report' | 'approve' | 'ban' | 'flair' | 'usernote' | 'message'
|
||||
kind: 'comment' | 'lock' | 'remove' | 'report' | 'approve' | 'ban' | 'flair' | 'usernote' | 'message' | 'userflair'
|
||||
}
|
||||
|
||||
export const isActionJson = (obj: object): obj is ActionJson => {
|
||||
|
||||
@@ -29,7 +29,8 @@ import * as RuleSetSchema from '../Schema/RuleSet.json';
|
||||
import * as ActionSchema from '../Schema/Action.json';
|
||||
import {ActionObjectJson, RuleJson, RuleObjectJson, ActionJson as ActionTypeJson} from "../Common/types";
|
||||
import {SubredditResources} from "../Subreddit/SubredditResources";
|
||||
import {Author, AuthorCriteria, AuthorOptions} from "../Author/Author";
|
||||
import {Author, AuthorCriteria, AuthorOptions} from '..';
|
||||
import {ExtendedSnoowrap} from '../Utils/SnoowrapClients';
|
||||
|
||||
const checkLogName = truncateStringToLength(25);
|
||||
|
||||
@@ -50,7 +51,7 @@ export abstract class Check implements ICheck {
|
||||
dryRun?: boolean;
|
||||
notifyOnTrigger: boolean;
|
||||
resources: SubredditResources;
|
||||
client: Snoowrap;
|
||||
client: ExtendedSnoowrap;
|
||||
|
||||
constructor(options: CheckOptions) {
|
||||
const {
|
||||
@@ -345,13 +346,13 @@ export interface ICheck extends JoinCondition, ChecksActivityState {
|
||||
}
|
||||
|
||||
export interface CheckOptions extends ICheck {
|
||||
rules: Array<IRuleSet | IRule>
|
||||
actions: ActionConfig[]
|
||||
logger: Logger
|
||||
subredditName: string
|
||||
notifyOnTrigger?: boolean
|
||||
resources: SubredditResources
|
||||
client: Snoowrap
|
||||
rules: Array<IRuleSet | IRule>;
|
||||
actions: ActionConfig[];
|
||||
logger: Logger;
|
||||
subredditName: string;
|
||||
notifyOnTrigger?: boolean;
|
||||
resources: SubredditResources;
|
||||
client: ExtendedSnoowrap;
|
||||
cacheUserResult?: UserResultCacheOptions;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import {RepeatActivityJSONConfig} from "../Rule/RepeatActivityRule";
|
||||
import {AuthorRuleJSONConfig} from "../Rule/AuthorRule";
|
||||
import {AttributionJSONConfig} from "../Rule/AttributionRule";
|
||||
import {FlairActionJson} from "../Action/SubmissionAction/FlairAction";
|
||||
import {UserFlairActionJson} from "../Action/UserFlairAction";
|
||||
import {CommentActionJson} from "../Action/CommentAction";
|
||||
import {ReportActionJson} from "../Action/ReportAction";
|
||||
import {LockActionJson} from "../Action/LockAction";
|
||||
@@ -18,7 +19,7 @@ import {RepostRuleJSONConfig} from "../Rule/RepostRule";
|
||||
export type RuleJson = RecentActivityRuleJSONConfig | RepeatActivityJSONConfig | AuthorRuleJSONConfig | AttributionJSONConfig | HistoryJSONConfig | RegexRuleJSONConfig | RepostRuleJSONConfig | string;
|
||||
export type RuleObjectJson = Exclude<RuleJson, string>
|
||||
|
||||
export type ActionJson = CommentActionJson | FlairActionJson | ReportActionJson | LockActionJson | RemoveActionJson | ApproveActionJson | BanActionJson | UserNoteActionJson | MessageActionJson | string;
|
||||
export type ActionJson = CommentActionJson | FlairActionJson | ReportActionJson | LockActionJson | RemoveActionJson | ApproveActionJson | BanActionJson | UserNoteActionJson | MessageActionJson | UserFlairActionJson | string;
|
||||
export type ActionObjectJson = Exclude<ActionJson, string>;
|
||||
|
||||
// borrowed from https://github.com/jabacchetta/set-random-interval/blob/master/src/index.ts
|
||||
|
||||
@@ -391,6 +391,7 @@
|
||||
"message",
|
||||
"remove",
|
||||
"report",
|
||||
"userflair",
|
||||
"usernote"
|
||||
],
|
||||
"type": "string"
|
||||
|
||||
@@ -1129,6 +1129,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/FlairActionJson"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/UserFlairActionJson"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentActionJson"
|
||||
},
|
||||
@@ -3207,6 +3210,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/FlairActionJson"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/UserFlairActionJson"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CommentActionJson"
|
||||
},
|
||||
@@ -3508,6 +3514,95 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UserFlairActionJson": {
|
||||
"description": "Flair the Submission",
|
||||
"properties": {
|
||||
"authorIs": {
|
||||
"$ref": "#/definitions/AuthorOptions",
|
||||
"description": "If present then these Author criteria are checked before running the Action. If criteria fails then the Action is not run.",
|
||||
"examples": [
|
||||
{
|
||||
"include": [
|
||||
{
|
||||
"flairText": [
|
||||
"Contributor",
|
||||
"Veteran"
|
||||
]
|
||||
},
|
||||
{
|
||||
"isMod": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"css": {
|
||||
"description": "The text of the css class of the flair to apply",
|
||||
"type": "string"
|
||||
},
|
||||
"dryRun": {
|
||||
"default": false,
|
||||
"description": "If `true` the Action will not make the API request to Reddit to perform its action.",
|
||||
"examples": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"type": "boolean"
|
||||
},
|
||||
"enable": {
|
||||
"default": true,
|
||||
"description": "If set to `false` the Action will not be run",
|
||||
"examples": [
|
||||
true
|
||||
],
|
||||
"type": "boolean"
|
||||
},
|
||||
"flair_template_id": {
|
||||
"description": "Flair template to pick.\n\n**Note:** If this template is used text/css are ignored",
|
||||
"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 Action.\n\nIf any set of criteria passes the Action will be run."
|
||||
},
|
||||
"kind": {
|
||||
"description": "The type of action that will be performed",
|
||||
"enum": [
|
||||
"userflair"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "An optional, but highly recommended, friendly name for this Action. If not present will default to `kind`.\n\nCan only contain letters, numbers, underscore, spaces, and dashes",
|
||||
"examples": [
|
||||
"myDescriptiveAction"
|
||||
],
|
||||
"pattern": "^[a-zA-Z]([\\w -]*[\\w])?$",
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"description": "The text of the flair to apply",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserNoteActionJson": {
|
||||
"description": "Add a Toolbox User Note to the Author of this Activity",
|
||||
"properties": {
|
||||
|
||||
@@ -128,6 +128,12 @@
|
||||
class="font-mono font-semibold">modcontributors</span> for the bot to
|
||||
ban/mute users in the subreddits it moderates</label>
|
||||
</div>
|
||||
<div>
|
||||
<input class="permissionToggle" type="checkbox" id="flair" name="flair"
|
||||
checked>
|
||||
<label for="flair"><span class="font-mono font-semibold">flair</span> for the bot
|
||||
to select subreddit flairs.</label>
|
||||
</div>
|
||||
<div>
|
||||
<input class="permissionToggle" type="checkbox" id="modposts" name="modposts"
|
||||
checked>
|
||||
|
||||
@@ -86,6 +86,11 @@
|
||||
class="font-mono font-semibold">modcontributors</span> for the bot to
|
||||
ban/mute users in the subreddits it moderates</label>
|
||||
</div>
|
||||
<div>
|
||||
<input class="permissionToggle" type="checkbox" id="flair" name="flair" disabled>
|
||||
<label for="flair"><span class="font-mono font-semibold">flair</span> for the bot
|
||||
to select subreddit flairs.</label>
|
||||
</div>
|
||||
<div>
|
||||
<input class="permissionToggle" type="checkbox" id="modposts" name="modposts" disabled>
|
||||
<label for="modposts"><span class="font-mono font-semibold">modposts</span> for the bot
|
||||
|
||||
Reference in New Issue
Block a user