Compare commits

..

2 Commits
edge ... opencv

Author SHA1 Message Date
FoxxMD
ea875e392f feat(image): Implement template matching #99
* Initial template matching logic using openCV
* Test using pokemon cheat logo
* Test using an "exact" selection from a stock image https://unsplash.com/photos/J2RQT7kJSMM
2022-08-24 17:25:55 -04:00
FoxxMD
b89d98e42b feat(image): Integrate openCV dependency
* Add opencv bindings/build packages as optional dependencies
* Add openCV build step to docker image
* document openCV install process for local installations
2022-08-24 12:55:19 -04:00
251 changed files with 6316 additions and 13448 deletions

View File

@@ -1,10 +1,7 @@
.git
logs
.github
_site
.bundle
vendor
docs/.jekyll-cache
docs
node_modules
coverage
.nyc_output
@@ -16,7 +13,7 @@ coverage
*.json5
*.yaml
*.yml
*.env
# exceptions
!heroku.yml
@@ -25,5 +22,3 @@ coverage
!.mocharc.json
!tsconfig.json
!package*.json
!docker/config/**
!_config.yml

1
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,2 @@
github: [FoxxMD]
patreon: FoxxMD
custom: ["bitcoincash:qqmpsh365r8n9jhp4p8ks7f7qdr7203cws4kmkmr8q"]

View File

@@ -1,3 +0,0 @@
{
"ref": "refs/heads/edge"
}

View File

@@ -1,14 +1,4 @@
name: Publish Docker image to registries
# Builds image and tags based on the type of push event:
# * branch push -> tag is branch name IE context-mod:edge
# * release (tag) -> tag is release name IE context-mod:0.13.0
#
# Then pushes tagged images to multiple registries
#
# Based on
# https://github.com/docker/build-push-action/blob/master/docs/advanced/push-multi-registries.md
# https://github.com/docker/metadata-action
name: Publish Docker image to Dockerhub
on:
push:
@@ -23,12 +13,8 @@ on:
jobs:
push_to_registry:
name: Build and Push Docker image to registries
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
permissions:
packages: write
contents: read
steps:
- name: Check out the repo
uses: actions/checkout@v2
@@ -39,22 +25,12 @@ jobs:
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: |
foxxmd/context-mod
ghcr.io/foxxmd/context-mod
images: foxxmd/context-mod
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=latest,enable=${{ endsWith(github.ref, 'master') }}
@@ -64,8 +40,7 @@ jobs:
latest=false
- name: Build and push Docker image
if: ${{ !env.ACT }}
uses: docker/build-push-action@v3
uses: docker/build-push-action@v2
with:
context: .
push: ${{ github.event_name != 'pull_request' }}

View File

@@ -1,53 +0,0 @@
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
name: Deploy Jekyll site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
# Build job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0' # Not needed with a .ruby-version file
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
cache-version: 0 # Increment this number if you need to re-download cached gems
- name: Setup Pages
id: pages
uses: actions/configure-pages@v1
- run: bundle exec jekyll build --baseurl ${{ steps.pages.outputs.base_path }} # defaults output to '/_site'
- name: Upload artifact
uses: actions/upload-pages-artifact@v1 # This will automatically upload an artifact from the '/_site' directory
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1

14
.gitignore vendored
View File

@@ -336,7 +336,6 @@ web_modules/
# dotenv environment variables file
.env
.env.test
*.env
# parcel-bundler cache (https://parceljs.org/)
.cache
@@ -381,17 +380,6 @@ dist
.yarn/install-state.gz
.pnp.*
# Copied from https://github.com/github/gitignore/blob/main/Jekyll.gitignore
# Ignore metadata generated by Jekyll
_site/
.sass-cache/
.jekyll-cache/
.jekyll-metadata
# Ignore folders generated by Bundler
.bundle/
vendor/
**/src/**/*.js
**/tests/**/*.js
**/tests/**/*.map
@@ -403,8 +391,6 @@ vendor/
*.json5
!src/Schema/*.json
!.github/push-hook-sample.json
!docs/**/*.json5
!docs/**/*.yaml
!docs/**/*.json
!docker/config/**

View File

@@ -9,9 +9,6 @@
<excludeFolder url="file://$MODULE_DIR$/src/logs" />
<excludeFolder url="file://$MODULE_DIR$/coverage" />
<excludeFolder url="file://$MODULE_DIR$/.nyc_output" />
<excludeFolder url="file://$MODULE_DIR$/_site" />
<excludeFolder url="file://$MODULE_DIR$/docs/.jekyll-cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor" />
</content>
<content url="file://$MODULE_DIR$/node_modules" />
<orderEntry type="inheritedJdk" />

View File

@@ -81,8 +81,9 @@ RUN apk add --no-cache \
#
# vips required to run sharp library for image comparison
# opencv required for other image processing
RUN echo "http://dl-4.alpinelinux.org/alpine/v3.14/community" >> /etc/apk/repositories \
&& apk --no-cache add vips
&& apk --no-cache add vips opencv opencv-dev
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
@@ -96,26 +97,11 @@ WORKDIR /app
FROM base as build
# copy NPM dependencies and install
COPY --chown=abc:abc package*.json ./
COPY --chown=abc:abc tsconfig.json .
RUN npm install
# copy bundle/jekyll dependencies and docs folder
COPY --chown=abc:abc Gemfile Gemfile.lock _config.yml ./
COPY --chown=abc:abc docs ./docs/
# sassc (a jekll dependency) is very slow to compile bc there are no alpine binaries
# https://github.com/sass/sassc-ruby/issues/189#issuecomment-629758948
# so for now sync used jekyll version with prebuilt binary available in alpine repo
RUN apk add --no-cache --virtual .build-deps \
ruby-jekyll \
&& bundle install \
&& jekyll build -b /docs \
&& apk del .build-deps \
&& rm -rf docs
COPY --chown=abc:abc . /app
RUN npm run build && rm -rf node_modules
@@ -130,6 +116,15 @@ RUN npm install --production \
&& rm -rf node_modules/ts-node \
&& rm -rf node_modules/typescript
# build bindings for opencv
RUN apk add --no-cache --virtual .build-deps \
make \
g++ \
gcc \
libgcc \
&& npm run cv-install-docker-prebuild \
&& apk del .build-deps
ENV NPM_CONFIG_LOGLEVEL debug
# can set database to use more performant better-sqlite3 since we control everything

19
Gemfile
View File

@@ -1,19 +0,0 @@
source 'https://rubygems.org'
# sassc (a jekll dependency) is very slow to compile bc there are no alpine binaries
# https://github.com/sass/sassc-ruby/issues/189#issuecomment-629758948
# so for now sync used jekyll version with prebuilt binary available in alpine repo
gem "jekyll", "4.2.2" # installed by `gem jekyll`
# gem "webrick" # required when using Ruby >= 3 and Jekyll <= 4.2.2
gem "just-the-docs", "0.4.0.rc3" # currently the latest pre-release
# gem "just-the-docs" # the latest release - currently 0.3.3
gem "jekyll-readme-index"
gem 'jekyll-default-layout'
gem 'jekyll-titles-from-headings'
gem 'jekyll-relative-links'
group :jekyll_plugins do
gem 'jekyll-optional-front-matter'
end

View File

@@ -1,90 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
colorator (1.1.0)
concurrent-ruby (1.1.10)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
eventmachine (1.2.7)
ffi (1.15.5)
forwardable-extended (2.6.0)
http_parser.rb (0.8.0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
jekyll (4.2.2)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (~> 2.0)
jekyll-watch (~> 2.0)
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (~> 0.4.0)
pathutil (~> 0.9)
rouge (~> 3.0)
safe_yaml (~> 1.0)
terminal-table (~> 2.0)
jekyll-default-layout (0.1.5)
jekyll (>= 3.0, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-sass-converter (2.2.0)
sassc (> 2.0.1, < 3.0)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
just-the-docs (0.4.0.rc3)
jekyll (>= 3.8.5)
jekyll-seo-tag (>= 2.0)
rake (>= 12.3.1)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.0)
rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.30.0)
safe_yaml (1.0.5)
sassc (2.4.0)
ffi (~> 1.9)
terminal-table (2.0.0)
unicode-display_width (~> 1.1, >= 1.1.1)
unicode-display_width (1.8.0)
PLATFORMS
x86_64-linux
DEPENDENCIES
jekyll (= 4.2.2)
jekyll-default-layout
jekyll-optional-front-matter
jekyll-readme-index
jekyll-relative-links
jekyll-titles-from-headings
just-the-docs (= 0.4.0.rc3)
BUNDLED WITH
2.3.25

View File

@@ -1,13 +1,9 @@
---
title: Home
nav_order: 1
---
# ContextMod [![Latest Release](https://img.shields.io/github/v/release/foxxmd/context-mod)](https://github.com/FoxxMD/context-mod/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker Pulls](https://img.shields.io/docker/pulls/foxxmd/context-mod)](https://hub.docker.com/r/foxxmd/context-mod)
<img src="/docs/logo.png" align="right"
alt="ContextMod logo" width="180" height="176">
[**Context Mod**](https://contextmod.dev/) (CM) is an event-based, [reddit](https://reddit.com) moderation bot built on top of [snoowrap](https://github.com/not-an-aardvark/snoowrap) and written in [typescript](https://www.typescriptlang.org/).
**Context Mod** (CM) is an event-based, [reddit](https://reddit.com) moderation bot built on top of [snoowrap](https://github.com/not-an-aardvark/snoowrap) and written in [typescript](https://www.typescriptlang.org/).
It is designed to help fill in the gaps for [automoderator](https://www.reddit.com/wiki/automoderator/full-documentation) in regard to more complex behavior with a focus on **user-history based moderation.**
@@ -20,27 +16,25 @@ An example of the above that Context Bot can do:
Feature Highlights for **Moderators:**
* Complete bot **autonomy**. YAML config is [stored in your subreddit's wiki](/docs/moderators/gettingStarted.md#setup-wiki-page) (like automoderator)
* Complete bot **autonomy**. YAML config is [stored in your subreddit's wiki](/docs/subreddit/gettingStarted.md#setup-wiki-page) (like automoderator)
* Simple rule-action behavior can be combined to create **complex behavior detection**
* Support Activity filtering based on:
* [Author criteria](docs/subreddit-configuration/in-depth/filters/README.md#author-filter) (name, css flair/text, age, karma, moderator status, [Toolbox User Notes](https://www.reddit.com/r/toolbox/wiki/docs/usernotes), and more!)
* [Activity state](docs/subreddit-configuration/in-depth/filters/README.md#item-filter) (removed, locked, distinguished, etc...)
* State of Subreddit Activity is in [Subreddit](docs/subreddit-configuration/in-depth/filters/README.md#subreddit-filter) (nsfw, name, profile, etc...)
* Rules and Actions support [named references](docs/subreddit-configuration/README.md#named-rules) -- **write once, reference anywhere**
* Powerful [logic control](docs/subreddit-configuration/advancedConcepts/flowControl.md) (if, then, goto)
* [Delay/re-process activities](docs/subreddit-configuration/README.md#dispatch) using arbitrary rules
* [**Image Comparisons**](docs/subreddit-configuration/imageComparison.md) via fingerprinting and/or pixel differences
* [**Repost detection**](docs/subreddit-configuration/in-depth/repost) with support for external services (youtube, etc...)
* [Author criteria](/docs/subreddit/components/README.md#author-filter) (name, css flair/text, age, karma, moderator status, [Toolbox User Notes](https://www.reddit.com/r/toolbox/wiki/docs/usernotes), and more!)
* [Activity state](/docs/subreddit/components/README.md#item-filter) (removed, locked, distinguished, etc...)
* State of Subreddit Activity is in [Subreddit](/docs/subreddit/components/README.md#subreddit-filter) (nsfw, name, profile, etc...)
* Rules and Actions support [named references](/docs/subreddit/components/README.md#named-rules) -- **write once, reference anywhere**
* Powerful [logic control](/docs/subreddit/components/advancedConcepts/flowControl.md) (if, then, goto)
* [Delay/re-process activities](/docs/subreddit/components/README.md#dispatch) using arbitrary rules
* [**Image Comparisons**](/docs/imageComparison.md) via fingerprinting and/or pixel differences
* [**Repost detection**](/docs/subreddit/components/repost) with support for external services (youtube, etc...)
* Event notification via Discord
* [**Web interface**](#web-ui-and-screenshots) for monitoring, administration, and oauth bot authentication
* [**Placeholders**](docs/subreddit-configuration/actionTemplating.md) (like automoderator) can be configured via a wiki page or raw text and supports [mustache](https://mustache.github.io) templating
* [**Partial Configurations**](docs/subreddit-configuration/README.md#partial-configurations) -- offload parts of your configuration to shared locations to consolidate logic between multiple subreddits
* [Guest Access](docs/moderators/README.md#guest-access) enables collaboration and easier setup by allowing temporary access
* [Toxic content prediction](docs/subreddit-configuration/README.md#moderatehatespeechcom-predictions) using [moderatehatespeech.com](https://moderatehatespeech.com) machine learning model
* [**Placeholders**](/docs/subreddit/actionTemplating.md) (like automoderator) can be configured via a wiki page or raw text and supports [mustache](https://mustache.github.io) templating
* [**Partial Configurations**](/docs/subreddit/components/README.md#partial-configurations) -- offload parts of your configuration to shared locations to consolidate logic between multiple subreddits
Feature highlights for **Developers and Hosting (Operators):**
* [Server/client architecture](/docs/operator/serverClientArchitecture.md)
* [Server/client architecture](/docs/serverClientArchitecture.md)
* Default/no configuration runs "All In One" behavior
* Additional configuration allows web interface to connect to multiple servers
* Each server instance can run multiple reddit accounts as bots
@@ -48,7 +42,7 @@ Feature highlights for **Developers and Hosting (Operators):**
* [Database Persistence](/docs/operator/database.md) using SQLite, MySql, or Postgres
* Audit trails for bot activity
* Historical statistics
* [Docker container](/docs/operator/installation.md#docker-recommended) and [docker-compose](/docs/operator/installation.md#docker-compose) support
* [Docker container support](/docs/operator/installation.md#docker-recommended)
* Easy, UI-based [OAuth authentication](/docs/operator/addingBot.md) for adding Bots and moderator dashboard
* Integration with [InfluxDB](https://www.influxdata.com) for detailed [time-series metrics](/docs/operator/database.md#influx) and a pre-built [Grafana](https://grafana.com) [dashboard](/docs/operator/database.md#grafana)
@@ -63,7 +57,7 @@ Feature highlights for **Developers and Hosting (Operators):**
Each subreddit using the RCB bot configures its behavior via their own wiki page.
When a monitored **Activity** (new comment/submission, new modqueue item, etc.) is detected the bot runs through a list of [**Checks**](docs/subreddit-configuration/README.md#checks) to determine what to do with the **Activity** from that Event. Each **Check** consists of :
When a monitored **Activity** (new comment/submission, new modqueue item, etc.) is detected the bot runs through a list of [**Checks**](/docs/subreddit/components/README.md#checks) to determine what to do with the **Activity** from that Event. Each **Check** consists of :
#### Kind
@@ -71,11 +65,11 @@ Is this check for a submission or comment?
#### Rules
A list of [**Rules**](docs/subreddit-configuration/README.md#rules) to run against the **Activity**. Triggered Rules can cause the whole Check to trigger and run its **Actions**
A list of [**Rules**](/docs/subreddit/components/README.md#rules) to run against the **Activity**. Triggered Rules can cause the whole Check to trigger and run its **Actions**
#### Actions
A list of [**Actions**](docs/subreddit-configuration/README.md#actions) that describe what the bot should do with the **Activity** or **Author** of the activity (comment, remove, approve, etc.). The bot will run **all** Actions in this list.
A list of [**Actions**](/docs/subreddit/components/README.md#actions) that describe what the bot should do with the **Activity** or **Author** of the activity (comment, remove, approve, etc.). The bot will run **all** Actions in this list.
___
@@ -99,14 +93,14 @@ See the [Operator's Getting Started Guide](/docs/operator/gettingStarted.md)
This guide is for **reddit moderators** who want to configure an existing CM bot to run on their subreddit.
See the [Moderator's Getting Started Guide](/docs/moderators/gettingStarted.md)
See the [Moderator's Getting Started Guide](/docs/subreddit/gettingStarted.md)
## Configuration and Documentation
Context Bot's configuration can be written in YAML (like automoderator) or [JSON5](https://json5.org/). Its schema conforms to [JSON Schema Draft 7](https://json-schema.org/). Additionally, many **operator** settings can be passed via command line or environmental variables.
* For **operators** (running the bot instance) see the [Operator Configuration](/docs/operator/configuration.md) guide
* For **moderators** consult the [Subreddit Configuration Docs](/docs/subreddit-configuration/README.md)
* For **moderators** consult the [app schema and examples folder](/docs/README.md#configuration-and-usage)
[**Check the full docs for in-depth explanations of all concepts and examples**](/docs)
@@ -140,10 +134,6 @@ Moderator view/invite and authorization:
![Invite View](docs/images/oauth-invite.jpg)
A similar helper and invitation experience is available for adding **subreddits to an existing bot.**
![Subreddit Invite View](docs/images/subredditInvite.jpg)
### Configuration Editor
A built-in editor using [monaco-editor](https://microsoft.github.io/monaco-editor/) makes editing configurations easy:

View File

@@ -1,45 +0,0 @@
title: ContextMod
description: Documentation for ContextMod
theme: just-the-docs
source: docs
url: https://contextmod.dev
color_scheme: dark
mermaid:
version: "9.1.3"
aux_links:
Github: https://github.com/foxxmd/context-mod
plugins:
- jekyll-readme-index
- jekyll-default-layout
- jekyll-titles-from-headings
- jekyll-optional-front-matter
- jekyll-relative-links
titles_from_headings:
enabled: true
strip_title: false
collections: false
readme_index:
enabled: true
remove_originals: true
with_frontmatter: true
optional_front_matter:
remove_originals: true
defaults:
- scope:
path: ""
values:
has_toc: false
- scope:
path: "images"
values:
image: true

View File

@@ -1,3 +0,0 @@
GITHUB_TOKEN=
DOCKERHUB_USERNAME=
DOCKER_PASSWORD=

View File

@@ -1,62 +0,0 @@
version: '3.7'
services:
app:
image: foxxmd/context-mod:latest
# use the settings below, instead of 'image', if running context-mod from the repository (developing local changes)
# build:
# context: .
volumes:
# Location of config file to use with CM
# The path BEFORE the colon (:) is the path on the host machine
# which defaults to a folder named 'data' in the same directory this file is run in.
- './data:/config'
# For a new installation you should use the config from the repository included for use with docker-compose
# https://github.com/FoxxMD/context-mod/blob/master/docker/config/docker-compose/config.yaml
# Copy config.yaml to /(this directory)/data/config.yaml and then modify to match any changed settings below (see comments on config.yaml)
ports:
- "${CM_WEB-8085}:8085"
environment:
IS_DOCKER: true
# If using a linux host, uncomment these and set them accordingly https://github.com/FoxxMD/context-mod/blob/master/docs/operator/installation.md#linux-host
# PUID: 1000
# PGID: 1000
cache:
image: 'redis:7-alpine'
volumes:
# on linux will need to make sure this directory has correct permissions for container to access
- './data/cache:/data'
database:
image: 'mariadb:10.9.3'
environment:
MYSQL_ROOT_PASSWORD: CHANGE_THIS
MYSQL_USER: cmuser
# this should match the password set in config.yaml
MYSQL_PASSWORD: CHANGE_THIS
MYSQL_DATABASE: ContextMod
volumes:
- './data/db:/var/lib/mysql'
influx:
image: 'influxdb:latest'
volumes:
- './data/influx:/var/lib/influxdb2'
ports:
- "${INFLUX_WEB:-8086}:8086"
profiles:
- full
grafana:
image: 'grafana/grafana'
volumes:
- './data/grafana:/var/lib/grafana'
ports:
- "${GRAFANA_WEB:-3000}:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: CHANGE_THIS
depends_on:
- influx
profiles:
- full

View File

@@ -1,43 +0,0 @@
operator:
name: CHANGE_THIS #YOUR REDDIT USERNAME HERE
logging:
# default level for all transports
level: debug
file:
# override default level
level: warn
# true -> log folder at projectDir/log
dirname: true
caching:
provider:
store: redis
host: cache
port: 6379
prefix: prod
databaseConfig:
migrations:
continueOnAutomatedBackup: true
#force: true # uncomment this to make cm run new migrations without confirmation
#logging: ['query', 'error', 'warn', 'log'] # uncomment this to get typeorm to log EVERYTHING
connection:
type: 'mariadb'
host: 'database'
username: 'cmuser'
# This should match the password set in docker-compose.yaml
password: 'CHANGE_THIS'
database: 'ContextMod'
web:
credentials:
redirectUri: 'http://localhost:8085/callback'
session:
storage: cache
port: 8085
#
# Influx/Grafana requires additional configuration. See https://github.com/FoxxMD/context-mod/blob/master/docs/operator/database.md#influx
#
#influxConfig:
# credentials:
# url: 'http://influx:8086'
# token: 'YourInfluxToken'
# org: YourInfluxOrg
# bucket: contextmod

View File

@@ -1,8 +1,4 @@
---
title: Overview
permalink: /overview.html
nav_order: 2
---
# Documentation
# Table of Contents
@@ -26,8 +22,8 @@ nav_order: 2
Review **at least** the **How It Works** and **Concepts** below, then:
* For **Operators** (running a bot instance) refer to [**Operator Getting Started**](operator/gettingStarted.md) guide
* For **Moderators** (configuring an existing bot for your subreddit) refer to the [**Moderator Getting Started**](moderators/gettingStarted.md) guide
* For **Operators** (running a bot instance) refer to [**Operator Getting Started**](/docs/operator/gettingStarted.md) guide
* For **Moderators** (configuring an existing bot for your subreddit) refer to the [**Moderator Getting Started**](/docs/subreddit/gettingStarted.md) guide
## How It Works
@@ -37,10 +33,10 @@ Where possible Context Mod (CM) uses the same terminology as, and emulates the b
Expand the section below for a simplified flow diagram of how CM processes an incoming Activity. Then refer the text description of the diagram below as well as [Concepts](#Concepts) for descriptions of individual components.
<details markdown="block">
<details>
<summary>Diagram</summary>
![Flow Diagram](images/diagram-highlevel.jpg)
![Flow Diagram](/docs/images/diagram-highlevel.jpg)
</details>
@@ -96,7 +92,7 @@ An example of Runs:
Both group of Checks are independent of each other (don't have any patterns or actions in common).
[Full Documentation for Runs](subreddit-configuration/README.md#runs)
[Full Documentation for Runs](/docs/subreddit/components/README.md#runs)
### Checks
@@ -109,7 +105,7 @@ A Run can be made up of one or more **Checks** that are processed **in the order
Once a Check is **triggered** (its Rules are satisfied and Actions performed) all subsequent Checks are skipped.
[Full Documentation for Checks](subreddit-configuration/README.md#checks)
[Full Documentation for Checks](/docs/subreddit/components/README.md#checks)
### Rule
@@ -117,11 +113,11 @@ A **Rule** is some set of **criteria** (conditions) that are tested against an A
CM has different **Rules** that can test against different types of behavior and aspects of a User, their history, and the Activity (submission/common) being checked.
[Full Documentation for Rules](subreddit-configuration/README.md#rules)
[Full Documentation for Rules](/docs/subreddit/components/README.md#rules)
#### Available Rules
All available rules can be found in the [components documentation](subreddit-configuration/README.md#rules)
All available rules can be found in the [components documentation](/docs/subreddit/components/README.md#rules)
### Rule Set
@@ -131,7 +127,7 @@ Rule Sets can be used interchangeably with other **Rules** and **Rule Sets** in
They allow you to create more complex trigger behavior by combining multiple rules into one "parent rule".
[Rule Sets Documentation](subreddit-configuration/README.md#rule-sets)
[Rule Sets Documentation](/docs/subreddit/components/README.md#rule-sets)
### Action
@@ -139,7 +135,7 @@ An **Action** is some action the bot can take against the checked Activity (comm
#### Available Actions
[Available Actions Documentation](subreddit-configuration/README.md#list-of-actions)
[Available Actions Documentation](/docs/subreddit/components/README.md#list-of-actions)
### Filters
@@ -150,14 +146,13 @@ An **Action** is some action the bot can take against the checked Activity (comm
* When the filter test **passes** the thing being tested continues to process as usual
* When the filter test **fails** the thing being tested **fails**.
[Full Documentation for Filters](subreddit-configuration/README.md#filters)
[Full Documentation for Filters](/docs/subreddit/components/README.md#filters)
## Configuration And Usage
* For **Operator/Bot maintainers** see **[Operation Guide](operator/README.md)**
* For **Operator/Bot maintainers** see **[Operation Guide](/docs/operator/README.md)**
* For **Moderators**
* Start with the [Subreddit/Moderator docs](moderators/README.md) or [Moderator Getting Started guide](moderators/gettingStarted.md)
* Refer to the [Subreddit Components Documentation](subreddit-configuration) or the [subreddit-ready examples](subreddit-configuration/cookbook)
* Refer to the [Subreddit Components Documentation](/docs/subreddit/components) or the [subreddit-ready examples](/docs/subreddit/components/subredditReady)
* as well as the [schema](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) which has
* fully annotated configuration data/structure
* generated examples in json/yaml

View File

@@ -1,40 +1,4 @@
---
nav_order: 7
---
# Development
# Serving Docs Locally
Requirements:
* [Jeykll](https://jekyllrb.com/) installed
* Ruby 2.5.0 or higher and [RubyGems](https://rubygems.org/pages/download) (usually bundled)
* [Bundler](https://bundler.io/) installed
## Install Doc Dependencies
```bash
npm run docs-install
```
## Serve Docs
```bash
npm run docs-start
```
# Developing/Testing Github Actions
Use [act](https://github.com/nektos/act) to run Github actions locally.
An example secrets file can be found in the project working directory at [act.env.example](../act.env.example)
Modify [push-hook-sample.json](../.github/push-hook-sample.json) to point to the local branch you want to run a `push` event trigger on, then run this command from the project working directory:
```bash
act -e .github/push-hook-sample.json --secret-file act.env
```
TODO add more development sections...
# Mocking Reddit API
@@ -52,7 +16,7 @@ Map port `1080:1080` -- acts as both the proxy port and the UI endpoint with the
http(s)://localhost:1080/mockserver/dashboard
```
In your [operator configuration](operator/configuration.md) define a proxy for snoowrap at the top-level:
In your [operator configuration](/docs/operator/operatorConfiguration.md) define a proxy for snoowrap at the top-level:
```yaml
snoowrap:
@@ -83,7 +47,7 @@ Content-Length: 155
--data-raw '{
"httpRequest": {},
"priority": 0,
"httpForward": {
"httpForward": {
"host": "oauth.reddit.com",
"port": 443,
"scheme": "HTTPS"
@@ -119,7 +83,7 @@ The lifecycle of a mock call I do:
Content-Type: application/json
Content-Length: 1757
```
```
</details>
@@ -202,7 +166,7 @@ Content-Length: 1757
```
</details>
#### All Responses Timeout
<details>
@@ -284,7 +248,7 @@ curl --location --request PUT 'http://localhost:8010/mockserver/expectation' \
### Clearing Behavior
```HTTP
```HTTP
PUT /mockserver/clear?type=EXPECTATIONS HTTP/1.1
Host: localhost:8010
Content-Type: application/json
@@ -311,7 +275,7 @@ Content-Length: 251
</details>
<details markdown="block">
<details>
<summary>CURL</summary>
```bash
@@ -337,7 +301,7 @@ curl --location --request PUT 'http://localhost:8010/mockserver/expectation' \
#### All Responses Drop After Delay (Connection Closed by Server)
<details markdown="block">
<details>
<summary>HTTP</summary>
```HTTP
@@ -364,7 +328,7 @@ Content-Length: 234
</details>
<details markdown="block">
<details>
<summary>CURL</summary>
```bash
@@ -402,7 +366,7 @@ Content-Length: 26
}
```
<details markdown="block">
<details>
<summary>CURL</summary>
```bash

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,13 +1,8 @@
---
title: Image Comparison
parent: Subreddit Configuration
---
# Overview
ContextMod supports comparing image content, for the purpose of detecting duplicates, with two different but complimentary systems. Image comparison behavior is available for the following rules:
* [Recent Activity](in-depth/recentActivity)
* [Recent Activity](/docs/subreddit/components/recentActivity)
* Repeat Activity (In-progress)
To enable comparisons reference the example below (at the top-level of your rule) and configure as needed:
@@ -44,7 +39,6 @@ YAML
```yaml
name: ruleWithImageDetection
kind: recentActivity
imageDetection:
enable: true
threshold: 5
fetchBehavior: extension

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 479 KiB

View File

@@ -1,169 +0,0 @@
---
title: Home
nav_order: 1
---
# ContextMod [![Latest Release](https://img.shields.io/github/v/release/foxxmd/context-mod)](https://github.com/FoxxMD/context-mod/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker Pulls](https://img.shields.io/docker/pulls/foxxmd/context-mod)](https://hub.docker.com/r/foxxmd/context-mod)
<img src="/logo.png" align="right"
alt="ContextMod logo" width="180" height="176">
[**Context Mod**](https://contextmod.dev/) (CM) is an event-based, [reddit](https://reddit.com) moderation bot built on top of [snoowrap](https://github.com/not-an-aardvark/snoowrap) and written in [typescript](https://www.typescriptlang.org/).
It is designed to help fill in the gaps for [automoderator](https://www.reddit.com/wiki/automoderator/full-documentation) in regard to more complex behavior with a focus on **user-history based moderation.**
An example of the above that Context Bot can do:
> * On a new submission, check if the user has also posted the same link in **N** number of other subreddits within a timeframe/# of posts
> * On a new submission or comment, check if the user has had any activity (sub/comment) in **N** set of subreddits within a timeframe/# of posts
>
>In either instance Context Bot can then perform any action a moderator can (comment, report, remove, lock, etc...) against that user, comment, or submission.
Feature Highlights for **Moderators:**
* Complete bot **autonomy**. YAML config is [stored in your subreddit's wiki](moderators/gettingStarted.md#setup-wiki-page) (like automoderator)
* Simple rule-action behavior can be combined to create **complex behavior detection**
* Support Activity filtering based on:
* [Author criteria](subreddit-configuration/in-depth/filters/README.md#author-filter) (name, css flair/text, age, karma, moderator status, [Toolbox User Notes](https://www.reddit.com/r/toolbox/wiki/usernotes), and more!)
* [Activity state](subreddit-configuration/in-depth/filters/README.md#item-filter) (removed, locked, distinguished, etc...)
* State of Subreddit Activity is in [Subreddit](subreddit-configuration/in-depth/filters/README.md#subreddit-filter) (nsfw, name, profile, etc...)
* Rules and Actions support [named references](subreddit-configuration/README.md#named-rules) -- **write once, reference anywhere**
* Powerful [logic control](subreddit-configuration/advancedConcepts/flowControl.md) (if, then, goto)
* [Delay/re-process activities](subreddit-configuration/README.md#dispatch) using arbitrary rules
* [**Image Comparisons**](subreddit-configuration/imageComparison.md) via fingerprinting and/or pixel differences
* [**Repost detection**](subreddit-configuration/in-depth/repost) with support for external services (youtube, etc...)
* Event notification via Discord
* [**Web interface**](#web-ui-and-screenshots) for monitoring, administration, and oauth bot authentication
* [**Placeholders**](subreddit-configuration/actionTemplating.md) (like automoderator) can be configured via a wiki page or raw text and supports [mustache](https://mustache.github.io) templating
* [**Partial Configurations**](subreddit-configuration/README.md#partial-configurations) -- offload parts of your configuration to shared locations to consolidate logic between multiple subreddits
* [Guest Access](moderators/README.md#guest-access) enables collaboration and easier setup by allowing temporary access
* [Toxic content prediction](subreddit-configuration/README.md#moderatehatespeechcom-predictions) using [moderatehatespeech.com](https://moderatehatespeech.com) machine learning model
Feature highlights for **Developers and Hosting (Operators):**
* [Server/client architecture](operator/serverClientArchitecture.md)
* Default/no configuration runs "All In One" behavior
* Additional configuration allows web interface to connect to multiple servers
* Each server instance can run multiple reddit accounts as bots
* Global/subreddit-level [**caching**](operator/caching.md) of Reddit APIs responses and CM results
* [Database Persistence](operator/database.md) using SQLite, MySql, or Postgres
* Audit trails for bot activity
* Historical statistics
* [Docker container](operator/installation.md#docker-recommended) and [docker-compose](operator/installation.md#docker-compose) support
* Easy, UI-based [OAuth authentication](operator/addingBot.md) for adding Bots and moderator dashboard
* Integration with [InfluxDB](https://www.influxdata.com) for detailed [time-series metrics](operator/database.md#influx) and a pre-built [Grafana](https://grafana.com) [dashboard](operator/database.md#grafana)
# Table of Contents
* [How It Works](#how-it-works)
* [Getting Started](#getting-started)
* [Configuration And Documentation](#configuration-and-documentation)
* [Web UI and Screenshots](#web-ui-and-screenshots)
### How It Works
Each subreddit using the RCB bot configures its behavior via their own wiki page.
When a monitored **Activity** (new comment/submission, new modqueue item, etc.) is detected the bot runs through a list of [**Checks**](subreddit-configuration/README.md#checks) to determine what to do with the **Activity** from that Event. Each **Check** consists of :
#### Kind
Is this check for a submission or comment?
#### Rules
A list of [**Rules**](subreddit-configuration/README.md#rules) to run against the **Activity**. Triggered Rules can cause the whole Check to trigger and run its **Actions**
#### Actions
A list of [**Actions**](subreddit-configuration/README.md#actions) that describe what the bot should do with the **Activity** or **Author** of the activity (comment, remove, approve, etc.). The bot will run **all** Actions in this list.
___
The **Checks** for a subreddit are split up into **Submission Checks** and **Comment Checks** based on their **kind**. Each list of checks is run independently based on when events happen (submission or comment).
When an Event occurs all Checks of that type are run in the order they were listed in the configuration. When one check is triggered (an Action is performed) the remaining checks will not be run.
___
[Learn more about the RCB lifecycle and core concepts in the docs.](/README.md#how-it-works)
## Getting Started
#### Operators
This guide is for users who want to **run their own bot on a ContextMod instance.**
See the [Operator's Getting Started Guide](operator/gettingStarted.md)
#### Moderators
This guide is for **reddit moderators** who want to configure an existing CM bot to run on their subreddit.
See the [Moderator's Getting Started Guide](moderators/gettingStarted.md)
## Configuration and Documentation
Context Bot's configuration can be written in YAML (like automoderator) or [JSON5](https://json5.org/). Its schema conforms to [JSON Schema Draft 7](https://json-schema.org/). Additionally, many **operator** settings can be passed via command line or environmental variables.
* For **operators** (running the bot instance) see the [Operator Configuration](operator/configuration.md) guide
* For **moderators** consult the [Subreddit Configuration Docs](subreddit-configuration/README.md)
[**Check the full docs for in-depth explanations of all concepts and examples**](/docs)
## Web UI and Screenshots
### Dashboard
CM comes equipped with a dashboard designed for use by both moderators and bot operators.
* Authentication via Reddit OAuth -- only accessible if you are the bot operator or a moderator of a subreddit the bot moderates
* Connect to multiple ContextMod instances (specified in configuration)
* Monitor API usage/rates
* Monitoring and administration **per subreddit:**
* Start/stop/pause various bot components
* View statistics on bot usage (# of events, checks run, actions performed) and cache usage
* View various parts of your subreddit's configuration and manually update configuration
* View **real-time logs** of what the bot is doing on your subreddit
* **Run bot on any permalink**
![Subreddit View](images/subredditStatus.jpg)
### Bot Setup/Authentication
A bot oauth helper allows operators to define oauth credentials/permissions and then generate unique, one-time invite links that allow moderators to authenticate their own bots without operator assistance. [Learn more about using the oauth helper.](operator/addingBot.md#cm-oauth-helper-recommended)
Operator view/invite link generation:
![Oauth View](images/oauth.jpg)
Moderator view/invite and authorization:
![Invite View](images/oauth-invite.jpg)
A similar helper and invitation experience is available for adding **subreddits to an existing bot.**
![Subreddit Invite View](images/subredditInvite.jpg)
### Configuration Editor
A built-in editor using [monaco-editor](https://microsoft.github.io/monaco-editor/) makes editing configurations easy:
* Automatic JSON or YAML syntax validation and formatting
* Automatic Schema (subreddit or operator) validation
* All properties are annotated via hover popups
* Unauthenticated view via `yourdomain.com/config`
* Authenticated view loads subreddit configurations by simple link found on the subreddit dashboard
* Switch schemas to edit either subreddit or operator configurations
![Configuration View](images/editor.jpg)
### [Grafana Dashboard](operator/database.md#grafana)
* Overall stats (active bots/subreddits, api calls, per second/hour/minute activity ingest)
* Over time graphs for events, per subreddit, and for individual rules/check/actions
![Grafana Dashboard](images/grafana.jpg)
## License
[MIT](/LICENSE)

View File

@@ -1,101 +0,0 @@
---
has_children: true
title: Moderators
nav_order: 3
---
This section is for **reddit moderators**. It covers how to use a CM bot for your subreddit.
If you are trying to run a ContextMod instance (the actual software) please refer to the [operator section](../operator/README.md).
# Table of Contents
* [Overview](#overview)
* [Your Relationship to CM](#your-relationship-to-cm)
* [Operator](#operator)
* [Your Bot](#your-bot)
* [Getting Started](#getting-started)
* [Accessing The Bot](#accessing-the-bot)
* [Editing The Bot](#editing-the-bot)
* [Configuration](#configuration)
* [Guest Access](#guest-access)
# Overview
The Context Mod **software** can manage multiple **bots** (reddit accounts used as bots, like `/u/MyCMBot`). Each bot can manage (run) multiple **subreddits** which is determined by the subreddits the account is a moderator of.
You, the moderator of a subreddit a CM bot runs in, can access/manage the Bot using the CM software's [web interface](../images/subredditStatus.jpg) and control its behavior using the [web editor.](../images/editor.jpg)
## Your Relationship to CM
It is important to understand the relationship between you (the moderator), the bot, and the operator (the person running the CM software).
The easiest way to think about this is in relation to how you use Automoderator and interact with Reddit as a moderator. As an analogy:
### Operator
The operator is the person running the actual server/machine the Context Mod software is on.
They are best thought of as **Reddit:**
* Mostly hands-off when it comes to the bot and interacting with your subreddit
* You must interact with Reddit first before you can use automoderator (login, create a subreddit, etc...)
Unlike reddit, though, there is a greater level of trust required between you and the Operator because what you make the Bot do ultimately affects the Operator since they are the ones actually running your Bot and making API calls to reddit.
### Your Bot
Your bot is like an **invite-only version of Automoderator**:
* Unlike automoderator, you **must** interact with the Operator in order to get the bot working. It is not public for anyone to use.
* Like automoderator, you **must** create a [configuration](../subreddit-configuration/README.md) for it do anything.
* The bot does not come pre-configured for you. It is a blank slate and requires user input to be useful.
* Also like automoderator, you are **entirely in control of the bot.**
* You can start, stop, and edit its behavior at any time without needing to communicate with the Operator.
* CM provides you _tools_, different ways the Bot can detect patterns in your subreddit/users as well as actions it can, and you can decide to use them however you want.
* Your bot is **only accessible to moderators of your subreddit.**
# Getting Started
The [Getting Started](gettingStarted.md) guide lays out the steps needed to go from nothing to a working Bot. If you are a moderator new to Context Mod this is where you want to begin.
# Accessing The Bot
All bot management and editing is done through the [web interface.](/../images/subredditStatus.jpg) The URL used for accessing this interface is given to you by the **Operator** once they have agreed to host your bot/subreddit.
NOTE: This interface is **only access to moderators of your subreddit** and [guests.](#guest-access) You must login to the web interface **with your moderator account** in order to access it.
A **guided tour** that helps show how to manage the bot at a high-level is available on the web interface by clicking the **Help** button in the top-right of the page.
## Editing The Bot
Find the [editor in the web interface](../webInterface.md#editingupdating-your-config) to access the built-in editor for the bot.
[The editor](../images/editor.jpg) should be your all-in-one location for viewing and editing your bot's behavior. **It is equivalent to Automoderator's editor page.**
The editor features:
* syntax validation and highlighting
* configuration auto-complete and documentation (hover over properties)
* built-in validation using Microsoft Word "squiggly lines" indicators and an error list at the bottom of the window
* built-in saving (at the top of the window)
# Configuration
Use the [Configuration Reference](../subreddit-configuration/README.md) to learn about all the different components available for building a CM configuration.
Additionally, refer to [How It Works](../README.md#how-it-works) and [Core Concepts](../README.md#concepts) to learn the basic of CM configuration.
After you have the basics under your belt you could use the [subreddit configurations cookbook](../subreddit-configuration/cookbook) to familiarize yourself with a complete configuration and ways to use CM.
# Guest Access
CM supports **Guest Access**. Reddit users who are given Guest Access to your bot are allowed to access the web interface even though they are not moderators.
Additionally, they can edit the subreddit's config using the bot. If a Guest edits your config their username will be mentioned in the wiki page edit reason.
Guests can do everything a regular mod can except view/add/remove Guest. They can be removed at any time or set with an expiration date that their access is removed on.
**Guests are helpful if you are new to CM and know reddit users that can help you get started.**
[Add guests from the Subreddit tab in the main interface.](../images/guests.jpg)

View File

@@ -1,9 +1,4 @@
---
has_children: true
nav_order: 4
---
# Operator
# Operator Guide
An **Operator** is the user **running the ContextMod software.**
@@ -11,18 +6,18 @@ They are responsible for configuring the software at a high-level and managing a
* Creating cache/database servers and configuring their connections in CM
* Provisioning the [Reddit Clients](#provisioning-a-reddit-client) needed to run bots and the CM UI
* Providing [global-level configuration](configuration.md) that affects general bot/subreddit behavior
* Providing [global-level configuration](/docs/operator/configuration.md) that affects general bot/subreddit behavior
* Onboarding new bots/subreddits
# Table of Contents
* [Overview](#overview)
* [Client-Server Architecture](serverClientArchitecture.md)
* [Getting Started](gettingStarted.md)
* [Installation](installation.md)
* [Client-Server Architecture](/docs/serverClientArchitecture.md)
* [Getting Started](/docs/operator/gettingStarted.md)
* [Installation](/docs/operator/installation.md)
* [Provisioning a Reddit Client](#provisioning-a-reddit-client)
* [Configuration](configuration.md)
* [Adding A Bot](addingBot.md)
* [Configuration](/docs/operator/configuration.md)
* [Adding A Bot](/docs/operator/addingBot.md)
# Overview
@@ -33,13 +28,13 @@ CM is composed of two applications that operate independently but are packaged t
Both applications authenticate, and are primarily operated, by using [Reddit's API through OAuth.](https://github.com/reddit-archive/reddit/wiki/OAuth2) The **Client** uses OAuth to verify the identity of moderators logging into the web interface. The **Server** uses oauth tokens to interact with Reddit's API and operate all the configured bots.
In its default mode of operation CM takes care of all the interaction between **Server** and **Client** for you so that you can effectively treat it as a monolithic application. Learn more about CM's architecture and other operation modes in the [Server-Client Architecture documentation.](../serverClientArchitecture.md)
In its default mode of operation CM takes care of all the interaction between **Server** and **Client** for you so that you can effectively treat it as a monolithic application. Learn more about CM's architecture and other operation modes in the [Server-Client Architecture documentation.](/docs/serverClientArchitecture.md)
# [Getting Started](gettingStarted.md)
# [Getting Started](/docs/operator/gettingStarted.md)
The [Getting Started](gettingStarted.md) guide serves as a straight-forward "how-to" for standing up a CM server from scratch with minimal explanation.
The [Getting Started](/docs/operator/gettingStarted.md) guide serves as a straight-forward "how-to" for standing up a CM server from scratch with minimal explanation.
# [Installation](installation.md)
# [Installation](/docs/operator/installation.md)
CM has many installation options:
@@ -47,7 +42,7 @@ CM has many installation options:
* Built/pulled from a Docker image hosted on Dockerhub
* Deployed to Heroku with a Quick Deploy template (experimental)
Refer to the [Installation](installation.md) docs for more information.
Refer to the [Installation](/docs/operator/installation.md) docs for more information.
# Provisioning A Reddit Client
@@ -65,18 +60,18 @@ Click **create app**.
Then write down your **Client ID, Client Secret, and Redirect Uri** somewhere
# [Configuration](configuration.md)
# [Configuration](/docs/operator/configuration.md)
The [Configuration](configuration.md) documentation covers:
The [Configuration](/docs/operator/configuration.md) documentation covers:
* How CM's configuration can be defined
* How to create and define location for a config file
* Running CM from the command line
* Documentation for configuration on Bots, the web client, API, and more...
# [Adding A Bot](addingBot.md)
# [Adding A Bot](/docs/operator/addingBot.md)
The [Adding A Bot](addingBot.md) documentation covers:
The [Adding A Bot](/docs/operator/addingBot.md) documentation covers:
* What is a Bot?
* What is needed to add a Bot to CM?

View File

@@ -1,10 +1,3 @@
---
parent: Operator
nav_order: 4
---
# Adding A Bot
# Table of Contents
* [What is a Bot?](#what-is-a-bot)
@@ -26,7 +19,7 @@ There is nothing special about the account! What's special is how its used -- th
These things need to be done before a Bot can be added to CM:
* [Provisioned a Reddit Client](README.md#provisioning-a-reddit-client)
* [Provisioned a Reddit Client](/docs/operator/README.md#provisioning-a-reddit-client)
* You or the person who controls the Bot account must have account credentials (username/password). Logging in to reddit is part of the setup process.
* If the bot does not exist **create a reddit account for it.**
* If the bot does exist make sure you are in communication with the owner of the account.
@@ -45,7 +38,7 @@ This method will use CM's built in oauth flow. It is recommended because:
If this is your **first time adding a bot** you must make sure you have
* done the [prerequisites](#prerequisites)
* created a [minimum operator configuration](configuration.md#minimum-config)
* created a [minimum operator configuration](/docs/operator/configuration.md#minimum-config)
* that specifies the client id/secret from provisioning your reddit client
* specified **Operator Name** in the configuration
@@ -63,14 +56,14 @@ Follow the directions in the helper to create a **Bot Invite Link.**
Visit the **Bot Invite Link** while **logged in to reddit as the bot account** to begin the onboarding process. Refer to the [Onboarding Your Bot]() subreddit documentation for more information on this process.
At the end of the onboarding process the bot should be automatically added to your operator configuration. If there is an issue with automatically adding it then the oauth credentials will be displayed at the end of onboarding and can be [manually added to the configuration.](configuration.md#manually-adding-a-bot)
At the end of the onboarding process the bot should be automatically added to your operator configuration. If there is an issue with automatically adding it then the oauth credentials will be displayed at the end of onboarding and can be [manually added to the configuration.](/docs/operator/configuration.md#manually-adding-a-bot)
## Aardvark OAuth Helper
This method should only be used if you cannot use the [CM OAuth Helper method.](#cm-oauth-helper-recommended)
* Visit [https://not-an-aardvark.github.io/reddit-oauth-helper/](https://not-an-aardvark.github.io/reddit-oauth-helper/) and follow the instructions given.
* **Note:** You will need to update the **redirect uri** you set when [provisioning your reddit client.](README.md#provisioning-a-reddit-client)
* **Note:** You will need to update the **redirect uri** you set when [provisioning your reddit client.](/docs/operator/README.md#provisioning-a-reddit-client)
* Input your **Client ID** and **Client Secret** in the text boxes with those names.
* Choose scopes. **It is very important you check everything on this list or CM may not work correctly**
* edit
@@ -89,5 +82,5 @@ This method should only be used if you cannot use the [CM OAuth Helper method.](
* wikiread
* wikiedit (if you are using Toolbox User Notes)
* Click **Generate tokens**, you will get a popup asking you to approve access (or login) -- **the account you approve access with is the account that Bot will control.**
* After approving an **Access Token** and **Refresh Token** will be shown at the bottom of the page. Use these to [manually add a bot to your operator configuration.](configuration.md#manually-adding-a-bot)
* After approving an **Access Token** and **Refresh Token** will be shown at the bottom of the page. Use these to [manually add a bot to your operator configuration.](/docs/operator/configuration.md#manually-adding-a-bot)
* After adding the bot you will need to restart CM.

View File

@@ -1,9 +1,3 @@
---
parent: Operator
---
# Caching
# Table of Contents
* [Overview](#overview)

View File

@@ -1,10 +1,3 @@
---
parent: Operator
nav_order: 3
---
# Configuration
The **Operator** configuration refers to configuration used configure to the actual application/bot. This is different
from the **Subreddit** configuration that is defined in each Subreddit's wiki and determines the rules/actions for
activities the Bot runs on.
@@ -36,14 +29,14 @@ configuration.
* **FILE** -- Values specified in a YAML/JSON configuration file using the structure [in the schema](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FOperatorConfig.json)
* When reading the **schema** if the variable is available at a level of configuration other than **FILE** it will be
noted with the same symbol as above. The value shown is the default.
* **ARG** -- Values specified as CLI arguments to the program (see [CLI Usage](#cli-usage) below)
* **ARG** -- Values specified as CLI arguments to the program (see [ClI Usage](#cli-usage) below)
## File Configuration (Recommended)
Using a file has many benefits over using ARG or ENV:
* CM can automatically update your configuration
* CM can automatically add bots via the [CM OAuth Helper](addingBot.md#cm-oauth-helper-recommended)
* CM can automatically add bots via the [CM OAuth Helper](/docs/operator/addingBot.md#cm-oauth-helper-recommended)
* CM has a built-in configuration editor that can help you build and validate your configuration file
* File config is **required** if adding multiple bots to CM
@@ -51,8 +44,8 @@ Using a file has many benefits over using ARG or ENV:
By default CM will look for `config.yaml` or `config.json` in the `DATA_DIR` directory:
* [Local installation](installation.md#locally) -- `DATA_DIR` is the root of your installation directory (same folder as `package.json`)
* [Docker](installation.md#docker-recommended) -- `DATA_DIR` is at `/config` in the container
* [Local installation](/docs/operator/installation.md#locally) -- `DATA_DIR` is the root of your installation directory (same folder as `package.json`)
* [Docker](/docs/operator/installation.md#docker-recommended) -- `DATA_DIR` is at `/config` in the container
The `DATA_DIR` directory can be changed by passing `DATA_DIR` as an environmental variable EX `DATA_DIR=/path/to/directory`
@@ -72,7 +65,7 @@ One ContextMod instance can
However, the default configuration (using **ENV/ARG**) assumes your intention is to run one bot (one reddit account) on one CM instance without these additional features. This is to make this mode of operation easier for users with this intention.
To take advantage of this additional features you **must** use a **FILE** configuration. Learn about how this works and how to configure this scenario in the [Architecture Documentation.](serverClientArchitecture.md)
To take advantage of this additional features you **must** use a **FILE** configuration. Learn about how this works and how to configure this scenario in the [Architecture Documentation.](/docs/serverClientArchitecture.md)
## CLI Usage
@@ -86,7 +79,7 @@ node src/index.js run
Run `node src/index.js run help` to get a list of available command line options (denoted by **ARG** above):
<details markdown="block">
<details>
```
Usage: index [options] [command]
@@ -131,11 +124,11 @@ Options:
# Minimum Configuration
The minimum configuration required to run CM assumes you have no bots and want to use CM to [add your first bot.](addingBot.md#cm-oauth-helper-recommended)
The minimum configuration required to run CM assumes you have no bots and want to use CM to [add your first bot.](/docs/operator/addingBot.md#cm-oauth-helper-recommended)
You will need have this information available:
* From [provision a reddit client](README.md#provisioning-a-reddit-client)
* From [provision a reddit client](/docs/operator/README.md#provisioning-a-reddit-client)
* Client ID
* Client Secret
* Redirect URI (if different from default `http://localhost:8085/callback`)
@@ -160,7 +153,7 @@ Configured using the `bots` top-level property. Bot configuration can override a
## Adding A Bot
If you use the [CM OAuth Helper](addingBot.md#cm-oauth-helper-recommended) and it works successfully then the configuration for the Bot will be automatically added.
If you use the [CM OAuth Helper](/docs/operator/addingBot.md#cm-oauth-helper-recommended) and it works successfully then the configuration for the Bot will be automatically added.
### Manually Adding a Bot
@@ -173,7 +166,7 @@ Minimum information required for a valid bot:
* Refresh Token
* Access Token
<details markdown="block">
<details>
<summary>Example</summary>
```yaml
@@ -218,7 +211,7 @@ Below are examples of the minimum required config to run the application using a
Using **FILE**
<details markdown="block">
<details>
See [Specify File Location](#specify-file-location) for where this file would be located.
@@ -255,7 +248,7 @@ JSON (`config.json5`)
Using **ENV** (`.env`)
<details markdown="block">
<details>
```
OPERATOR=YourRedditUsername
@@ -268,7 +261,7 @@ REDIRECT_URI=http://localhost:8085/callback
Using **ARG**
<details markdown="block">
<details>
```
node src/index.js run --clientId=f4b4df1c7b2 --clientSecret=34v5q1c56ub --redirectUri=http://localhost:8085/callback
@@ -282,7 +275,7 @@ An example of using multiple configuration levels together IE all are provided t
**FILE**
<details markdown="block">
<details>
```json
{
@@ -303,7 +296,7 @@ logging:
**ENV** (`.env`)
<details markdown="block">
<details>
```
CLIENT_SECRET=34v5q1c56ub
@@ -315,7 +308,7 @@ PORT=9008
**ARG**
<details markdown="block">
<details>
```
node src/index.js run --subreddits=sub1 --clientId=34v5q1c56ub
@@ -335,9 +328,9 @@ log level: debug
## Configuring Client for Many Instances
See the [Architecture Docs](erverClientArchitecture.md) for more information.
See the [Architecture Docs](/docs/serverClientArchitecture.md) for more information.
<details markdown="block">
<details>
YAML
@@ -408,8 +401,8 @@ JSON
# Cache Configuration
See the [Cache Configuration](caching.md) documentation.
See the [Cache Configuration](/docs/operator/caching.md) documentation.
# Database Configuration
See the [Database Configuration](database.md) documentation.
See the [Database Configuration](/docs/operator/database.md) documentation.

View File

@@ -1,9 +1,3 @@
---
parent: Operator
---
# Database
# Overview
CM uses a database to store three types of data:
@@ -37,16 +31,16 @@ databaseConfig:
## SQLite
When using a [local installation](installation.md#locally) the default database is `sqljs`, which requires no binary dependencies. When using [docker](installation.md#docker-recommended) the default is `better-sqlite3`.
When using a [local installation](/docs/installation.md#locally) the default database is `sqljs`, which requires no binary dependencies. When using [docker](/docs/operator/installation.md#docker-recommended) the default is `better-sqlite3`.
**NOTE:** It is **NOT RECOMMENDED** to use `sqljs` in a production environment for performance reasons. You should at least switch to `better-sqlite3` or preferably MySql/Postgres.
* [`sqljs` connection options](https://typeorm.io/data-source-options#sqljs-data-source-options)
* [`better-sqlite3` connection options](https://typeorm.io/data-source-options#better-sqlite3-data-source-options)
For both sqlite types, if no database/location is specified, it will be created in the [`DATA_DIR` directory.](configuration.md#specify-file-location)
For both sqlite types, if no database/location is specified, it will be created in the [`DATA_DIR` directory.](/docs/operator/configuration.md#specify-file-location)
If CM detects it cannot **read and write** to the database files, or directory if no files exist, it will fallback to using an in-memory database that will be lost when CM restarts. If you have trouble with r/w permissions and are using docker make sure [file permissions are correct for your mounted volume.](installation.md#linux-host)
If CM detects it cannot **read and write** to the database files, or directory if no files exist, it will fallback to using an in-memory database that will be lost when CM restarts. If you have trouble with r/w permissions and are using docker make sure [file permissions are correct for your mounted volume.](/docs/operator/installation.md#linux-host)
## MySQL/MariaDB
@@ -101,7 +95,7 @@ The Retention Policy can be specified at operator level, bot, subreddit *overrid
operator:
name: u/MyRedditAccount
databaseConfig:
retention: '3 months' # each subreddit will retain 3 months of recorded events
retention: '3 months' # each subreddit will retain 3 more of recorded events
bots:
# all subreddits this bot moderates will have 3 month retention
- name: u/OneBotAccount
@@ -178,7 +172,7 @@ influxConfig:
A pre-built dashboard for [Grafana](https://grafana.com) can be imported to display overall metrics/stats using InfluxDB data.
![Grafana Dashboard](../images/grafana.jpg)
![Grafana Dashboard](/docs/images/grafana.jpg)
* Create a new Data Source using **InfluxDB** type
* Choose **Flux** for the **Query Language**
@@ -187,7 +181,7 @@ A pre-built dashboard for [Grafana](https://grafana.com) can be imported to disp
* Click **Save and test**
* Import Dashboard
* **Browse** the Dashboard pane
* Click **Import** and **upload** the [grafana dashboard json file](grafana.json)
* Click **Import** and **upload** the [grafana dashboard json file](/docs/operator/grafana.json)
* Chose the data source you created from the **InfluxDB CM** dropdown
* Click **Import**

View File

@@ -1,11 +1,4 @@
---
parent: Operator
nav_order: 1
---
# Getting Started
This getting started guide is for **Operators** -- that is, someone who wants to run the actual software for a ContentMod bot. If you are a **Moderator** check out the [moderator getting started](/docs/moderators/gettingStarted.md) guide instead.
This getting started guide is for **Operators** -- that is, someone who wants to run the actual software for a ContentMod bot. If you are a **Moderator** check out the [moderator getting started](/docs/subreddit/gettingStarted.md) guide instead.
# Table of Contents
@@ -18,11 +11,11 @@ This getting started guide is for **Operators** -- that is, someone who wants to
# Installation
Follow the [installation](installation.md) documentation. It is recommended to use **Docker** since it is self-contained.
Follow the [installation](/docs/operator/installation.md) documentation. It is recommended to use **Docker** since it is self-contained.
# Create a Reddit Client
[Create a reddit client](README.md#provisioning-a-reddit-client)
[Create a reddit client](/docs/operator/README.md#provisioning-a-reddit-client)
# Start ContextMod
@@ -34,11 +27,11 @@ The First Time Setup page will ask you to input:
* Client Secret (from [Create a Reddit Client](#create-a-reddit-client))
* Operator -- this is the username of your main Reddit account.
**Write Config** and then restart CM. You have now created the [minimum configuration](configuration.md#minimum-configuration) required to run CM.
**Write Config** and then restart CM. You have now created the [minimum configuration](/docs/operator/configuration.md#minimum-configuration) required to run CM.
# Add A Bot to CM
You should automatically be directed to the [Bot Invite Helper](addingBot.md#cm-oauth-helper-recommended) used to authorize and add a Bot to your CM instance.
You should automatically be directed to the [Bot Invite Helper](/docs/operator/addingBot.md#cm-oauth-helper-recommended) used to authorize and add a Bot to your CM instance.
Follow the directions here and **create an Authorization Invite** at the bottom of the page.
@@ -54,8 +47,8 @@ To monitor the behavior of bots running on your instance visit http://localhost:
# What's Next?
As an operator you should familiarize yourself with how the [operator configuration](configuration.md) you made works. This will help you understand how to get the most of your CM instance by leveraging the [Cache](caching.md) and [Database](database.md) effectively as well as provide you will all possible options for configuring CM using the [schema.](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FOperatorConfig.json)
As an operator you should familiarize yourself with how the [operator configuration](/docs/operator/configuration.md) you made works. This will help you understand how to get the most of your CM instance by leveraging the [Cache](/docs/oeprator/caching.md) and [Database](/docs/operator/database.md) effectively as well as provide you will all possible options for configuring CM using the [schema.](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FOperatorConfig.json)
If you are also the moderator of the subreddit the bot will be running you should check out the [moderator getting started guide.](../moderators/gettingStarted.md#setup-wiki-page)
If you are also the moderator of the subreddit the bot will be running you should check out the [moderator getting started guide.](/docs/subreddit/gettingStarted.md#setup-wiki-page)
You might also be interested in these [quick tips for using the web interface](../webInterface.md). Additionally, on the dashboard click the **Help** button at the top of the page to get a guided tour of the dashboard.
You might also be interested in these [quick tips for using the web interface](/docs/webInterface.md). Additionally, on the dashboard click the **Help** button at the top of the page to get a guided tour of the dashboard.

View File

@@ -1,8 +1,3 @@
---
parent: Operator
nav_order: 2
---
# Installation
In order to run a ContextMod instance you must first you must install it somewhere.
@@ -13,19 +8,16 @@ ContextMod can be run on almost any operating system but it is recommended to us
PROTIP: Using a container management tool like [Portainer.io CE](https://www.portainer.io/products/community-edition) will help with setup/configuration tremendously.
Images available from these registeries:
### [Dockerhub](https://hub.docker.com/r/foxxmd/context-mod)
* [Dockerhub](https://hub.docker.com/r/foxxmd/context-mod) - `docker.io/foxxmd/context-mod`
* [GHCR](https://github.com/foxxmd/context-mod/pkgs/container/context-mod) - `ghcr.io/foxxmd/context-mod`
An example of starting the container using the [minimum configuration](configuration.md#minimum-config):
An example of starting the container using the [minimum configuration](/docs/operator/configuration.md#minimum-config):
* Bind the directory where your config file, logs, and database are located on your host machine into the container's default `DATA_DIR` by using `-v /host/path/folder:/config`
* Note: **You must do this** or else your configuration will be lost next time your container is updated.
* Expose the web interface using the container port `8085`
```
docker run -d -v /host/path/folder:/config -p 8085:8085 ghcr.io/foxxmd/context-mod:latest
docker run -d -v /host/path/folder:/config -p 8085:8085 foxxmd/context-mod
```
The location of `DATA_DIR` in the container can be changed by passing it as an environmental variable EX `-e "DATA_DIR=/home/abc/config`
@@ -42,35 +34,7 @@ To get the UID and GID for the current user run these commands from a terminal:
* `id -g` -- prints GID
```
docker run -d -v /host/path/folder:/config -p 8085:8085 -e PUID=1000 -e PGID=1000 ghcr.io/foxxmd/context-mod:latest
```
### Docker-Compose
The included [`docker-compose.yml`](/docker-compose.yml) provides production-ready dependencies for CM to use:
* [Redis](https://redis.io/) for caching
* [MariaDB](https://mariadb.org/) for database
* Optionally, [Influx/Grafana](database.md#influx) instances
#### Setup
The included `docker-compose.yml` file is written for **Docker Compose v2.**
For new installations copy [`config.yaml`](/docker/config/docker-compose/config.yaml) into a folder named `data` in the same folder `docker-compose.yml` will be run from. For users migrating their existing CM instances to docker-compose, copy your existing `config.yaml` into the same `data` folder.
Read through the comments in both `docker-compose.yml` and `config.yaml` and makes changes to any relevant settings (passwords, usernames, etc...). Ensure that any settings used in both files (EX mariaDB passwords) match.
To build and start CM:
```bash
docker compose up -d
```
To include Grafana/Influx dependencies run:
```bash
docker compose --profile full up -d
docker run -d -v /host/path/folder:/config -p 8085:8085 -e PUID=1000 -e PGID=1000 foxxmd/context-mod
```
## Locally
@@ -90,12 +54,71 @@ npm install
tsc -p .
```
An example of running CM using the [minimum configuration](configuration.md#minimum-config) with a [configuration file](configuration.md#file-configuration-recommended):
An example of running CM using the [minimum configuration](/docs/operator/configuration.md#minimum-config) with a [configuration file](/docs/operator/configuration.md#file-configuration-recommended):
```bash
node src/index.js run
```
### Dependencies
Note: All below dependencies are automatically included in the [Docker](#docker-recommended) image.
#### Sharp
For basic [Image Comparisons](/docs/imageComparison.md) and image data CM uses [sharp](https://sharp.pixelplumbing.com/) which depends on [libvips](https://www.libvips.org/)
Binaries for Sharp and libvips ship with the `sharp` npm package for all major operating systems and should require no additional steps to use -- installing CM with the above script should be sufficient.
See more about Sharp dependencies in the [image comparison prerequisites.](/docs/imageComparison.md#prerequisites)
#### OpenCV
For advanced image comparison CM uses [OpenCV.](https://opencv.org/) OpenCV is an **optional** dependency that is only utilized if CM is configured to run these advanced image operations so if you are NOT doing any image-related operations you can safely ignore this section/dependency.
**NOTE:** Depending on the image being compared (resolution) and operations being performed this can be a **CPU heavy resource.** TODO: Add rules that are cpu heavy...
##### Installation
Installation is not an automatic process. The below instructions are a summary of "easy" paths for installation but are not exhaustive. DO reference the detailed instructions (including additional details for windows installs) at [opencv4nodejs How to Install](https://github.com/UrielCh/opencv4nodejs#how-to-install).
###### Build From Source
This may take **some time** since openCV will be built from scratch.
On windows you must first install build tools: `npm install --global windows-build-tools`
Otherwise, run one of the following commands from the CM project directory:
* For CUDA (Nvidia GPU acceleration): `npm run cv-autoinstall-cuda`
* Normal: `npm run cv-autoinstall`
###### Build from Prebuilt
In this use-case you already have openCV built OR are using a distro prebuilt package. This method is much faster than building from source as only bindings need to be built.
[More information on prebuild installation](https://github.com/UrielCh/opencv4nodejs#installing-opencv-manually)
Prerequisites:
* Windows `choco install OpenCV -y -version 4.1.0`
* MacOS `brew install opencv@4; brew link --force opencv@4`
* Linux -- varies, check your package manager for `opencv` and `opencv-dev`
A script for building on **Ubuntu** is already included in CM:
* `sudo apt install opencv-dev`
* `npm run cv-install-ubuntu-prebuild`
Otherwise, you will need to modify `scripts` in CM's `package.json`, use the script `cv-install-ubuntu-prebuild` as an example. Your command must include:
* `--incDir [path/to/opencv/dev-files]` (on linux, usually `/usr/include/opencv4/`)
* `--libDir [path/to/opencv/shared-files]` (on linux usually `/lib/x86_64-linux-gnu/` or `/usr/lib/`)
* `--binDir=[path/to/openv/binaries]` (on linux usually `/usr/bin/`)
After you have modified/added a script for your operating system run it with `npm run yourScriptName`
## [Heroku Quick Deploy](https://heroku.com/about)
**NOTE:** This is still experimental and requires more testing.

View File

@@ -1,9 +1,3 @@
---
parent: Operator
---
# Architecture
# Overview
ContextMod's high-level functionality is separated into two **independently run** applications.

View File

@@ -1,206 +0,0 @@
---
parent: Subreddit Configuration
---
# Action Templating
Actions that can submit text (Report, Comment, UserNote, Message, Ban, Submission) will have their `content` values run through a [Mustache Template](https://mustache.github.io/). This means you can insert data generated by Rules into your text before the Action is performed.
See here for a [cheatsheet](https://gist.github.com/FoxxMD/d365707cf99fdb526a504b8b833a5b78) and [here](https://www.tsmean.com/articles/mustache/the-ultimate-mustache-tutorial/) for a more thorough tutorial.
# Template Data
Some data can always be accessed at the top-level. Example
```
This action was run from {{manager}} in Check {{check}}.
The bot intro post is {{botLink}}
Message the moderators of this subreddit using this [compose link]({{modmailLink}})
```
| Name | Description | Example |
|---------------|---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `manager` | The name of the subreddit the bot is running in | mealtimevideos |
| `check` | The name of the Check that was triggered | myCheck |
| `botLink` | A link to the bot introduction | https://www.reddit.com/r/ContextModBot/comments/otz396/introduction_to_contextmodbot |
| `modmailLink` | A link that opens reddit's DM compose with the subject line as the Activity being processed | https://www.reddit.com/message/compose?to=/r/mealtimevideos&message=https://www.reddit.com/r/ContextModBot/comments/otz396/introduction_to_contextmodbot |
## Activity Data
**Activity data can be accessed using the `item` variable.** Example
```
This activity is a {{item.kind}} with {{item.votes}} votes, created {{item.age}} ago.
```
Produces:
> This activity is a submission with 10 votes created 5 minutes ago.
### Common
All Actions with `content` have access to this data:
| Name | Description | Example |
|--------------|-----------------------------------------------------------------------------------------------------|----------------------------------------------------------|
| `kind` | The Activity type (submission or comment) | submission |
| `author` | Name of the Author of the Activity being processed | FoxxMD |
| `permalink` | URL to the Activity | https://reddit.com/r/mySuibreddit/comments/ab23f/my_post |
| `votes` | Number of upvotes | 69 |
| `age` | The age of the Activity in a [human friendly format](https://day.js.org/docs/en/durations/humanize) | 5 minutes |
| `subreddit` | The name of the subreddit the Activity is from | mealtimevideos |
| `id` | The `Reddit Thing` ID for the Activity | t3_0tin1 |
| `title` | As comments => the body of the comment. As Submission => title | Test post please ignore |
| `shortTitle` | The same as `title` but truncated to 15 characters | test post pleas... |
#### Common Author
Additionally, `author` has these properties accessible:
| Name | Description | Example |
|----------------|-----------------------------------------------------------------------------------|------------|
| `age` | (Approximate) Age of account | 3 months |
| `linkKarma` | Amount of link karma | 10 |
| `commentKarma` | Amount of comment karma | 3 |
| `totalKarma` | Combined link+comment karma | 13 |
| `verified` | Does account have a verified email? | true |
| `flairText` | The text of the Flair assigned to the Author in this subreddit, if one is present | Test Flair |
NOTE: Accessing these properties may require an additional API call so use sparingly on high-volume comments
##### Example Usage
```
The user {{item.author}} has been a redditor for {{item.author.age}}
```
Produces:
> The user FoxxMD has been a redditor for 3 months
### Submissions
If the **Activity** is a Submission these additional properties are accessible:
| Name | Description | Example |
|-------------------|-----------------------------------------------------------------|-------------------------|
| `upvoteRatio` | The upvote ratio | 100% |
| `nsfw` | If the submission is marked as NSFW | true |
| `spoiler` | If the submission is marked as a spoiler | true |
| `url` | If the submission was a link then this is the URL for that link | http://example.com |
| `title` | The title of the submission | Test post please ignore |
| `link_flair_text` | The flair text assigned to this submission | Test Flair |
### Comments
If the **Activity** is a Comment these additional properties are accessible:
| Name | Description | Example |
|------|--------------------------------------------------------------|---------|
| `op` | If the Author is the OP of the Submission this comment is in | true |
### Moderator
If the **Activity** occurred in a Subreddit the Bot moderates these properties are accessible:
| Name | Description | Example |
|---------------|-------------------------------------|---------|
| `reports` | The number of reports recieved | 1 |
| `modReports` | The number of reports by moderators | 1 |
| `userReports` | The number of reports by users | 1 |
## Rule Data
### Summary
A summary of what rules were processed and which were triggered, with results, is available using the `ruleSummary` variable. Example:
```
A summary of rules processed for this activity:
{{ruleSummary}}
```
Would produce:
> A summary of rules processed for this activity:
>
> * namedRegexRule - ✘
> * nameAttributionRule - ✓ - 1 Attribution(s) met the threshold of < 20%, with 1 (3%) of 32 Total -- window: 6 months
> * noXPost ✓ - ✓ 1 of 1 unique items repeated <= 3 times, largest repeat: 1
### Individual
Individual **Rules** can be accessed using the name of the rule, **lower-cased, with all spaces/dashes/underscores.** Example:
```
Submission was repeated {{rules.noxpost.largestRepeat}} times
```
Produces
> Submission was repeated 7 times
## Action Data
### Summary
A summary of what actions have already been run **when the template is rendered** is available using the `actionSummary` variable. It is therefore important that the Action you want to produce the summary is run **after** any other Actions you want to get a summary for.
Example:
```
A summary of actions processed for this activity, so far:
{{actionSummary}}
```
Would produce:
> A summary of actions processed for this activity, so far:
>
> * approve - ✘ - Item is already approved??
> * lock - ✓
> * modnote - ✓ - (SOLID_CONTRIBUTOR) User is good
### Individual
Individual **Actions** can be accessed using the name of the action, **lower-cased, with all spaces/dashes/underscores.** Example:
```
User was banned for {{actions.exampleban.duration}} for {{actions.exampleban.reason}}
```
Produces
> User was banned for 4 days for toxic behavior
# Quick Templating Tutorial
As a quick example for how you will most likely be using templating -- wrapping a variable in curly brackets, `{{variable}}`, will cause the variable value to be rendered instead of the brackets:
```
myVariable = 50;
myOtherVariable = "a text fragment"
template = "This is my template, the variable is {{myVariable}}, my other variable is {{myOtherVariable}}, and that's it!";
console.log(Mustache.render(template, {myVariable});
// will render...
"This is my template, the variable is 50, my other variable is a text fragment, and that's it!";
```
**Note: When accessing an object or its properties you must use dot notation**
```
const item = {
aProperty: 'something',
anotherObject: {
bProperty: 'something else'
}
}
const content = "My content will render the property {{item.aProperty}} like this, and another nested property {{item.anotherObject.bProperty}} like this."
```

View File

@@ -1,205 +0,0 @@
---
parent: Subreddit Configuration
---
# Cookbook
Here you will find useful configs for CM that provide real-world functionality. This is where you should look first for **"how do i..."** questions.
## How To Use
Each recipe includes what type of config piece it is (Rule, Check, Action, Run, etc...). Keep this in mind before copy-pasting to make sure it goes in the right place in your config.
### Copy-Pasting
If the type is **Check** or **Run** the recipe contents will have instructions in the comments on how to use it as a **full subreddit config** OR **by itself (default).** If not Check/Run then when copy-pasting you will need to ensure it is placed in the correct spot in your config.
### As Config Fragment
**Checks, Runs, Actions, and Rule** recipes can be referenced in your config without copy-pasting by using them as [Config Fragments.](../README.md#partial-configurations) These need to be placed in the correct spot in your config, just like copy-pasting, but only require the URL of the recipe instead of all the code.
To use a recipe as a fragment **copy** the URL of the config and insert into your config like this:
```yaml
- 'url:https://URL_TO_CONFIG'
```
EXAMPLE: Using the **Config** link from the [Free Karma](#remove-submissions-from-users-who-have-used-freekarma-subs-to-bypass-karma-checks) check below -- copy the **Config** link and insert it into a full subreddit config like this:
<details markdown="block">
<summary>Config</summary>
```yaml
polling:
- newSub
runs:
- name: MyFirstRun
checks:
# freekarma check
- 'url:https://github.com/FoxxMD/context-mod/blob/master/docs/subreddit/components/cookbook/freekarma.yaml'
- name: MyRegularCheck
kind: submission
# ...
```
</details>
# Recipes
## Spam Prevention
### Remove submissions from users who have used 'freekarma' subs to bypass karma checks
* Type: **Check**
* [Config](freekarma.yaml)
If the user has any activity (comment/submission) in known freekarma subreddits in the past (100 activities) then remove the submission.
### Remove submissions that are consecutively spammed by the author
* Type: **Check**
* [Config](crosspostSpam.yaml)
If the user has crossposted the same submission in the past (100 activities) 4 or more times in a row then remove the submission.
### Remove submissions if users is flooding new
* Type: **Check**
* [Config](floodingNewSubmissions.yaml)
If the user has made more than 4 submissions in your subreddit in the last 24 hours than new submissions are removed and user is tagged with a modnote.
### Remove submissions posted in diametrically-opposed subreddit
* Type: **Check**
* [Config](diametricSpam.yaml)
If the user makes the same submission to another subreddit(s) that are "thematically" opposed to your subreddit it is probably spam. This check removes it. Detects all types of submissions (including images).
### Remove comments that are consecutively spammed by the author
* Type: **Check**
* [Config](commentSpam.yaml)
If the user made the same comment (with some fuzzy matching) 4 or more times in a row in the past (100 activities or 6 months) then remove the comment.
### Remove comment if it is a chat invite link spam
* Type: **Check**
* [Config](chatSpam.yaml)
This rule goes a step further than automod can by being more discretionary about how it handles this type of spam.
* Remove the comment if:
* Comment being checked contains **only** a chat link (no other text) OR
* Chat links appear **anywhere** in three or more of the last 100 comments the Author has made
This way ContextMod can more easily distinguish between these use cases for a user commenting with a chat link:
* actual spammers who only spam a chat link
* users who may comment with a link but have context for it either in the current comment or in their history
* users who many comment with a link but it's a one-off event (no other links historically)
## Repost Detection
### Remove comments reposted from youtube video submissions
* Type: **Check**
* [Config](youtubeCommentRepost.yaml)
**Requires bot has an API Key for Youtube.**
Removes comment on reddit if the same comment is found on the youtube video the submission is for.
### Remove comments reposted from reddit submissions
* Type: **Check**
* [Config](commentRepost.yaml)
Checks top-level comments on submissions younger than 30 minutes:
* Finds other reddit submissions based on crosspost/duplicates/title/URL, takes top 10 submissions based # of upvotes
* If this comment matches any top comments from those other submissions with at least 85% sameness then it is considered a repost and removed
### Remove reposted reddit submission
* Type: **Check**
* [Config](submissionRepost.yaml)
Checks reddit for top posts with a **Title** that is 90% or more similar to the submission being checked and removes it, if found.
## Self Promotion
### Remove link submissions where the user's history is comprised of 10% or more of the same link
* Type: **Check**
* [Config](selfPromo.yaml)
If the link origin (youtube author, twitter author, etc. or regular domain for non-media links)
* comprises 10% or more of the users **entire** history in the past (100 activities or 6 months)
* or comprises 10% or more of the users **submission** history in the past (100 activities or 6 months) and the user has low engagement (<50% of history is comments or 40%> of comment are as OP)
then remove the submission
### Remove submissions posted in 'newtube' subreddits
* Type: **Check**
* [Config](newtube.yaml)
If the user makes the same submission to a 'newtube' or self-promotional subreddit it is removed and a modnote is added.
## Safety
### Remove comments on brigaded submissions when user has no history
* Type: **Check**
* [Config](brigadingNoHistory.yaml)
The users of comments on a brigaded submission (based on a special submission flair) have their comment history checked -- if they have no participation in your subreddit then the comment is removed.
### Remove submissions from users with a history of sex solicitation
* Type: **Check**
* [Config](sexSolicitationHistory.yaml)
If the author of a submission has submissions in their history that match common reddit "sex solicitation" tags (MFA, R4F, M4F, etc...) the submission is removed and a modnote added.
This is particularly useful for subreddits with underage audiences or mentally/emotionally vulnerable groups.
The check can be modified to removed comments by changing `kind: submission` to `kind: comment`
## Verification
### Verify users from r/TranscribersOfReddit
* Type: **Check**
* [Config](transcribersOfReddit.yaml)
[r/TranscribersOfReddit](https://www.reddit.com/r/transcribersofreddit) is a community of volunteers transcribing images and videos, across reddit, into plain text.
This Check detects their standard transcription template and also checks they have a history in r/transcribersofreddit -- then approves the comment and flairs the user with **Transcriber ✍️**
### Require submission authors have prior subreddit participation
* Type: **Check**
* [Config](requireNonOPParticipation.yaml)
Submission is removed if the author has **less than 5 non-OP comments** in your subreddit prior to making the submission.
### Require submission authors make a top-level comment with 15 minutes of posting
* Type: **Check**
* [Config](requireNonOPParticipation.yaml)
After making a submission the author must make a top-level comment with a regex-checkable pattern within X minutes. If the comment is not made the submission is removed.
# Monitoring
### Sticky a comment on popular submissions
* Type: **Run**
* [Config](popularSubmissionMonitoring.yaml)
This **Run** should come after any other Runs you have that may remove a Submission.
The Run will cause CM to check new submissions for 3 hours at a 10 minute interval. The bot will then make a comment and sticky it WHEN it detects the number of upvotes is abnormal for how long the Submission has been "alive".

View File

@@ -1,44 +0,0 @@
#polling:
# - newComm
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Report comments from users with no history in the subreddit IF the submission is flaired as being brigaded
# optionally, remove comment
#
- name: Brigading No History
kind: comment
# only runs on comments in a submission with a link flair css class of 'brigaded'
itemIs:
- submissionState:
# can use any or all of these to detect brigaded submission
- link_flair_css: brigaded
#flairTemplate: 123-1234
#link_flair_text: Restricted
rules:
- name: noHistory
kind: recentActivity
# check last 100 activities that have not been removed
window:
count: 100
filterOn:
post:
commentState:
include:
- removed: false
thresholds:
# triggers if user has only one activity (this one) in your subreddit
- subreddits:
- MYSUBREDDIT
threshold: '<= 1'
actions:
- kind: report
enable: true
content: User has no history in subreddit
- kind: remove
enable: false
note: User has no history in subreddit

View File

@@ -1,71 +0,0 @@
#polling:
# - newSub
# - newComm
#runs:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a series of RUNS
- name: approvals
checks:
- name: approveSubmissionOnComment
description: Approve an unapproved submission when OP comments with the magic words
kind: comment
itemIs:
# only check comment if submission is not approved and this comment is by OP
- submissionState:
- approved: false
op: true
rules:
- name: OPMagic
kind: regex
criteria:
# YOU NEED TO EDIT THIS REGEX TO MATCH THE PATTERN THE OP'S COMMENT SHOULD HAVE IN ORDER TO VERIFY THE SUBMISSION
- regex: '/Say Please/i'
actions:
- kind: approve
targets:
- parent
- self
# cancel any delayed dispatched actions
- kind: cancelDispatch
# tell action to look for delayed items matched parent (submission)
target: parent
# submission must have 'subVerification' identifier
identifier: subVerification
- name: verification
checks:
- name: waitForVerification
description: Delay processing this submission for 15 minutes
kind: submission
itemIs:
# only dispatch if this is the first time we are seeing this submission
- source:
- "poll:newSub"
- user
actions:
- kind: dispatch
target: self
# unique identifier which is a nice hint in the UI and also allows targeting this item while it is delayed
identifier: subVerification
delay: "15 minutes"
# when it is reprocessed go directly to the 'verification' run, skipping everything else
goto: verification
- name: removeNoVerification
description: Remove submission if it is not verified after delay
kind: submission
itemIs:
# only process this submission if it comes dispatch with 'subVerification' identifier and is NOT approved after 15 minutes
- source: "dispatch:subVerification"
approved: false
actions:
# if this submission is being processed it has been 5 minutes and was not cancelled by OF comment
- kind: remove
enable: true
- kind: comment
enable: true
lock: true
distinguish: true
content: 'Your submission has been removed because you did not follow verification instructions within 15 minutes of posting.'

View File

@@ -1,54 +0,0 @@
#polling:
# - newComm
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Checks top-level comments on submissions younger than 30 minutes:
# * Finds other reddit submissions based on crosspost/duplicates/title/URL, takes top 10 submissions based # of upvotes
# * If this comment matches any comments from those other submissions with at least 85% sameness then it is considered repost
#
# optionally, bans user if they have more than one modnote for comment reposts
#
- name: commRepost
description: Check if comment has been reposted from youtube
kind: comment
itemIs:
- removed: false
approved: false
op: false
# top level comments only
depth: '< 1'
submissionState:
- age: '< 30 minutes'
condition: AND
rules:
- name: commRepost
kind: repost
criteria:
- searchOn:
- external
actions:
- kind: remove
spam: true
note: 'reposted comment from reddit with {{rules.commrepost.closestSameness}}% sameness'
- kind: ban
authorIs:
# if the author has more than one spamwatch usernote then just ban em
include:
- modActions:
- noteType: SPAM_WATCH
note: "/comment repost.*/i"
search: total
count: "> 1"
message: You have been banned for repeated spammy behavior including reposting reddit comments
note: reddit comment repost + spammy behavior
reason: reddit comment repost + spammy behavior
- name: commRepostModNote
kind: modnote
content: 'YT comment repost with {{rules.commrepost.closestSameness}}% sameness'
type: SPAM_WATCH

View File

@@ -1,34 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
- name: diametricSpam
description: Check if author has posted the same image in opposite subs
kind: submission
rules:
- name: recent
kind: recentActivity
useSubmissionAsReference: true
# requires your subreddit to be running on a CM instance that supports image processing
imageDetection:
enable: true
threshold: 5
lookAt: submissions
window: 30
thresholds:
- threshold: ">= 1"
subreddits:
- AnotherSubreddit
actions:
- kind: remove
enable: true
content: "Posted same image in {{rules.recent.subSummary}}"
- kind: comment
distinguish: true
sticky: true
lock: true
content: 'You have posted the same image in another subreddit ({{rules.recent.subSummary}}) that does not make sense given the theme of this subreddit. We consider this spam and it has been removed.'

View File

@@ -1,34 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Add a mote note to users who are making more than 4 submissions a day
# and optionally remove new submissions by them
#
- name: Flooding New
description: Detect users make more than 4 submission in 24 hours
kind: submission
rules:
- name: Recent In Sub
kind: recentActivity
useSubmissionAsReference: false
window:
duration: 24 hours
fetch: submissions
thresholds:
- subreddits:
# change this to your subreddit
- MYSUBREDDIT
threshold: "> 4"
actions:
- kind: modnote
type: SPAM_WATCH
content: '{{rules.recentinsub.totalCount}} submissions in the last 24 hours'
- kind: remove
enable: false
note: '{{rules.recentinsub.totalCount}} submissions in the last 24 hours'

View File

@@ -1,45 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Remove submissions from users who have recent activity in freekarma subs in the last 100 activities
#
- name: freekarma removal
description: Remove submission if user has used freekarma sub recently
kind: submission
rules:
- name: freekarma
kind: recentActivity
window: 100
useSubmissionAsReference: false
thresholds:
- subreddits:
- FreeKarma4U
- FreeKarma4You
- freekarmaforyou
- KarmaFarming4Pros
- KarmaStore
- upvote
- promote
- shamelessplug
- upvote
- FreeUpVotes
- GiveMeKarma
- nsfwkarma
- GetFreeKarmaAnyTime
- freekarma2021
- FreeKarma2022
- KarmaRocket
- FREEKARMA4PORN
actions:
- kind: report
enable: false
content: 'Remove => {{rules.freekarma.totalCount}} activities in freekarma subs'
- kind: remove
enable: true
note: '{{rules.freekarma.totalCount}} activities in freekarma subs'

View File

@@ -1,55 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Add a mote note to users who make a submission that is also posted to a 'newtube' subreddit
# and optionally remove new submission
#
- name: Newtube Submission
description: Tag user if submission was posted in 'newtube' subreddit
kind: submission
rules:
- name: newTube
kind: recentActivity
window:
count: 100
fetch: submissions
thresholds:
- subreddits:
- AdvertiseYourVideos
- BrandNewTube
- FreeKarma4U
- FreeKarma4You
- KarmaStore
- GetMoreSubsYT
- GetMoreViewsYT
- NewTubers
- promote
- PromoteGamingVideos
- shamelessplug
- SelfPromotionYouTube
- SmallYTChannel
- SmallYoutubers
- upvote
- youtubestartups
- YouTube_startups
- YoutubeSelfPromotions
- YoutubeSelfPromotion
- YouTubeSubscribeBoost
- youtubepromotion
- YTPromo
- Youtubeviews
- YouTube_startups
actions:
- name: newtubeModTag
kind: modnote
type: SPAM_WATCH
content: 'New Tube => {{rules.newtube.subSummary}}{{rules.newtubeall.subSummary}}'
- kind: remove
enable: false
note: 'New Tube => {{rules.newtube.subSummary}}{{rules.newtubeall.subSummary}}'

View File

@@ -1,89 +0,0 @@
polling:
- newSub
runs:
- name: MyRegularRun
itemIs:
# regular run/checks should only run on new activities or if from dashboard
- source:
- 'poll:newSub'
- 'poll:newComm'
- 'user'
checks:
- name: RuleBreakingCheck1
kind: submission
# ...
#
# your regular checks go here
#
# assuming if a Submission makes it through all of your Checks then it is "OK"
# to be Approved or generally will be visible in the subreddit (valid for monitoring for r/All)
# -- at the end of the Run add a Dispath action
- name: Dispatch For Popular Monitoring
kind: submission
actions:
- kind: dispatch
identifier: 'popular'
# CM will wait 5 minutes before processing this submission again
delay: '5 minutes'
target: 'self'
# a separate run that only processes Submissions from dispatch:popular
- name: PopularWatch
itemIs:
- source: 'dispatch:popular'
checks:
# each check here looks at submission age and tests upvotes against what you think is probably r/All number of votes
# in descending age (oldest first)
# NOTE: You should change the 'age' and 'score' tests to fit the traffic volume for your subreddit!
- name: Two Hour Check
kind: submission
itemIs:
- age: '>= 2 hours'
score: '> 100'
actions:
- kind: comment
name: popularComment
content: 'Looks like this thread is getting a lot of attention. Greetings r/All! Please keep it civil.'
sticky: true
distinguish: true
lock: true
- name: One Hour Check
kind: submission
itemIs:
- age: '>= 1 hours'
score: '> 50'
actions:
- popularComment
- name: Thirty Minute Check
kind: submission
itemIs:
- age: '>= 30 minutes'
score: '> 25'
actions:
- popularComment
- name: Ten Minute Check
kind: submission
itemIs:
- age: '>= 10 minutes'
score: '> 10'
actions:
- popularComment
# finally, if none of the popular checks passed re-dispatch submission to be checked in another 10 minutes
- name: Delay Popular Check
kind: submission
postTrigger:
# don't need to add this Actioned Events
recordTo: false
itemIs:
# only monitor until submission is 3 hours old
- age: '<= 3 hours'
actions:
- kind: dispatch
identifier: 'popular'
delay: '10 minutes'
target: 'self'

View File

@@ -1,51 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Report submissions by users with less than 5 non-OP comments in our subreddit
# and optionally remove the submission
#
- name: RequireEngagement
description: Remove submission if author has less than X non-op comments in our subreddit
kind: submission
rules:
- name: LittleEngagement
kind: recentActivity
lookAt: comments
useSubmissionAsReference: false
# bot will check the last 100 NON-OP comments from user's history
window:
count: 100
fetch: comments
filterOn:
post:
commentState:
- op: false
thresholds:
subreddits:
- MYSUBREDDIT
# rule is "triggered" if there are LESS THAN 5 comments in our subreddit in the window specified (currently 100 non-op comments)
threshold: '< 5'
actions:
- kind: report # report the submission
enable: true
# the text of the report
content: 'User has <5 non-OP comments in last 100 comments'
- kind: remove # remove the submission
enable: false
note: 'User has <5 non-OP comments in last 100 comments'
- kind: comment # reply to submission with a comment
enable: false
# contents of the comment
content: We require users to have a minimum level of engagement (>5 comments on other people's posts) in our subreddit before making submissions. Your submission has been automatically removed.
sticky: true
distinguish: true
lock: true

View File

@@ -1,33 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Remove submission if user has any "redditor for [sex]..." submissions in their history
# and optionally bans user
#
- name: sexSpamHistory
description: Detect sex spam language in recent history and ban if found (most likely a bot)
kind: submission
rules:
- kind: regex
name: redditorFor
criteria:
# matches if text has common "looking for" acronym like F4M R4A etc...
- regex: '/[RFM]4[a-zA-Z\s0-9]/i'
totalMatchThreshold: "> 1"
window: 100
testOn:
- body
- title
actions:
- kind: remove
enable: true
note: 'Has sex solicitation submission history: {{rules.redditorfor.matchSample}}'
- kind: modnote
type: ABUSE_WARNING
content: 'Has sex solicitation submission history: {{rules.redditorfor.matchSample}}'

View File

@@ -1,31 +0,0 @@
#polling:
# - newSub
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
- name: BotRepost
description: Remove submission if it is likely a repost
kind: submission
rules:
# search reddit for similar submissions to see if it is a repost
- name: subRepost
kind: repost
criteria:
- searchOn:
# match found Submissions sameness using title against title of Submission being checked
- kind: title
# sameness (confidence) % of a title required to consider Submission being checked as a repost
matchScore: 90
actions:
# report the submission
- kind: report
enable: true
content: '{{rules.subrepost.closestSameness}} confidence this is a repost.'
# remove the submission
- kind: remove
enable: false
note: '{{rules.subrepost.closestSameness}} confidence this is a repost.'

View File

@@ -1,41 +0,0 @@
#polling:
# - newComm
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# Detect top-level comments by users from r/transcribersofreddit
# and approve/flair the user
#
- name: transcriber comment
description: approve/flair transcribed video comment
kind: comment
itemIs:
# top-level comments
depth: '< 1'
condition: AND
rules:
- name: transcribedVideoFormat
kind: regex
criteria:
- regex: '/^[\n\r\s]*\*Video Transcription\*[\n\r]+---[\S\s]+---/gim'
- name: transcribersActivity
kind: recentActivity
window:
count: 100
duration: 1 week
useSubmissionAsReference: false
thresholds:
- subreddits:
- transcribersofreddit
actions:
- kind: approve
- name: flairTranscriber
kind: flair
authorIs:
exclude:
- flairText:
- Transcriber ✍️
text: Transcriber ✍️

View File

@@ -1,47 +0,0 @@
#polling:
# - newComm
#runs:
# - checks:
#### Uncomment the code above to use this as a FULL subreddit config
####
#### Otherwise copy-paste the code below to use as a CHECK
#
# If submission type is a youtube video CM will check top comments on the video and remove comment if it at least 85% the same
# optionally, bans user if they have more than one modnote for comment reposts
#
- name: commRepostYT
description: Check if comment has been reposted from youtube
kind: comment
itemIs:
- removed: false
approved: false
op: false
condition: AND
rules:
- name: commRepost
kind: repost
criteria:
- searchOn:
- external
actions:
- kind: remove
spam: true
note: 'reposted comment from youtube with {{rules.commrepostyt.closestSameness}}% sameness'
- kind: ban
authorIs:
# if the author has more than one spamwatch usernote then just ban em
include:
- modActions:
- noteType: SPAM_WATCH
note: "/comment repost.*/i"
search: total
count: "> 1"
message: You have been banned for repeated spammy behavior including reposting youtube comments
note: yt comment repost + spammy behavior
reason: yt comment repost + spammy behavior
- name: commRepostYTModNote
kind: modnote
content: 'YT comment repost with {{rules.commrepostyt.closestSameness}}% sameness'
type: SPAM_WATCH

View File

@@ -1,9 +0,0 @@
---
parent: Subreddit Configuration
has_children: true
has_toc: true
---
# In Depth
Further details and examples for CM components.

View File

@@ -1,36 +0,0 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Attribution Rule
The **Attribution** rule will aggregate an Author's content Attribution (youtube channels, twitter, website domains, etc.) and can check on their totals or percentages of all Activities over a time period:
* Total # of attributions
* As percentage of all Activity or only Submissions
* Look at all domains or only media (youtube, vimeo, etc.)
* Include self posts (by reddit domain) or not
Consult the [schema](https://json-schema.app/view/%23/%23%2Fdefinitions%2FCheckJson/%23%2Fdefinitions%2FAttributionJSONConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) for a complete reference of the rule's properties.
# [Template Variables](../../actionTemplating.md)
| Name | Description | Example |
|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
| `result` | Summary of rule results (also found in Actioned Events) | 1 Attribution(s) met the threshold of >= 20%, with 6 (40%) of 15 Total -- window: 3 years |
| `triggeredDomainCount` | Number of domains that met the threshold | 1 |
| `window` | Number or duration of Activities considered from window | 3 years |
| `largestCount` | The count from the largest aggregated domain | 6 |
| `largestPercentage` | The percentage of Activities the largest aggregated domain comprises | 40% |
| `smallestCount` | The count from the smallest aggregated domain | 1 |
| `smallestPercentage` | The percentage of Activities the smallest aggregated domain comprises | 6% |
| `countRange` | A convenience string displaying "smallestCount - largestCount" or just one number if both are the same | 5 |
| `percentRange` | A convenience string displaying "smallestPercentage - largestPercentage" or just one percentage if both are the same | 34% |
| `domainsDelim` | A comma-delimited list of all the domain URLs that met the threshold | youtube.com/example1, youtube.com/example2, rueters.com |
| `titlesDelim` | A comma-delimited list of friendly-names of the domain if one is present, otherwise the URL (IE youtube.com/c/34ldfa343 => "My Youtube Channel Title") | My Channel A, My Channel B, reuters.com |
| `threshold` | The threshold you configured for this Rule to trigger | `>= 20%` |
# Examples
* Self Promotion as percentage of all Activities [YAML](redditSelfPromoAll.yaml) | [JSON](redditSelfPromoAll.json5) - Check if Author is submitting much more than they comment.
* Self Promotion as percentage of Submissions [YAML](redditSelfPromoSubmissionsOnly.yaml) | [JSON](redditSelfPromoSubmissionsOnly.json5) - Check if any of Author's aggregated submission origins are >10% of their submissions

View File

@@ -1,457 +0,0 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
title: Filters
---
# Table of Contents
* [Filters](#filters)
* [Criteria](#criteria)
* [Filter Shapes](#filter-shapes)
* [Simple Object](#simple-object)
* [Simple List](#simple-list)
* [Filter Types](#filter-types)
* [Author Filter](#author-filter)
* [Mod Actions/Notes Filter](#mod-actionsnotes-filter)
* [Toolbox UserNotes Filter](#toolbox-usernotes-filter)
* [Item Filter](#item-filter)
* [Subreddit Filter](#subreddit-filter)
* [Named Filters](#named-filters)
* [Examples](#examples)
* [General Usage](#general-usage)
* [Usage in a Run](#usage-in-a-run)
* [Usage in a Check](#usage-in-a-check)
* [Usage in a Rule](#usage-in-a-rule)
* [Usage in an Action](#usage-in-an-action)
* [Using Author and Item Filter](#using-author-and-item-filter)
* [Filter Shapes Usage](#filter-shapes-usage)
* [Using a Simple Object](#using-a-simple-object)
* [Using a Simple List](#using-a-simple-list)
* [Using a Full Anonymous Filter](#using-a-full-anonymous-filter)
* [Using a Full Anonymous Filter with Exclude](#using-a-full-anonymous-filter-with-exclude)
* [Using a Full Named Filter](#using-a-full-named-filter)
* [Author Filter Examples](#author-filter-examples)
* [New User](#new-user)
* [New User with pattern in Name](#new-user-with-pattern-in-name)
* [User has pattern in their profile description](#user-has-pattern-in-their-profile-description)
* [Exclude moderators AND users by name](#exclude-moderators-and-users-by-name)
* [Item Filter Examples](#item-filter-examples)
* [Unmoderated comment by non-op](#unmoderated-comment-by-non-op)
* [Submission is self post with no flair](#submission-is-self-post-with-no-flair)
# Filters
**Filters** are an additional channel for determining if an Event should be processed by ContextMod. They differ from [**Rules**](../../README.md#rules) in several key ways:
* **Runs, Checks, Rules, and Actions** can **all** have Filters
* Filters test against the **current state** of the Activity (or its Author) being processed, rather than looking at history/context/etc...
* Filter test results only determine if the Run, Check, Rule, or Action **should run** -- rather than triggering it
* When the filter test **passes** the thing being tested continues to process as usual
* When the filter test **fails** the thing being tested **fails**.
A Filter has these properties:
* `include` -- An optional list of Filter Criteria. If **any** passes the filter passes.
* `exclude` -- An optional list of Filter Criteria. All **must NOT** pass for the filter to pass. Ignored if `include` is present.
* `excludeCondition` -- A [condition](../../README.md#conditions) that determines how the list of Filter Criteria are tested together
## Criteria
A **criteria** is some property of a thing (Activity or Author) can be tested, and what the expected outcome is EX:
`age: '> 2 months'` => Author is older than 2 months
**Filter Criteria** is one of more **criteria** combined together to form a set of conditions that must all be true together for the Filter Criteria to be true EX
```yaml
age: '> 2 months'
verified: true
```
The above Filter Criteria is true if:
* the Author's account is older than 2 months AND
* they have a verified email
## Filter Shapes
Generically, a "full" Filter looks like this:
```yaml
include: #optional
- name: AFilterCriteria
criteria:
#...
#...one or more Filter Criteria
exclude: #optional
#...one or more Filter Criteria
excludeCondition: OR or AND
```
But for convenience a Filter's shape can be simplified with a few assumptions:
### Simple Object
When a Filter is an object, the object is assumed to be a [Filter Criteria](#criteria) which is used in `include`
```yaml
itemIs:
approved: false
```
### Simple List
When a Filter is a list, the list is assumed to be a list of [Filter Criteria](#criteria) and used in `include`
```yaml
itemIs:
- approved: false
filtered: false
- is_self: true
```
## Filter Types
There are two types of Filter. Both types have the same "shape" in the configuration with the differences between them being:
* what they are testing on
* what criteria are available to test
### Author Filter
Test the Author of an Activity. See [Schema documentation](https://json-schema.app/view/%23%2Fdefinitions%2FAuthorCriteria?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json) for all possible Author Criteria
#### Mod Actions/Notes Filter
See [Mod Actions/Notes](../modActions/README.md#mod-action-filter) documentation.
#### Toolbox UserNotes Filter
See [UserNotes](../userNotes/README.md) documentation
### Item Filter
Test for properties of an Activity:
* [Comment Criteria](https://json-schema.app/view/%23%2Fdefinitions%2FCommentState?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
* [Submission Criteria](https://json-schema.app/view/%23%2Fdefinitions%2FSubmissionState?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
### Subreddit Filter
Test for properties of the Subreddit an Activity belongs to. See [Schema documentation](https://json-schema.app/view/%23%2Fdefinitions%2FSubredditCriteria?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
## Named Filters
**Named Filters** work the same as [**Named Rules**](../../README.md#named-rules) and [**Named Actions:**](../../README.md#named-actions)
**Filter Criteria** may be given a `name`. A named **Filter Criteria** can **re-used anywhere in the configuration regardless of location.** This is done by:
* specifying a name on a **Filter Criteria** **once** EX: `name: MyFilterCriteria`
* using the Filter Criteria name in place of a Filter Criteria object
```yaml
runs:
- name: MyFirstRun
checks:
- name: MyFirstCheck
kind: submission
itemIs:
- MyFilterCriteria
rules:
#...
actions:
#...
- name: MySecondCheck
kind: submission
itemIs:
include:
- name: MyFilterCriteria
criteria:
approved: false
rules:
#...
actions:
#...
```
# Examples
## General Usage
Below are examples of where filters can be used
### Usage in a Run
```yaml
runs:
# this run will only be processed if author is a contributor
- name: MyRun
authorIs:
- isContributor: true
checks:
# - ...
```
### Usage in a Check
```yaml
runs:
- name: MyRun
checks:
# check will only be processed if author is a contributor
- name: MyCheck
kind: submission
authorIs:
- isContributor: true
rules:
# ...
actions:
# ...
```
### Usage in a Rule
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
rules:
# rule will only run if author is a contributor
- name: MyFirstRule
kind: recentActivity
authorIs:
- isContributor: true
thresholds:
# ...
actions:
# ...
```
### Usage in an Action
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
rules:
- name: MyFirstRule
# ...
actions:
# action will only run if author is a contributor
- kind: approve
authorIs:
- isContributor: true
```
### Using Author and Item Filter
```yaml
runs:
- name: MyRun
checks:
# Check will only process if author is a contributor AND submission is not approved
- name: MyCheck
kind: submission
authorIs:
- isContributor: true
itemIs:
- approved: false
rules:
# ...
actions:
# ...
```
## Filter Shapes Usage
Below are examples of how filters can be structured using [filter shapes](#filter-shapes)
### Using a Simple Object
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
# check is only processed if submission is not approved AND not marked as nsfw
itemIs:
approved: false
over_18: false
rules:
# ...
actions:
# ...
```
### Using a Simple List
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
# check is only processed if submission is EITHER:
# -> not approved AND not marked as nsfw
# -> not approved AND marked as nsfw AND has flair text 'Mildly NSFW;
itemIs:
# each '-' denotes a NEW set of criteria
- approved: false
over_18: false
- link_flair_text: Mildly NSFW
over_18: true
approved: false
rules:
# ...
actions:
# ...
```
### Using a Full Anonymous Filter
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
# check is only processed if submission is EITHER:
# -> not approved AND not marked as nsfw
# -> not approved AND marked as nsfw AND has flair text 'Mildly NSFW;
itemIs:
include:
- approved: false
over_18: false
- link_flair_text: Mildly NSFW
over_18: true
approved: false
rules:
# ...
actions:
# ...
```
### Using a Full Anonymous Filter with Exclude
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
# check is only processed if submission is NOT approved
itemIs:
exclude:
- approved: true
rules:
# ...
actions:
# ...
```
### Using a Full Named Filter
```yaml
runs:
- name: MyRun
checks:
- name: MyCheck
kind: submission
# check is only processed if submission is:
# -> not approved AND not marked as nsfw
itemIs:
include:
- name: sfwNotApproved
criteria:
- approved: false
over_18: false
rules:
# ...
actions:
# ...
```
## Author Filter Examples
### New User
```yaml
# author's account is less than 30 days old AND has less than 30 comment karma
authorIs:
include:
- name: newUser
criteria:
age: < 30 days
commentKarma: < 30
```
### New User with pattern in Name
```yaml
# author's account is less than 30 days old AND has less than 30 comment karma AND has 'nsfw' in their account name
authorIs:
include:
- name: newUser
criteria:
age: < 30 days
commentKarma: < 30
name: '/nsfw/i'
```
### User has pattern in their profile description
```yaml
authorIs:
include:
- description:
- '/Add Me On Snapchat/i'
- '/Add my snapchat/i'
- '/Dm me for content/i'
- '/Will Verify/i'
```
### Exclude moderators AND users by name
Useful when CM should not run if the author is from a list of users or a moderator
```yaml
authorIs:
excludeCondition: AND
exclude:
# will not run if user is a mod or is automoderator
- isMod: true
# will not run if the user is in the list below
- name:
- User1
- User2
- User3
```
## Item Filter Examples
### Unmoderated comment by non-op
```yaml
itemIs:
- removed: false
approved: false
op: false
```
### Submission is self post with no flair
```yaml
itemIs:
- is_self: true
link_flair_text: false
```

View File

@@ -1,73 +0,0 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# History Rule
The **History** rule can check an Author's submission/comment statistics over a time period:
* Submission total or percentage of All Activity
* Comment total or percentage of all Activity
* Comments made as OP (commented in their own Submission) total or percentage of all Comments
* Ratio of activities against another window of activities
Consult the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FHistoryJSONConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) for a complete reference of the rule's properties.
## Ratio
Use the `ratio` property in Criteria to test the [number of activities](../../activitiesWindow.md) found in the parent criteria against the number of activities from _another_ [activity window](../../activitiesWindow.md) defined in the ratio.
Example:
```yaml
- kind: history
criteria:
# "parent" criteria, returns all activities, in the last 100 from user's history, that occurred in r/mealtimevideos
- window:
count: 100
filterOn:
post:
subreddits:
include:
- mealtimevideos
ratio:
# "ratio" criteria, returns all activities, in the last 100 from user's history, that occurred in r/redditdev
window:
count: 100
filterOn:
post:
subreddits:
include:
- redditdev
# test (number of parent criteria activities) / (number of ratio critieria activities)
threshold: '> 1.2'
```
`threshold` may be a number or percentage `(number * 100)`
* EX `> 1.2` => There are 1.2 activities from parent criteria for every 1 ratio activities
* EX `<= 75%` => There are equal to or less than 0.75 activities from parent criteria for every 1 ratio activities
### Examples
* Low Comment Engagement [YAML](lowEngagement.yaml) | [JSON](lowEngagement.json5) - Check if Author is submitting much more than they comment.
* OP Comment Engagement [YAML](opOnlyEngagement.yaml) | [JSON](opOnlyEngagement.json5) - Check if Author is mostly engaging only in their own content
# [Template Variables](../../actionTemplating.md)
| Name | Description | Example |
|----------------------|------------------------------------------------------------------------|----------------------------------------------------|
| `result` | Summary of rule results (also found in Actioned Events) | Filtered Activities (7) were < 10 Items (2 months) |
| `activityTotal` | Total number of activities from window | 50 |
| `filteredTotal` | Total number of activities filtered from window | 7 |
| `filteredPercent` | Percentage of activities filtered from window | 14% |
| `submissionTotal` | Total number of filtered submissions from window | 4 |
| `submissionPercent` | Percentage of filtered submissions from window | 8% |
| `commentTotal` | Total number of filtered comments from window | 3 |
| `commentPercent` | Percentage of filtered comments from window | 6% |
| `opTotal` | Total number of comments as OP from filtered comments | 2 |
| `opPercent` | Percentage of comments as OP from filtered comments | 66% |
| `thresholdSummary` | A text summary of the first Criteria triggered with totals/percentages | Filtered Activities (7) were < 10 Items |
| `subredditBreakdown` | A markdown list of filtered activities by subreddit | * SubredditA - 5 (71%) \n * Subreddit B - 2 (28%) |
| `window` | Number or duration of Activities considered from window | 2 months |

View File

@@ -1,184 +0,0 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# ModerateHateSpeech.com Rule
# Table of Contents
* [Overview](#overview)
* [MHS Predictions](#mhs-predictions)
* [Flagged](#flagged)
* [Confidence](#confidence)
* [Usage](#usage)
* [Minimal/Default Config](#minimaldefault-config)
* [Full Config](#full-config)
* [Historical Matching](#historical-matching)
* [Examples](#examples)
# Overview
[moderatehatespeech.com](https://moderatehatespeech.com/) (MHS) is a [non-profit initiative](https://moderatehatespeech.com/about/) to identify and fight toxic and hateful content online using programmatic technology such as machine learning models.
They offer a [toxic content prediction model](https://moderatehatespeech.com/framework/) specifically trained on and for [reddit content](https://www.reddit.com/r/redditdev/comments/xdscbo/updated_bot_backed_by_moderationoriented_ml_for/) as well as partnering [directly with subreddits.](https://moderatehatespeech.com/research/subreddit-program/).
Context Mod leverages their [API](https://moderatehatespeech.com/docs/) for toxic content predictions in the **MHS Rule.**
The **MHS Rule** sends an Activity's content (title or body) to MHS which returns a prediction on whether the content is toxic and actionable by a moderator.
## MHS Predictions
MHS's toxic content predictions return two indicators about the content it analyzed. Both are available as test conditions in ContextMod.
### Flagged
MHS returns a straight "Toxic or Normal" **flag** based on how it classifies the content.
Example
* `Normal` - "I love those pineapples"
* `Toxic` - "why are we having all these people from shithole countries coming here"
### Confidence
MHS returns how **confident** it is of the flag classification on a scale of 0 to 100.
Example
"why are we having all these people from shithole countries coming here"
* Flag = `Toxic`
* Confidence = `97.12` -> The model is 97% confident the content is `Toxic`
# Usage
**An MHS Api Key is required to use this Rule**. An API Key can be acquired, for free, by creating an account at [moderatehatespeech.com](https://moderatehatespeech.com).
The Key can be provided by the bot's Operator in the [bot config credentials](https://json-schema.app/view/%23/%23%2Fdefinitions%2FBotInstanceJsonConfig/%23%2Fdefinitions%2FBotCredentialsJsonConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fedge%2Fsrc%2FSchema%2FOperatorConfig.json) or in the subreddit's config in the top-level `credentials` property like this:
```yaml
credentials:
mhs:
apiKey: 'myMHSApiKey'
# the rest of your config below
polling:
# ...
runs:
# ...
```
### Minimal/Default Config
ContextMod provides a reasonable default configuration for the MHS Rule if you do not wish to configure it yourself. The default configuration will trigger the rule if the MHS prediction:
* flags as `toxic`
* with `90% or greater` confidence
Example
```yaml
rules:
- kind: mhs
# rest of your rules here...
```
### Full Config
| Property | Type | Description | Default |
|--------------|---------|-------------------------------------------------------------------------------------------|---------|
| `flagged` | boolean | Test whether content is flagged as toxic (true) or normal (false) | `true` |
| `confidence` | string | Comparison against a number 0 to 100 representing how confident MHS is in the prediction | `>= 90` |
| `testOn` | array | Which parts of the Activity to send to MHS. Options: `title` and/or `body` | `body` |
Example
```yaml
rules:
- kind: mhs
criteria:
flagged: true # triggers if MHs flags the content as toxic AND
confidence: '> 66' # MHS is 66% or more confident in its prediction
testOn: # send the body of the activity to the MHS prediction service
- body
```
#### Historical Matching
Like the [Sentiment](../sentiment#historical) and [Regex](../regex#historical) rules CM can also use MHS predictions to check content from the Author's history.
Example
```yaml
rules:
- kind: mhs
# ...same config as above but can include below...
historical:
mustMatchCurrent: true # if true then CM will not check author's history unless current Activity matches MHS prediction criteria
totalMatching: '> 1' # comparison for how many activities in history must match to trigger the rule
window: 10 # specify the range of activities to check in author's history
criteria: #... if specified, overrides parent-level criteria
```
# [Template Variables](../../actionTemplating.md)
| Name | Description | Example |
|-----------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| `result` | Summary of rule results (also found in Actioned Events) | Current Activity MHS Test: ✓ Confidence test (>= 90) PASSED MHS confidence of 99.85% Flagged pass condition of true (toxic) MATCHED MHS flag 'toxic' |
| `window` | Number or duration of Activities considered from window | 1 activities |
| `criteriaTest` | MHS value to test against | MHS confidence is > 95% |
| `totalMatching` | Total number of activities (current + historical) that matched `criteriaTest` | 1 |
# Examples
Report if MHS flags as toxic
```yaml
rules:
- kind: mhs
actions:
- kind: report
content: 'MHS flagged => {{rules.mhs.summary}}'
```
Report if MHS flags as toxic with 95% confidence
```yaml
rules:
- kind: mhs
criteria:
confidence: '>= 95'
actions:
- kind: report
content: 'MHS flagged => {{rules.mhs.summary}}'
```
Report if MHS flags as toxic and at least 3 recent activities in last 10 from author's history are also toxic
```yaml
rules:
- kind: mhs
historical:
window: 10
mustMatchCurrent: true
totalMatching: '>= 3'
actions:
- kind: report
content: 'MHS flagged => {{rules.mhs.summary}}'
```
Approve if MHS flags as NOT toxic with 95% confidence
```yaml
rules:
- kind: mhs
criteria:
confidence: '>= 95'
flagged: false
actions:
- kind: approve
```

View File

@@ -1,50 +0,0 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Recent Activity Rule
Given a list subreddit criteria, the **Recent Activity** rule finds Activities matching those criteria in the Author's history over [window](../../activitiesWindow.md) and then allows for comparing different facets of the results.
Subreddit criteria can be:
* names
* regular expression for names
* [Subreddit meta properties](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubmissionCheckJson/%23%2Fdefinitions%2FRecentActivityRuleJSONConfig/%23%2Fdefinitions%2FActivityThreshold/%23%2Fdefinitions%2FSubredditState?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fmaster%2Fsrc%2FSchema%2FApp.json) like NSFW, description, is user profile, is author's profile, etc...
Facets available to compare from analyzed history:
* number of activities found EX `> 3` => more than 3 activities found
* aggregated karma from activities EX `> 50` => more than 50 combined karma from found activities
* number of subreddits found EX `> 5` => more than 5 distinct subreddits matching subreddit criteria found
The above can also be expressed as a percentage instead of number IE "more than 10% of activities in author history come from subreddits matching criteria"
The search can also be modified in a number of ways:
* Filter found activities using an [Item Filter](#item)
* Only return activities that match the Activity from the Event being processed
* Using image detection (pixel or perceptual hash matching)
* Only return certain types of activities (only submission or only comments)
Consult the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FRecentActivityRuleJSONConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) for a complete reference of the rule's properties.
### Examples
* Free Karma Subreddits [YAML](freeKarma.yaml) | [JSON](freeKarma.json5) - Check if the Author has recently posted in any "free karma" subreddits
* Submission in Free Karma Subreddits [YAML](freeKarmaOnSubmission.yaml) | [JSON](freeKarmaOnSubmission.json5) - Check if the Author has posted the Submission this check is running on in any "free karma" subreddits recently
# [Template Variables](../../actionTemplating.md)
| Name | Description | Example |
|----------------------|------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| `result` | Summary of rule results (also found in Actioned Events) | 9 activities found in 2 of the specified subreddits (out of 21 total) MET threshold of >= 1 activities -- subreddits: SubredditA, SubredditB |
| `window` | Number or duration of Activities considered from window | 100 activities |
| `subSummary` | Comma-delimited list of subreddits matched by the criteria | SubredditA, SubredditB |
| `subCount` | Number of subreddits that match the criteria | 2 |
| `totalCount` | Total number of activities found by criteria | 9 |
| `threshold` | The threshold used to trigger the rule | `>= 1` |
| `karmaThreshold` | If present, the karma threshold used to trigger the rule | `> 5` |
| `combinedKarma` | Total number of karma gained from the matched activities | 10 |
| `subredditBreakdown` | A markdown list of filtered activities by subreddit | * SubredditA - 5 (71%) \n * Subreddit B - 2 (28%) |

View File

@@ -1,36 +0,0 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Regex Rule
The **Regex** rule matches on text content from a comment or submission in the same way automod uses regex. The rule, however, provides additional functionality automod does not:
* Can set the **number** of matches that trigger the rule (`matchThreshold`)
Which can then be used in conjunction with a [`window`](../../activitiesWindow.md) to match against activities from the history of the Author of the Activity being checked (including the Activity being checked):
* Can set the **number of Activities** that meet the `matchThreshold` to trigger the rule (`activityMatchThreshold`)
* Can set the **number of total matches** across all Activities to trigger the rule (`totalMatchThreshold`)
* Can set the **type of Activities** to check (`lookAt`)
* When an Activity is a Submission can **specify which parts of the Submission to match against** IE title, body, and/or url (`testOn`)
### Examples
* Trigger if regex matches against the current activity - [YAML](matchAnyCurrentActivity.yaml) | [JSON](matchAnyCurrentActivity.json5)
* Trigger if regex matches 5 times against the current activity - [YAML](matchThresholdCurrentActivity.yaml) | [JSON](matchThresholdCurrentActivity.json5)
* Trigger if regex matches against any part of a Submission - [YAML](matchSubmissionParts.yaml) | [JSON](matchSubmissionParts.json5)
* Trigger if regex matches any of Author's last 10 activities - [YAML](matchHistoryActivity.yaml) | [JSON](matchHistoryActivity.json5)
* Trigger if regex matches at least 3 of Author's last 10 activities - [YAML](matchActivityThresholdHistory.json5) | [JSON](matchActivityThresholdHistory.json5)
* Trigger if there are 5 regex matches in the Author's last 10 activities - [YAML](matchTotalHistoryActivity.yaml) | [JSON](matchTotalHistoryActivity.json5)
* Trigger if there are 5 regex matches in the Author's last 10 comments - [YAML](matchSubsetHistoryActivity.yaml) | [JSON](matchSubsetHistoryActivity.json5)
* Remove comments that are spamming discord links - [YAML](removeDiscordSpam.yaml) | [JSON](removeDiscordSpam.json5)
* Differs from just using automod because this config can allow one-off/organic links from users who DO NOT spam discord links but will still remove the comment if the user is spamming them
# [Template Variables](../../actionTemplating.md)
| Name | Description | Example |
|---------------|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| `result` | Summary of rule results (also found in Actioned Events) | Criteria 1 ✓ -- Activity Match ✓ => 1 > 0 (Threshold > 0) and 1 Total Matches (Window: 1 Item) -- Matched Values: "example.com/test" |
| `matchSample` | A comma-delimited list of matches from activities | "example.com/test" |

View File

@@ -0,0 +1,120 @@
Actions that can submit text (Report, Comment, UserNote) will have their `content` values run through a [Mustache Template](https://mustache.github.io/). This means you can insert data generated by Rules into your text before the Action is performed.
See here for a [cheatsheet](https://gist.github.com/FoxxMD/d365707cf99fdb526a504b8b833a5b78) and [here](https://www.tsmean.com/articles/mustache/the-ultimate-mustache-tutorial/) for a more thorough tutorial.
# Template Data
## Activity Data
Activity data can be accessed using the `item` variable. Example
```
This activity is a {{item.kind}} with {{item.votes}} votes, created {{item.age}} ago.
```
Produces:
> This activity is a submission with 10 votes created 5 minutes ago.
### Common
All Actions with `content` have access to this data:
| Name | Description | Example |
|-------------|-----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|
| `kind` | The Activity type (submission or comment) | submission |
| `author` | Name of the Author of the Activity being processed | FoxxMD |
| `permalink` | URL to the Activity | https://reddit.com/r/mySuibreddit/comments/ab23f/my_post |
| `votes` | Number of upvotes | 69 |
| `age` | The age of the Activity in a [human friendly format](https://day.js.org/docs/en/durations/humanize) | 5 minutes |
| `botLink` | A URL to CM's introduction thread | https://www.reddit.com/r/ContextModBot/comments/otz396/introduction_to_contextmodbot |
### Submissions
If the **Activity** is a Submission these additional properties are accessible:
| Name | Description | Example |
|---------------|-----------------------------------------------------------------|-------------------------|
| `upvoteRatio` | The upvote ratio | 100% |
| `nsfw` | If the submission is marked as NSFW | true |
| `spoiler` | If the submission is marked as a spoiler | true |
| `url` | If the submission was a link then this is the URL for that link | http://example.com |
| `title` | The title of the submission | Test post please ignore |
### Comments
If the **Activity** is a Comment these additional properties are accessible:
| Name | Description | Example |
|------|--------------------------------------------------------------|---------|
| `op` | If the Author is the OP of the Submission this comment is in | true |
### Moderator
If the **Activity** occurred in a Subreddit the Bot moderates these properties are accessible:
| Name | Description | Example |
|---------------|-------------------------------------|---------|
| `reports` | The number of reports recieved | 1 |
| `modReports` | The number of reports by moderators | 1 |
| `userReports` | The number of reports by users | 1 |
## Rule Data
### Summary
A summary of what rules were processed and which were triggered, with results, is available using the `ruleSummary` variable. Example:
```
A summary of rules processed for this activity:
{{ruleSummary}}
```
Would produce:
> A summary of rules processed for this activity:
>
> * namedRegexRule - ✘
> * nameAttributionRule - ✓ - 1 Attribution(s) met the threshold of < 20%, with 1 (3%) of 32 Total -- window: 6 months
> * noXPost ✓ - ✓ 1 of 1 unique items repeated <= 3 times, largest repeat: 1
### Individual
Individual **Rules** can be accessed using the name of the rule, **lower-cased, with all spaces/dashes/underscores.** Example:
```
Submission was repeated {{rules.noxpost.largestRepeat}} times
```
Produces
> Submission was repeated 7 times
#### Quick Templating Tutorial
As a quick example for how you will most likely be using templating -- wrapping a variable in curly brackets, `{{variable}}`, will cause the variable value to be rendered instead of the brackets:
```
myVariable = 50;
myOtherVariable = "a text fragment"
template = "This is my template, the variable is {{myVariable}}, my other variable is {{myOtherVariable}}, and that's it!";
console.log(Mustache.render(template, {myVariable});
// will render...
"This is my template, the variable is 50, my other variable is a text fragment, and that's it!";
```
**Note: When accessing an object or its properties you must use dot notation**
```
const item = {
aProperty: 'something',
anotherObject: {
bProperty: 'something else'
}
}
const content = "My content will render the property {{item.aProperty}} like this, and another nested property {{item.anotherObject.bProperty}} like this."
```

View File

@@ -1,9 +1,3 @@
---
parent: Subreddit Configuration
---
# Activities `window`
# Table Of Contents
* [Overview](#overview)
@@ -30,13 +24,13 @@ parent: Subreddit Configuration
# Overview
An **Activity Window** (`window`) is a group of properties that describe a **range** of [**Activities**](../README.md#activity) to retrieve from Reddit and how to **filter** them.
An **Activity Window** (`window`) is a group of properties that describe a **range** of [**Activities**](/docs/README.md#activity) to retrieve from Reddit and how to **filter** them.
The main components of an Activity Window:
* **Range** -- How many Activities ([`count`](#count)) or what time period ([`duration`](#duration)) of Activities to fetch
* **Type of Activities** -- When **fetching** from an Author's history, should it return overview (any Activities), just Submissions, or just Comments?
* **Filters** -- How the retrieved Activities should be [filtered](README.md#filters) before returning them to a Rule
* **Filters** -- How the retrieved Activities should be [filtered](/docs/subreddit/components/README.md#filters) before returning them to a Rule
As an example, if you want to run a **Recent Activity Rule** to check if a user has had activity in /r/mealtimevideos you also need to define what range of activities you want to look at from that user's history.
@@ -220,7 +214,7 @@ window:
# Filters
Activity Window can also specify [Item and Subreddit Filters](README.md#filters) to filter the Activities retrieved from Reddit before they are returned to a Rule.
Activity Window can also specify [Item and Subreddit Filters](/docs/subreddit/components/README.md#filters) to filter the Activities retrieved from Reddit before they are returned to a Rule.
Activities can be filtered **during** (`pre`) retrieval or **after** (`post`) retrieval. **When**, during the window **lifecycle**, the Activities are filtered can change the set of Activities returned to a Rule drastically.
@@ -228,10 +222,10 @@ Activities can be filtered **during** (`pre`) retrieval or **after** (`post`) re
Regardless of when you are filtering Activities the shape of the filter is the same. Filter properties:
* `subreddits` -- A [Filter Shape](README.md#filter-shapes) for filtering by the [Subreddit Criteria](README.md#subreddit-filter) of each Activity
* `submissionState` -- A [Filter Shape](README.md#filter-shapes) for [Submission Criteria](README.md#item-filter). Will run only if filtering a Submission.
* `commentState` -- A [Filter Shape](README.md#filter-shapes) for [Comment Criteria](README.md#item-filter). Will run only if filtering a Comment.
* `activityState` -- A [Filter Shape](README.md#filter-shapes) for either [Submission or Comment Criteria](README.md#item-filter). Will run only if `submissionState` or `commentState` is not defined for their respective Activity types.
* `subreddits` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for filtering by the [Subreddit Criteria](/docs/subreddit/components/README.md#subreddit-filter) of each Activity
* `submissionState` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for [Submission Criteria](/docs/subreddit/components/README.md#item-filter). Will run only if filtering a Submission.
* `commentState` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for [Comment Criteria](/docs/subreddit/components/README.md#item-filter). Will run only if filtering a Comment.
* `activityState` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for either [Submission or Comment Criteria](/docs/subreddit/components/README.md#item-filter). Will run only if `submissionState` or `commentState` is not defined for their respective Activity types.
In this example the filter only returns Activities:

View File

@@ -1,10 +1,3 @@
---
has_children: true
nav_order: 5
---
# Subreddit Configuration
High level overviews, important features of, and example usage for significant components in a subreddit's configuration are found here.
This list is not exhaustive. [For complete documentation on a subreddit's configuration consult the schema.](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fmaster%2Fsrc%2FSchema%2FApp.json)
@@ -29,7 +22,6 @@ This list is not exhaustive. [For complete documentation on a subreddit's config
* [Regex](#regex)
* [Repost](#repost)
* [Sentiment Analysis](#sentiment-analysis)
* [Toxic Content Prediction](#moderatehatespeechcom-predictions)
* [Rule Sets](#rule-sets)
* [Actions](#actions)
* [Named Actions](#named-actions)
@@ -52,6 +44,13 @@ This list is not exhaustive. [For complete documentation on a subreddit's config
* [Toolbox UserNote](#usernote)
* [Mod Note](#mod-note)
* [Filters](#filters)
* [Filter Types](#filter-types)
* [Author Filter](#author-filter)
* [Mod Notes/Actions](#mod-actionsnotes-filter)
* [Toolbox UserNotes](#toolbox-usernotes-filter)
* [Item Filter](#item-filter)
* [Subreddit Filter](#subreddit-filter)
* [Named Filters](#named-filters)
* [Common Patterns](#common-patterns)
* [Conditions](#conditions)
* [Activities `window`](#activities-window)
@@ -70,12 +69,11 @@ This list is not exhaustive. [For complete documentation on a subreddit's config
* [Rule Order](#rule-order)
* [Configuration Re-use and Caching](#configuration-re-use-and-caching)
* [Partial Configurations](#partial-configurations)
* [Sharing Configs Between Subreddits](#sharing-full-configs-as-runs)
* [Subreddit-ready examples](#subreddit-ready-examples)
# Runs
A **Run** is made up of a set of [**Checks**](#checks) that represent a group of related behaviors the bot should check for or perform. Checks within a Run are processed in the order they are listed. Refer to the [How It Works](../README.md#how-it-works) section to see how Runs fit into CM's lifecycle.
A **Run** is made up of a set of [**Checks**](#checks) that represent a group of related behaviors the bot should check for or perform. Checks within a Run are processed in the order they are listed. Refer to the [How It Works](/docs/README.md#how-it-works) section to see how Runs fit into CM's lifecycle.
**Runs** are the largest unit of behavior in a subreddit's configuration and are defined at the top level of the configuration like so:
@@ -135,13 +133,13 @@ A **Check** is a set of:
* Zero or more [**Rules**](#rules) that define what conditions should **trigger** this Check.
* Zero or more [**Actions**](#actions) that define what the bot should do once the Check is **triggered**.
Refer to the [How It Works](../README.md#how-it-works) section to see how Checks fit into CM's lifecycle.
Refer to the [How It Works](/docs/README.md#how-it-works) section to see how Checks fit into CM's lifecycle.
* If a Check has no Rules and passes any [Filters](#filters) it is automatically triggered
* If a Check is triggered and has no Actions it is only [recorded](#recording-options)
* **Checks must have explicitly defined:**
* **name**
* **kind** -- what type of [Activity](../README.md#activity) (`submission` or `comment`) it should process
* **kind** -- what type of [Activity](/docs/README.md#activity) (`submission` or `comment`) it should process
```yaml
runs:
@@ -217,11 +215,11 @@ This enables a user to arbitrarily configure how CM responds to the triggering (
Each Check will **always** have these properties defined -- either explicitly or passed down as defaults from a [Run](#flow-control-defaults-using-runs), [Subreddit](#filter-defaults), or Operator configuration.
Refer to the main [**Flow Control** documentation](advancedConcepts/flowControl.md) for an in-depth explanation and all possible options.
Refer to the main [**Flow Control** documentation](/docs/subreddit/components/advancedConcepts/flowControl.md) for an in-depth explanation and all possible options.
## Recording Options
`postFail` and `postTrigger` also enable specifying if/how an [Event](../README.md#event) is recorded. Valid options for recording:
`postFail` and `postTrigger` also enable specifying if/how an [Event](/docs/README.md#event) is recorded. Valid options for recording:
* `false` -- do not record this Event
* `true` -- record Event to all available outputs
@@ -251,7 +249,7 @@ When an Activity has finished being processed CM will aggregate all Recording Op
# Rules
A **Rule** is some set of **criteria** (conditions) that are tested against an [Activity](../README.md#activity), a User, or a User's history. A Rule is considered **triggered** when the **criteria** for that rule are found to be **true** for whatever is being tested against.
A **Rule** is some set of **criteria** (conditions) that are tested against an [Activity](/docs/README.md#activity), a User, or a User's history. A Rule is considered **triggered** when the **criteria** for that rule are found to be **true** for whatever is being tested against.
Rules must have a `kind` that identifies what kind of Rule they are.
@@ -294,13 +292,13 @@ runs:
Named Rules are essential building blocks of a readable and effective configuration. If you find yourself repeating the same Rule many times it's a sign you should give it a name and replace it's usage with references to it.
See **Rule Name Reuse Examples [YAML](advancedConcepts/ruleNameReuse.yaml) | [JSON](advancedConcepts/ruleNameReuse.json5)**
See **Rule Name Reuse Examples [YAML](/docs/subreddit/components/advancedConcepts/ruleNameReuse.yaml) | [JSON](/docs/subreddit/components/advancedConcepts/ruleNameReuse.json5)**
## List of Rules
### Attribution
[**Full Documentation**](in-depth/attribution)
[**Full Documentation**](/docs/subreddit/components/attribution)
The **Attribution** rule will aggregate an Author's content Attributions (youtube channels, twitter, website domains, etc.) and can check on their totals or percentages of all Activities over a time period:
@@ -311,7 +309,7 @@ The **Attribution** rule will aggregate an Author's content Attributions (youtub
### Recent Activity
[**Full Documentation**](in-depth/recentActivity)
[**Full Documentation**](/docs/subreddit/components/recentActivity)
Given a list subreddit criteria, the **Recent Activity** rule finds Activities matching those criteria in the Author's history over [window](#activities-window) and then allows for comparing different facets of the results:
@@ -323,14 +321,14 @@ The above can also be expressed as a percentage of all activities found, instead
The search can also be modified in a number of ways:
* Filter found activities using an [Item Filter](in-depth/filters#item-filter)
* Filter found activities using an [Item Filter](#item-filter)
* Only return activities that match the Activity from the Event being processed
* Using [image detection](imageComparison.md) (pixel or perceptual hash matching)
* Using [image detection](/docs/imageComparison.md) (pixel or perceptual hash matching)
* Only return certain types of activities (only submission or only comments)
### Repeat Activity
[**Full Documentation**](in-depth/repeatActivity)
[**Full Documentation**](/docs/subreddit/components/repeatActivity)
The **Repeat Activity** rule will check for patterns of repetition in an Author's Activity history over a [window](#activities-window). When comparing submissions it checks a composite of the submissions' title and content.
@@ -345,7 +343,7 @@ Some of the ways the rule can be modified:
### History
[**Full Documentation**](in-depth/history)
[**Full Documentation**](/docs/subreddit/components/history)
The **History** rule can check an Author's submission/comment statistics over a time period:
@@ -355,36 +353,30 @@ The **History** rule can check an Author's submission/comment statistics over a
### Author
[**Full Documentation**](in-depth/author)
[**Full Documentation**](/docs/subreddit/components/author)
The **Author** rule behaves the same as the [Author Filter](in-depth/filters#author-filter). It can be used when you want to test Author state alongside other rules to create more complex behavior than would be possible by only applying to individual Rules or an entire check.
The **Author** rule behaves the same as the [Author Filter](#author-filter). It can be used when you want to test Author state alongside other rules to create more complex behavior than would be possible by only applying to individual Rules or an entire check.
### Regex
[**Full Documentation**](in-depth/regex)
[**Full Documentation**](/docs/subreddit/components/regex)
The **Regex** rule matches on text content from an Activity in the same way automod uses regex. However, it can also be used to match on content from the Author's Activity history over a [window](#activities-window).
### Repost
[**Full Documentation**](in-depth/repost)
[**Full Documentation**](/docs/subreddit/components/repost)
The **Repost** rule is used to find reposts for both **Submissions** and **Comments**, depending on what type of **Check** it is used on.
This rule is for searching **all of Reddit** for reposts, as opposed to just the history of the Author of the Activity being checked. If you only want to check for reposts by the Author of the Activity being checked you should use the [Repeat Activity](repeatActivity) rule.
This rule is for searching **all of Reddit** for reposts, as opposed to just the history of the Author of the Activity being checked. If you only want to check for reposts by the Author of the Activity being checked you should use the [Repeat Activity](/docs/subreddit/components/repeatActivity) rule.
### Sentiment Analysis
[**Full Documentation**](in-depth/sentiment)
[**Full Documentation**](/docs/subreddit/components/sentiment)
The **Sentiment Rule** is used to determine the overall emotional intent (negative, neutral, positive) of a Submission or Comment by analyzing the actual text content of the Activity.
### ModerateHateSpeech.com Predictions
[**Full Documentation**](in-depth/mhs)
ContextMod integrates with [moderatehatespeech.com](https://moderatehatespeech.com/) (MHS) [toxic content machine learning model](https://moderatehatespeech.com/framework/) through their API. This rule sends an Activity's content (title or body) to MHS which returns a prediction on whether the content is toxic and actionable by a moderator. Their model is [specifically trained for reddit content.](https://www.reddit.com/r/redditdev/comments/xdscbo/updated_bot_backed_by_moderationoriented_ml_for/)
# Rule Sets
The `rules` list on a `Check` can contain both `Rule` objects and `RuleSet` objects.
@@ -420,7 +412,7 @@ runs:
...
```
See **ruleSets [YAML](advancedConcepts/ruleSets.yaml) | [JSON](advancedConcepts/ruleSets.json5)** for a complete example as well as consulting the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FRuleSetJson?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json).
See **ruleSets [YAML](/docs/subreddit/components/advancedConcepts/ruleSets.yaml) | [JSON](/docs/subreddit/components/advancedConcepts/ruleSets.json5)** for a complete example as well as consulting the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FRuleSetJson?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json).
# Actions
@@ -432,7 +424,7 @@ Actions are performed in the order they are listed in the **Check.**
## Named Actions
**Named Actions** work the same as [**Named Rules**](#named-rules) and [**Named Filters:**](in-depth/filters#named-filters)
**Named Actions** work the same as [**Named Rules**](#named-rules) and [**Named Filters:**](#named-filters)
Actions may be given a `name`. If an Action is named it can **re-used anywhere in the configuration regardless of location.** This is done by:
@@ -464,7 +456,7 @@ runs:
Actions that can submit text (Report, Comment, UserNote) will have their `content` values run through a [Mustache Template](https://mustache.github.io/). This means you can insert data generated by Rules into your text before the Action is performed.
[**Action Templating Documentation**](actionTemplating.md)
[**Action Templating Documentation**](/docs/subreddit/actionTemplating.md)
## List of Actions
@@ -537,25 +529,6 @@ actions:
targets: string # 'self' or 'parent' or 'https://reddit.com/r/someSubreddit/21nfdi....'
```
### Comment As Subreddit
ContextMod can comment [as the subreddit](https://www.reddit.com/r/modnews/comments/wpy5c8/announcing_remove_as_a_subreddit/) using the `/u/subreddit-ModTeam` account with some restrictions:
* The activity being replied to must ALREADY BE REMOVED.
* You can use the [Remove Action](#remove) beforehand to ensure this is the case.
* The created comment will always be stickied and distinguished
Usage:
```yaml
actions:
- kind: comment
asModTeam: true
content: string # required, the content of the comment
lock: boolean # lock the comment after creation
targets: string # 'self' or 'parent' or 'https://reddit.com/r/someSubreddit/21nfdi....'
```
### Submission
Create a Submission [Schema Documentation](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubmissionCheckJson/%23%2Fdefinitions%2FSubmissionActionJson?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fmaster%2Fsrc%2FSchema%2FApp.json)
@@ -719,16 +692,15 @@ Some other things to note:
* If the `to` property is not specified then the message is sent to the Author of the Activity being processed
* `to` may be a **User** (u/aUser) or a **Subreddit** (r/aSubreddit)
* `to` **cannot** be a Subreddit when `asSubreddit: true` -- IE cannot send subreddit-to-subreddit messages
* TIP: `to` can be templated -- to send a message to the subreddit the Activity being processed is in use `'r/{{item.subreddit}}'`
* `content` and `title` can be [templated](#templating) and use [URL Tokens](#url-tokens)
* `content` can be [templated](#templating) and use [URL Tokens](#url-tokens)
```yaml
actions:
- kind: message
asSubreddit: true
content: 'A message sent as the subreddit' # can be templated
title: 'Title of the message' # can be templated
to: 'u/aUser' # do not specify 'to' in order default to sending to Author of Activity being processed. Can also be templated
content: 'A message sent as the subreddit'
title: 'Title of the message'
to: 'u/aUser' # do not specify 'to' in order default to sending to Author of Activity being processed
```
### Remove
@@ -736,7 +708,7 @@ actions:
Remove the Activity being processed. [Schema Documentation](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubmissionCheckJson/%23%2Fdefinitions%2FRemoveActionJson?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
* **note** can be [templated](#templating)
* **reasonId** IDs can be found in the [editor](../../webInterface.md) using the **Removal Reasons** popup
* **reasonId** IDs can be found in the [editor](/docs/webInterface.md) using the **Removal Reasons** popup
If neither note nor reasonId are included then no removal reason is added.
@@ -764,7 +736,7 @@ actions:
Add a Toolbox User Note to the Author of the Activity. [Schema Documentation](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubmissionCheckJson/%23%2Fdefinitions%2FUserNoteActionJson?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
Your subreddit must have [Toolbox UserNotes](in-depth/userNotes) enabled for this action to work.
Your subreddit must have [Toolbox UserNotes](/docs/subreddit/components/userNotes) enabled for this action to work.
* `type` is required
* `content` can be [templated](#templating) and use [URL Tokens](#url-tokens)
@@ -774,12 +746,12 @@ actions:
- kind: usernote
type: spamwarn
content: 'Usernote message'
existingNoteCheck: boolean # if true (default) then the usernote will not be added if the same note appears for this activity
allowDuplicate: boolean # if false then the usernote will not be added if the same note appears for this activity
```
### Mod Note
[**Full Documentation**](in-depth/modActions/README.md#mod-note-action)
[**Full Documentation**](/docs/subreddit/components/modActions/README.md#mod-note-action)
Add a [Mod Note](https://www.reddit.com/r/modnews/comments/t8vafc/announcing_mod_notes/) for the Author of the Activity.
@@ -799,7 +771,6 @@ actions:
type: SPAM_WATCH
content: 'a note only mods can see message' # optional
referenceActivity: boolean # if true the Note will be linked to the Activity being processed
existingNoteCheck: boolean # if true (default) then the note will not be added if the same note appears for this activity
```
# Filters
@@ -808,17 +779,133 @@ actions:
* **Runs, Checks, Rules, and Actions** can **all** have Filters
* Filters test against the **current state** of the Activity (or it's Author) being processed, rather than looking at history/context/etc...
* CM supports filters for:
* [Author](in-depth/filters#author-filter) - age, verified email, profile description, flair...
* [Item (Submission/Comment)](in-depth/filters#item-filter) - sticked, # of reports, removed, flair, score...
* [Subreddit](in-depth/filters#subreddit-filter) - name, nsfw, quarantined...
* [Toolbox Usernotes](in-depth/filters#toolbox-usernotes-filter)
* [Mod Notes](in-depth/filters#mod-actionsnotes-filter)
* Filter test results only determine if the Run, Check, Rule, or Action **should run** -- rather than triggering it
* When the filter test **passes** the thing being tested continues to process as usual
* When the filter test **fails** the thing being tested **fails**.
[**Refer to the full Filter documentation for more**](in-depth/filters)
A Filter has these properties:
* `include` -- An optional list of Filter Criteria. If **any** passes the filter passes.
* `exclude` -- An optional list of Filter Criteria. All **must NOT** pass for the filter to pass. Ignored if `include` is present.
* `excludeCondition` -- A [condition](#conditions) that determines how the list of Filter Criteria are tested together
## Filter Criteria
A **criteria** is some property of a thing can be tested, and what the expected outcome is EX
`age: '> 2 months'` => Author is older than 2 months
**Filter Criteria** is one of more **criteria** combined together to form a set of criteria that must all be true together for the Filter Criteria to be true EX
```yaml
age: '> 2 months'
verified: true
```
The above Filter Criteria is true if the Author's account is older than 2 months AND they have a verified email
### Filter Shapes
Generically, a "full" Filter looks like this:
```yaml
include: #optional
- name: AFilterCriteria
criteria:
...
... #one or more filter criteria
exclude: #optional
... # one or more filter criteria
excludeCondition: OR or AND
```
But for convenience a Filter's shape can be simplified with a few assumptions
#### Simple Object
When a Filter is an object, the object is assumed to be a Filter Criteria which is used in `include`
```yaml
itemIs:
approved: false
```
#### Simple List
When a Filter is a list, the list is assumed to be a list of Filter Criteria and used in `include`
```yaml
itemIs:
- approved: false
filtered: false
- is_self: true
```
## Filter Types
There are two types of Filter. Both types have the same "shape" in the configuration with the differences between them being:
* what they are testing on
* what criteria are available to test
### Author Filter
Test the Author of an Activity. See [Schema documentation](https://json-schema.app/view/%23%2Fdefinitions%2FAuthorCriteria?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json) for all possible Author Criteria
#### Mod Actions/Notes Filter
See [Mod Actions/Notes](/docs/subreddit/components/modActions/README.md#mod-action-filter) documentation.
#### Toolbox UserNotes Filter
See [UserNotes](/docs/subreddit/components/userNotes/README.md) documentation
### Item Filter
Test for properties of an Activity:
* [Comment Criteria](https://json-schema.app/view/%23%2Fdefinitions%2FCommentState?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
* [Submission Criteria](https://json-schema.app/view/%23%2Fdefinitions%2FSubmissionState?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
### Subreddit Filter
Test for properties of the Subreddit an Activity belongs to. See [Schema documentation](https://json-schema.app/view/%23%2Fdefinitions%2FSubredditCriteria?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fedge%2Fsrc%2FSchema%2FApp.json)
## Named Filters
**Named Filters** work the same as [**Named Rules**](#named-rules) and [**Named Actions:**](#named-actions)
**Filter Criteria** may be given a `name`. A named **Filter Criteria** can **re-used anywhere in the configuration regardless of location.** This is done by:
* specifying a name on a **Filter Criteria** **once** EX: `name: MyFitlerCriteria`
* using the Filter Criteria's name in place of a Filter Criteria object
```yaml
runs:
- name: MyFirstRun
checks:
- name: MyFirstCheck
kind: submission
itemIs:
- MyFilterCriteria
rules:
...
actions:
...
- name: MySecondCheck
kind: submission
itemIs:
include:
- name: MyFilterCriteria
criteria:
approved: false
rules:
...
actions:
...
```
# Common Patterns
@@ -858,7 +945,7 @@ These conditions can be combined together to evaluate to either true or false us
Most **Rules** have a `window` property somewhere within their configuration. This property defines the range of **Activities** (submission and/or comments) that should be retrieved for checking the criteria of the Rule.
[Full Activities `window` documentation](activitiesWindow.md)
[Full Activities `window` documentation](/docs/subreddit/activitiesWindow.md)
## URL Tokens
@@ -920,7 +1007,7 @@ Some criteria accept an optional **duration** to compare against:
The duration value compares a time range from **now** to `duration value` time in the past.
Refer to [duration values in activity window documentation](activitiesWindow.md#duration) as well as the individual rule/criteria schema to see what this duration is comparing against.
Refer to [duration values in activity window documentation](/docs/subreddit/activitiesWindow.md#duration-values) as well as the individual rule/criteria schema to see what this duration is comparing against.
## Filter Defaults
@@ -954,7 +1041,7 @@ In other words -- Checks will not run if the Author of the Activity being proces
## Flow Control Defaults
See [Flow Control Documentation](advancedConcepts/flowControl.md#default-behaviors)
See [Flow Control Documentation](/docs/subreddit/components/advancedConcepts/flowControl.md#default-behaviors)
# Subreddit-Level Configuration
@@ -964,7 +1051,7 @@ See [Filter Defaults](#filter-defaults) and [Flow Control Defaults](#flow-contro
## Polling
**Polling** is how ContextMod creates [Events](../README.md#event) from new Activities in a Subreddit. CM monitors one or more polling sources and processes any new Activities it discovers.
**Polling** is how ContextMod creates [Events](/docs/README.md#event) from new Activities in a Subreddit. CM monitors one or more polling sources and processes any new Activities it discovers.
### Polling Sources
@@ -1096,7 +1183,7 @@ Re-use will result in less API calls and faster Check times.
PROTIP: You can monitor the re-use of cache in the `Cache` section of your subreddit on the web interface. See the tooltips in that section for a better breakdown of cache statistics.
[Learn more about how Caching works](../operator/caching.md)
[Learn more about how Caching works](/docs/operator/caching.md)
## Partial Configurations
@@ -1151,49 +1238,6 @@ The object contains:
* `path` -- REQUIRED string following rules above
* `ttl` -- OPTIONAL, number of seconds to cache the URL result. Defaults to `WikiTTL`
### Sharing Full Configs as Runs
If the Fragment fetched by CM is a "full config" (including `runs`, `polling`, etc...) that could be used as a valid config for another subreddit then CM will extract and use the **Runs** from that config.
**However, the config must also explicitly allow access for use as a Fragment.** This is to prevent subreddits that share a Bot account from accidentally (or intentionally) gaining access to another subreddit's config with permissions.
#### Sharing
The config that will be shared (accessed at `wiki:botconfig/contextbot|SharingSubreddit`) must have the `sharing` property defined at its top-level. If `sharing` is not defined access will be denied for all subreddits.
```yaml
sharing: false # deny access to all subreddits (default when sharing is not defined)
polling:
- newComm
runs:
# ...
```
```yaml
sharing: true # any subreddit can use this config (reddit account must also be able to access wiki page)
```
```yaml
# when a list is given all subreddit names that match any from the list are ALLOWED to access the config
# list can be regular expressions or case-insensitive strings
sharing:
- mealtimevideos
- videos
- '/Ask.*/i'
```
```yaml
# if `exclude` is used then any subreddit name that is NOT on this list can access the config
# list can be regular expressions or case-insensitive strings
sharing:
exclude:
- mealtimevideos
- videos
- '/Ask.*/i'
```
#### Examples
**Replacing A Rule with a URL Fragment**
@@ -1216,7 +1260,7 @@ runs:
subreddits:
- MyBadSubreddit
window: 7 days
actions:
actions:
- kind: report
content: 'uses freekarma subreddits and bad subreddits'
```
@@ -1251,33 +1295,6 @@ runs:
content: 'uses freekarma subreddits'
```
**Using Another Subreddit's Config**
```yaml
runs:
- `wiki:botconfig/contextbot|SharingSubreddit`
- name: MySubredditSpecificRun
checks:
- name: Free Karma Alert
description: Check if author has posted in 'freekarma' subreddits
kind: submission
rules:
- 'wiki:freeKarmaFrag'
actions:
- kind: report
content: 'uses freekarma subreddits'
```
In `r/SharingSubreddit`:
```yaml
sharing: true
runs:
- name: ARun
# ...
```
# Subreddit-Ready Examples
Refer to the [Subreddit Cookbook Examples](cookbook) section to find ready-to-use configurations for common scenarios (spam, freekarma blocking, etc...). This is also a good place to familiarize yourself with what complete configurations look like.
Refer to the [Subreddit-Ready Examples](/docs/subreddit/components/subredditReady) section to find ready-to-use configurations for common scenarios (spam, freekarma blocking, etc...). This is also a good place to familiarize yourself with what complete configurations look like.

View File

@@ -1,10 +1,3 @@
---
parent: Subreddit Configuration
has_toc: false
---
# Flow Control
Context Mod's behavior after a **Check** has been processed can be configured by a user. This allows a subreddit to control exactly what Runs/Checks will be processed based on the outcome (triggered or not) of a Check.
# Table of Contents
@@ -28,7 +21,7 @@ Context Mod's behavior after a **Check** has been processed can be configured by
When a Check is finished processing it can be in one of two states:
* **Triggered** -- The **Rules** defined in the Check were **triggered** which caused the **Actions** for the Check to be run
* **Failure** -- The **Rules** defined in the check were **not triggered**, based on the conditions that were set (either from the [Check condition](../README.md#Checks) or Rule Sets, and no **Actions** were run
* **Failure** -- The **Rules** defined in the check were **not triggered**, based on the conditions that were set (either from the [Check condition](/docs/README.md#Checks) or [Rule Sets](/docs/subreddit/components/advancedConcepts/README.md#Rule-Sets)), and no **Actions** were run
The behavior CM follows is based on which state it is in. The behavior can be specified **by one or both** of these **state properties** on the Check configuration:

View File

@@ -31,7 +31,7 @@
// if the nested rules pass the condition then the Rule Set triggers the Check
//
// AND = all nested rules must be triggered to make the Rule Set trigger
// OR = any of the nested Rules will be the Rule Set trigger
// AND = any of the nested Rules will be the Rule Set trigger
"condition": "AND",
// in this check we use an Attribution >10% on ONLY submissions, which is a lower requirement then the above attribution rule
// and combine it with a History rule looking for low comment engagement

View File

@@ -22,7 +22,7 @@ runs:
# if the nested rules pass the condition then the Rule Set triggers the Check
#
# AND = all nested rules must be triggered to make the Rule Set trigger
# OR = any of the nested Rules will be the Rule Set trigger
# AND = any of the nested Rules will be the Rule Set trigger
- condition: AND
# in this check we use an Attribution >10% on ONLY submissions, which is a lower requirement then the above attribution rule
# and combine it with a History rule looking for low comment engagement

View File

@@ -0,0 +1,14 @@
# Attribution
The **Attribution** rule will aggregate an Author's content Attribution (youtube channels, twitter, website domains, etc.) and can check on their totals or percentages of all Activities over a time period:
* Total # of attributions
* As percentage of all Activity or only Submissions
* Look at all domains or only media (youtube, vimeo, etc.)
* Include self posts (by reddit domain) or not
Consult the [schema](https://json-schema.app/view/%23/%23%2Fdefinitions%2FCheckJson/%23%2Fdefinitions%2FAttributionJSONConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) for a complete reference of the rule's properties.
### Examples
* Self Promotion as percentage of all Activities [YAML](/docs/subreddit/componentscomponents/attribution/redditSelfPromoAll.yaml) | [JSON](/docs/subreddit/componentscomponents/attribution/redditSelfPromoAll.json5) - Check if Author is submitting much more than they comment.
* Self Promotion as percentage of Submissions [YAML](/docs/subreddit/components/attribution/redditSelfPromoSubmissionsOnly.yaml) | [JSON](/docs/examplesm/attribution/redditSelfPromoSubmissionsOnly.json5) - Check if any of Author's aggregated submission origins are >10% of their submissions

View File

@@ -1,8 +1,3 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Author
## Rule
@@ -14,7 +9,7 @@ The **Author** rule triggers if any [AuthorCriteria](https://json-schema.app/vie
* author's subreddit flair text
* author's subreddit flair css
* author's subreddit mod status
* [Toolbox User Notes](../userNotes)
* [Toolbox User Notes](/docs/subreddit/componentscomponents/userNotes)
The Author **Rule** is best used in conjunction with other Rules to short-circuit a Check based on who the Author is. It is easier to use a Rule to do this then to write **author filters** for every Rule (and makes Rules more re-useable).
@@ -23,10 +18,10 @@ Consult the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FAuthorRule
### Examples
* Basic examples
* Flair new user Submission [YAML](flairNewUserSubmission.yaml) | [JSON](flairNewUserSubmission.json5) - If the Author does not have the `vet` flair then flair the Submission with `New User`
* Flair vetted user Submission [YAML](flairNewUserSubmission.yaml) | [JSON](flairNewUserSubmission.json5) - If the Author does have the `vet` flair then flair the Submission with `Vetted`
* Flair new user Submission [YAML](/docs/subreddit/componentscomponents/author/flairNewUserSubmission.yaml) | [JSON](/docs/subreddit/componentscomponents/author/flairNewUserSubmission.json5) - If the Author does not have the `vet` flair then flair the Submission with `New User`
* Flair vetted user Submission [YAML](/docs/subreddit/componentscomponents/author/flairNewUserSubmission.yaml) | [JSON](/docs/subreddit/componentscomponents/author/flairNewUserSubmission.json5) - If the Author does have the `vet` flair then flair the Submission with `Vetted`
* Used with other Rules
* Ignore vetted user [YAML](flairNewUserSubmission.yaml) | [JSON](flairNewUserSubmission.json5) - Short-circuit the Check if the Author has the `vet` flair
* Ignore vetted user [YAML](/docs/subreddit/componentscomponents/author/flairNewUserSubmission.yaml) | [JSON](/docs/subreddit/componentscomponents/author/flairNewUserSubmission.json5) - Short-circuit the Check if the Author has the `vet` flair
## Filter
@@ -40,7 +35,7 @@ All **Rules** and **Checks** have an optional `authorIs` property that takes an
### Examples
* Skip recent activity check based on author [YAML](authorFilter.yaml) | [JSON](authorFilter.json5) - Skip a Recent Activity check for a set of subreddits if the Author of the Submission has any set of flairs.
* Skip recent activity check based on author [YAML](/docs/subreddit/componentscomponents/author/authorFilter.yaml) | [JSON](/docs/subreddit/componentscomponents/author/authorFilter.json5) - Skip a Recent Activity check for a set of subreddits if the Author of the Submission has any set of flairs.
## Flair users and submissions
@@ -50,4 +45,4 @@ Consult [User Flair schema](https://json-schema.app/view/%23%2Fdefinitions%2FUse
### Examples
* OnlyFans submissions [YAML](onlyfansFlair.yaml) | [JSON](onlyfansFlair.json5) - Check whether submitter has typical OF keywords in their profile and flair both author + submission accordingly.
* OnlyFans submissions [YAML](/docs/subreddit/componentscomponents/author/onlyfansFlair.yaml) | [JSON](/docs/subreddit/componentscomponents/author/onlyfansFlair.json5) - Check whether submitter has typical OF keywords in their profile and flair both author + submission accordingly.

View File

@@ -0,0 +1,14 @@
# History
The **History** rule can check an Author's submission/comment statistics over a time period:
* Submission total or percentage of All Activity
* Comment total or percentage of all Activity
* Comments made as OP (commented in their own Submission) total or percentage of all Comments
Consult the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FHistoryJSONConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) for a complete reference of the rule's properties.
### Examples
* Low Comment Engagement [YAML](/docs/subreddit/componentscomponents/history/lowEngagement.yaml) | [JSON](/docs/subreddit/componentscomponents/history/lowEngagement.json5) - Check if Author is submitting much more than they comment.
* OP Comment Engagement [YAML](/docs/subreddit/componentscomponents/history/opOnlyEngagement.yaml) | [JSON](/docs/subreddit/componentscomponents/history/opOnlyEngagement.json5) - Check if Author is mostly engaging only in their own content

View File

@@ -1,10 +1,3 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Mod Actions
# Table of Contents
* [Overview](#overview)
@@ -16,9 +9,9 @@ parent: In Depth
# Overview
[Mod Notes](https://www.reddit.com/r/modnews/comments/t8vafc/announcing_mod_notes/) is a feature for New Reddit that allow moderators to add short, categorizable notes to Users of their subreddit, optionally associating te note with a submission/comment the User made. They are inspired by [Toolbox User Notes](https://www.reddit.com/r/toolbox/wiki/docs/usernotes) which are also [supported by ContextMod.](../userNotes) Reddit's **Mod Notes** also combine [Moderation Log](https://mods.reddithelp.com/hc/en-us/articles/360022402312-Moderation-Log) actions (**Mod Actions**) for the selected User alongside moderator notes, enabling a full "overview" of moderator interactions with a User in their subreddit.
[Mod Notes](https://www.reddit.com/r/modnews/comments/t8vafc/announcing_mod_notes/) is a feature for New Reddit that allow moderators to add short, categorizable notes to Users of their subreddit, optionally associating te note with a submission/comment the User made. They are inspired by [Toolbox User Notes](https://www.reddit.com/r/toolbox/wiki/docs/usernotes) which are also [supported by ContextMod.](/docs/subreddit/components/userNotes) Reddit's **Mod Notes** also combine [Moderation Log](https://mods.reddithelp.com/hc/en-us/articles/360022402312-Moderation-Log) actions (**Mod Actions**) for the selected User alongside moderator notes, enabling a full "overview" of moderator interactions with a User in their subreddit.
ContextMod supports adding **Mod Notes** to an Author using an [Action](../../README.md#mod-note) and using **Mod Actions/Mod Notes** as a criteria in an [Author Filter](../../README.md#author-filter)
ContextMod supports adding **Mod Notes** to an Author using an [Action](/docs/subreddit/components/README.md#mod-note) and using **Mod Actions/Mod Notes** as a criteria in an [Author Filter](/docs/subreddit/components/README.md#author-filter)
# Mod Note Action
@@ -44,7 +37,7 @@ actions:
# Mod Action Filter
ContextMod can use **Mod Actions** (from moderation log) and **Mod Notes** in an [Author Filter](../../../README.md#author-filter).
ContextMod can use **Mod Actions** (from moderation log) and **Mod Notes** in an [Author Filter](/docs/subreddit/components/README.md#author-filter).
## API Usage
@@ -68,15 +61,15 @@ Mod Action Filtering Used
In general,**do not** use Mod Actions in a Filter if:
* The filter is on a [**Comment** Check](../../README.md#checks) and your subreddit has a high volume of Comments
* The filter is on a [Run](../../README.md#runs) and your subreddit has a high volume of Activities
* The filter is on a [**Comment** Check](/docs/subreddit/components/README.md#checks) and your subreddit has a high volume of Comments
* The filter is on a [Run](/docs/subreddit/components/README.md#runs) and your subreddit has a high volume of Activities
If you need Mod Notes-like functionality for a high volume subreddit consider using [Toolbox UserNotes](../userNotes) instead.
If you need Mod Notes-like functionality for a high volume subreddit consider using [Toolbox UserNotes](/docs/subreddit/components/userNotes) instead.
In general, **do** use Mod Actions in a Filter if:
* The filter is on a [**Submission** Check](../../README.md#checks)
* The filter is part of an [Author **Rule**](../../README.md#author) that is processed as **late as possible in the rule order for a Check**
* The filter is on a [**Submission** Check](/docs/subreddit/components/README.md#checks)
* The filter is part of an [Author **Rule**](/docs/subreddit/components/README.md#author) that is processed as **late as possible in the rule order for a Check**
* Your subreddit has a low volume of Activities (less than 100 combined submissions/comments in a 10 minute period, for example)
* The filter is on an Action

View File

@@ -0,0 +1,31 @@
# Recent Activity
Given a list subreddit criteria, the **Recent Activity** rule finds Activities matching those criteria in the Author's history over [window](#activities-window) and then allows for comparing different facets of the results.
Subreddit criteria can be:
* names
* regular expression for names
* [Subreddit meta properties](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubmissionCheckJson/%23%2Fdefinitions%2FRecentActivityRuleJSONConfig/%23%2Fdefinitions%2FActivityThreshold/%23%2Fdefinitions%2FSubredditState?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Freddit-context-bot%2Fmaster%2Fsrc%2FSchema%2FApp.json) like NSFW, description, is user profile, is author's profile, etc...
Facets available to compare from analyzed history:
* number of activities found EX `> 3` => more than 3 activities found
* aggregated karma from activities EX `> 50` => more than 50 combined karma from found activities
* number of subreddits found EX `> 5` => more than 5 distinct subreddits matching subreddit criteria found
The above can also be expressed as a percentage instead of number IE "more than 10% of activities in author history come from subreddits matching criteria"
The search can also be modified in a number of ways:
* Filter found activities using an [Item Filter](#item)
* Only return activities that match the Activity from the Event being processed
* Using image detection (pixel or perceptual hash matching)
* Only return certain types of activities (only submission or only comments)
Consult the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FRecentActivityRuleJSONConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fcontext-mod%2Fmaster%2Fsrc%2FSchema%2FApp.json) for a complete reference of the rule's properties.
### Examples
* Free Karma Subreddits [YAML](/docs/subreddit/componentscomponents/recentActivity/freeKarma.yaml) | [JSON](/docs/subreddit/componentscomponents/recentActivity/freeKarma.json5) - Check if the Author has recently posted in any "free karma" subreddits
* Submission in Free Karma Subreddits [YAML](/docs/subreddit/componentscomponents/recentActivity/freeKarmaOnSubmission.yaml) | [JSON](/docs/subreddit/componentscomponents/recentActivity/freeKarmaOnSubmission.json5) - Check if the Author has posted the Submission this check is running on in any "free karma" subreddits recently

View File

@@ -0,0 +1,22 @@
The **Regex** rule matches on text content from a comment or submission in the same way automod uses regex. The rule, however, provides additional functionality automod does not:
* Can set the **number** of matches that trigger the rule (`matchThreshold`)
Which can then be used in conjunction with a [`window`](https://github.com/FoxxMD/context-mod/blob/master/docs/activitiesWindow.md) to match against activities from the history of the Author of the Activity being checked (including the Activity being checked):
* Can set the **number of Activities** that meet the `matchThreshold` to trigger the rule (`activityMatchThreshold`)
* Can set the **number of total matches** across all Activities to trigger the rule (`totalMatchThreshold`)
* Can set the **type of Activities** to check (`lookAt`)
* When an Activity is a Submission can **specify which parts of the Submission to match against** IE title, body, and/or url (`testOn`)
### Examples
* Trigger if regex matches against the current activity - [YAML](/docs/subreddit/componentscomponents/regex/matchAnyCurrentActivity.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/matchAnyCurrentActivity.json5)
* Trigger if regex matches 5 times against the current activity - [YAML](/docs/subreddit/componentscomponents/regex/matchThresholdCurrentActivity.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/matchThresholdCurrentActivity.json5)
* Trigger if regex matches against any part of a Submission - [YAML](/docs/subreddit/componentscomponents/regex/matchSubmissionParts.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/matchSubmissionParts.json5)
* Trigger if regex matches any of Author's last 10 activities - [YAML](/docs/subreddit/componentscomponents/regex/matchHistoryActivity.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/matchHistoryActivity.json5)
* Trigger if regex matches at least 3 of Author's last 10 activities - [YAML](/docs/subreddit/componentscomponents/regex/matchActivityThresholdHistory.json5) | [JSON](/docs/subreddit/componentscomponents/regex/matchActivityThresholdHistory.json5)
* Trigger if there are 5 regex matches in the Author's last 10 activities - [YAML](/docs/subreddit/componentscomponents/regex/matchTotalHistoryActivity.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/matchTotalHistoryActivity.json5)
* Trigger if there are 5 regex matches in the Author's last 10 comments - [YAML](/docs/subreddit/componentscomponents/regex/matchSubsetHistoryActivity.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/matchSubsetHistoryActivity.json5)
* Remove comments that are spamming discord links - [YAML](/docs/subreddit/componentscomponents/regex/removeDiscordSpam.yaml) | [JSON](/docs/subreddit/componentscomponents/regex/removeDiscordSpam.json5)
* Differs from just using automod because this config can allow one-off/organic links from users who DO NOT spam discord links but will still remove the comment if the user is spamming them

Some files were not shown because too many files have changed in this diff Show More