Compare commits

..

122 Commits

Author SHA1 Message Date
FoxxMD
a891e2d42b Merge branch 'edge' 2022-11-29 09:54:39 -05:00
FoxxMD
ef372e531e fix(database): Prevent usage of LIMIT in session storage driver when db backend is mysql/mariadb
Related to freshgiammi-lab/connect-typeorm#8

Closes #128
2022-11-29 09:47:55 -05:00
FoxxMD
fde2836208 chore: remove comments about wrong endpoints
At some point maybe this was fixed by reddit silently?
2022-11-28 14:36:33 -05:00
Matt Foxx
021dd5b0c5 Merge pull request #130 from rysie/bug/selecftlair-fix 2022-11-28 14:35:39 -05:00
Marcin Macinski
5bd38d367a assignFlair doesn't work with flair_template_id 2022-11-25 17:13:49 +01:00
FoxxMD
e79779d980 feat: Implement templating for flair actions 2022-11-21 11:43:34 -05:00
FoxxMD
b094b72d4a docs: Update docker compose instructions
* Specify docker-compose minimum version
* Change commands to use new syntax
2022-11-21 11:29:14 -05:00
FoxxMD
d90e88360d feat: Add some author properties for templating 2022-11-17 13:16:10 -05:00
FoxxMD
9031f7fec8 refactor(polling): Improve resilience for polling source parsing
* Replace hard-coded polling sources with string constants
* Implement string to PollOn parsing which is case-insensitive and forgives mispelling
* Check that manager specifies only one of each polling source type when build config
2022-11-17 12:03:55 -05:00
FoxxMD
0a2b13e4c4 fix: Fix including self activities in Recent Activity without filtering
* Consolidate ACID check for author history results into authorActivities function so it can be used everywhere
* Remove self check in Recent Activity and used consolidated functionality so that filtering still occurs on current activity
2022-11-16 10:18:37 -05:00
FoxxMD
5183747219 feat(docs): Improve jekyll dependencies to speed up docker image build 2022-11-15 13:58:35 -05:00
FoxxMD
718f81b921 feat(docs): Generate docs on startup or in docker build
* Generate docs if none found on Web client startup
* Add "Docs" link to local docs index
* Add working implementation of building docs in docker image
2022-11-15 13:07:40 -05:00
FoxxMD
154603328c chore: Exclude jekyll generated files from typescript compiler 2022-11-15 10:15:16 -05:00
FoxxMD
95c65304d4 Merge branch 'edge' 2022-11-15 09:36:42 -05:00
FoxxMD
4041ea5bb5 docs: Revert to using docs folder only
* Using project dir copies too much to _site directory and causes TS issues
* In order to keep "home" page in generated docs need to duplicate project README (unfortunately)
2022-11-15 09:36:29 -05:00
FoxxMD
d765a639dc Merge branch 'edge' 2022-11-14 14:43:40 -05:00
FoxxMD
981591a5fa docs: Add more filters documentation 2022-11-14 14:42:56 -05:00
FoxxMD
70a04a0db6 Merge branch 'edge' 2022-11-14 13:29:00 -05:00
FoxxMD
999329c6ce docs: Add missing mermaid version 2022-11-14 13:28:44 -05:00
FoxxMD
75fcfece84 Merge branch 'edge' 2022-11-14 12:22:27 -05:00
FoxxMD
d7cf15dcc1 docs: Fix links in main readme 2022-11-14 12:21:57 -05:00
FoxxMD
4b26b7d371 Merge branch 'edge' 2022-11-14 12:10:48 -05:00
FoxxMD
f58430c615 docs: Add doc site development documentation 2022-11-14 11:59:02 -05:00
FoxxMD
8e18afbda9 chore: Add excluded folders for idea 2022-11-14 11:54:23 -05:00
FoxxMD
b3b0d92f2a docs: Use project README as index and fix more links 2022-11-14 11:54:07 -05:00
FoxxMD
34ee5da082 docs: Fix broken link 2022-11-14 11:33:05 -05:00
FoxxMD
ba8ad100bc docs: Fix detail expansion blocks
https://github.com/just-the-docs/just-the-docs/issues/246#issuecomment-643783307
2022-11-14 10:46:40 -05:00
FoxxMD
3d26fd2e3b Merge branch 'edge' 2022-11-09 15:30:48 -05:00
FoxxMD
4b6f66499a docs: Fix relative links 2022-11-09 15:19:47 -05:00
FoxxMD
9a08df1990 testing relative links in plain docs with parent 2022-11-09 14:47:03 -05:00
FoxxMD
1f3aa8e732 testing relative links in plain docs 2022-11-09 14:44:53 -05:00
FoxxMD
ec98d8f629 docs: Initial implementation of just-the-docs 2022-11-09 14:22:53 -05:00
FoxxMD
2d8b7f7b86 fix: Modify reddit entity parsing regex to allow subreddit names that have been replaced with placeholders
Placeholder naming broke "normal" subreddit naming convention
2022-11-08 09:47:20 -05:00
FoxxMD
b9f85814d4 Merge branch 'dockerCompose' into edge 2022-11-01 16:41:14 -04:00
FoxxMD
e11a1d2a52 feat: Add full docker-compose support and documentation
* Annotated docker-compose file
* simplified CM config.yaml for docker-compose "base"
* instructions for usage in installation docs
2022-11-01 16:41:00 -04:00
FoxxMD
74925fa8d8 Merge branch 'edge' 2022-11-01 09:23:38 -04:00
FoxxMD
43bfa3ca51 fix(ui): Add workaround for removal reason copy-to-clipboard when in unsecure context 2022-10-31 11:30:17 -04:00
FoxxMD
0127cbfd0f docs: Add cookbook recipe for monitoring popular submissions 2022-10-27 15:40:53 -04:00
FoxxMD
59d31bde84 feat(comment): Implement commenting as subreddit 2022-10-27 14:29:05 -04:00
FoxxMD
17ae7fa295 refactor(modnotes): Encapsulate filtering functionality in modnote class for future testing 2022-10-27 11:36:12 -04:00
FoxxMD
bf074487ff fix: Fix how submission/comment snoowrap entities are generated from reddit thing ids 2022-10-27 11:34:12 -04:00
FoxxMD
85e786d248 fix(filter): Re-add missing modaction filtering improvements
They were removed by a merge somewhere??
2022-10-27 09:56:45 -04:00
FoxxMD
641a7fbd63 fix(filter): Fix usernote cutoff date comparison 2022-10-27 09:50:05 -04:00
FoxxMD
0278a4d673 feat(filter): Improve building filters from config
* Fix ignoring of filters when they are plain objects
* Fix default filter merging behavior to account for "new" filter structure (named criteria)
* Add tests for building/merging filters
2022-10-26 14:43:44 -04:00
FoxxMD
d318286507 fix(cache): Fix more memory provider cache object reconstruction issues #123
Same issues as a949a4ed10 -- memory provider stores objects in memory (no serialization) so need to check for object instance before trying to reconstruct
2022-10-26 09:48:41 -04:00
FoxxMD
36221705fa fix(filter): Fix filtered usernote assignment when search type is current and no notes exist
Addresses #123
2022-10-26 09:27:15 -04:00
FoxxMD
fdc0ccf4c8 fix(mhs): Fix examples missing criteria property 2022-10-25 16:51:47 -04:00
FoxxMD
a949a4ed10 fix(cache): Fix pre activities being wrongly reconstructed when retrieved from memory provider cache
Thanks @CryptoMaximalist for reporting the bug and providing logs!
2022-10-25 15:32:47 -04:00
FoxxMD
d67283a923 feat(filter): Add same regex/matching functionality for author flair filtering as item has 2022-10-24 13:02:27 -04:00
FoxxMD
21b2182ef0 fix(filter): Re-add missing item is criteria to filter test
Somehow got removed during refactor! Oops
2022-10-24 11:51:47 -04:00
FoxxMD
fcfb037d6c feat(docs): Add more cookbook recipies 2022-10-20 12:33:20 -04:00
FoxxMD
8c3601a4cf refactor(docs): Improve CM examples by using a "cookbook"
* Better instructions on how to use configs
* Remove json examples since everything else in docs is yaml
2022-10-20 10:49:17 -04:00
FoxxMD
cfc96b6c82 Merge branch 'sharedBaseConfig' into edge
# Conflicts:
#	src/Subreddit/UserNotes.ts
2022-10-20 09:37:01 -04:00
FoxxMD
239d173ffd feat(config): Implement ACL for full config sharing 2022-10-20 09:35:26 -04:00
FoxxMD
fda6090ddd feat(config): Refactor manager config updates to check hydrated structure
Instead of checking wiki revision, check hydrated (with config fragments) config hash against last good config hash
2022-10-19 16:19:39 -04:00
FoxxMD
d23f87ba60 feat(config): Add config fragments to shared cache 2022-10-19 16:19:29 -04:00
FoxxMD
2941386955 feat(cache): Add force/shared options for getting content/wiki/url results from subreddit resources
* Also refactor Manager to use subreddit resources for getting wiki page (DRY)
2022-10-19 15:15:58 -04:00
FoxxMD
b2b924c01d feat(cache): Add default prefix and shared option for interacting with cache
Enables getting cache KVs from shared *always* based on logic flow
2022-10-19 15:15:01 -04:00
FoxxMD
ee20ba786b refactor: Move cache key prefix into CMCache
* Makes adding prefix cache provider agnostic
* Prepares for #115
2022-10-19 14:33:05 -04:00
FoxxMD
f71933b9b9 refactor: Improve reuseability of SubredditResources
* Extract cache related functions into own class and encapsulate pruning/key search there as well
* Refactor SubredditStates to be "re-init"-able if state frequency changes
* Simplify and SubredditSource init and configuration functionality so that class is only created once and then reconfigured if major settings change
  * Only reinstantiates stats or cache class based on setting changes
* Remove obsolete maxActionedEvents from operator/subreddit config (from pre-db code)
2022-10-19 14:13:23 -04:00
FoxxMD
e6246188ad refactor: Extract stat-related functionality from SubredditResources into its own class 2022-10-19 11:23:24 -04:00
FoxxMD
bfd5ba7816 refactor: Consolidate ttl values into well-defined object 2022-10-19 10:02:44 -04:00
FoxxMD
fd5488376a docs: Add template variable examples for most rules #121 2022-10-18 13:18:12 -04:00
FoxxMD
6c8ea66fcc docs: Typo fix 2022-10-18 11:07:19 -04:00
FoxxMD
d02d70ded3 Merge branch 'edge' 2022-10-17 15:33:15 -04:00
FoxxMD
acbb9a8626 feat(usernote): Improve usernote filtering functionality
Same as modActions...

* Add `referencesCurrentActivity` boolean to filter by notes associated with current activity
* Add `note` string property to filter by note content (string or regular expression)
* Replace `allowDuplicates` with `existingNoteCheck` on UserNoteAction to allow for more granular note control on action
2022-10-17 15:32:47 -04:00
FoxxMD
122d5fb2af docs: Fix malformed URLs
Fixes #114
2022-10-17 14:16:34 -04:00
FoxxMD
cd8ccffa20 feat(config): Enable pulling run fragments from root subreddit config
* Refactor config fragment validation into parsing function
* Check for `runs` in config fragment
2022-10-17 13:52:12 -04:00
FoxxMD
8695058064 refactor: Seperate subreddit resources from bot resource manager 2022-10-17 13:52:09 -04:00
FoxxMD
1271eee4c5 Improvements 2022-10-14 11:18:33 -04:00
FoxxMD
59f935ce46 Barebones docker-compose 2022-10-11 09:56:08 -04:00
FoxxMD
80f83bf84b Merge branch 'edge' 2022-10-05 08:57:04 -04:00
FoxxMD
7933f77764 Merge branch 'edge' 2022-10-05 08:55:39 -04:00
FoxxMD
3bcc3d78e8 Merge branch 'edge' 2022-09-28 09:28:38 -04:00
FoxxMD
296f1c8dee Merge branch 'edge' 2022-09-14 15:30:27 -04:00
FoxxMD
e32ac60db5 Merge branch 'edge' 2022-09-14 15:29:13 -04:00
FoxxMD
859680dca8 Merge branch 'edge' 2022-09-01 09:03:27 -04:00
FoxxMD
ffa1e423b2 Merge branch 'edge' 2022-08-23 09:49:23 -04:00
FoxxMD
09cb08492c Merge branch 'edge' 2022-08-23 09:47:59 -04:00
FoxxMD
d9ab81ab8c Merge branch 'edge' 2022-07-27 09:19:30 -04:00
FoxxMD
98691bd19c Merge branch 'edge' 2022-07-15 09:27:22 -04:00
FoxxMD
8123c34463 Merge branch 'edge' 2022-06-21 16:13:54 -04:00
FoxxMD
3292d011fa Merge branch 'edge' 2022-06-21 10:03:14 -04:00
FoxxMD
661a0ae440 Merge branch 'edge' 2022-05-26 09:59:32 -04:00
FoxxMD
05f477b67d Merge branch 'edge' 2022-05-12 12:27:51 -04:00
Matt Foxx
1317a5916c Merge pull request #86 from wchristian/example_fix
trying to use names key in authorfilter causes config parse failure
2022-04-05 16:55:56 -04:00
Christian Walde
e9135ec1ef trying to use names key in authorfilter causes config parse failure 2022-04-05 13:49:41 +02:00
FoxxMD
e58a0f8f21 Merge branch 'edge' 2022-03-14 12:39:05 -04:00
FoxxMD
f7cebc013b Merge branch 'edge' 2022-03-08 09:48:06 -05:00
FoxxMD
ae8e11feb4 Merge branch 'edge' 2022-02-22 11:11:46 -05:00
FoxxMD
e07b8cc291 Merge branch 'edge' 2022-02-18 11:58:28 -05:00
FoxxMD
fc51928054 Merge branch 'edge' 2022-02-02 16:59:56 -05:00
FoxxMD
e2590e50f8 Merge branch 'edge' 2022-01-28 17:27:51 -05:00
FoxxMD
aaed0d3419 Merge branch 'edge' 2022-01-21 10:46:11 -05:00
FoxxMD
bc7eff8928 Merge branch 'edge' 2022-01-14 15:27:09 -05:00
FoxxMD
d6954533a0 Merge branch 'edge' 2022-01-10 12:32:14 -05:00
FoxxMD
ba53233640 Merge branch 'edge' 2022-01-07 09:31:14 -05:00
FoxxMD
1ac7ad4724 Merge branch 'edge' 2022-01-03 16:35:01 -05:00
FoxxMD
2a282a0d6f Merge branch 'edge' 2021-12-21 09:35:21 -05:00
FoxxMD
fd5a92758d Merge branch 'edge' 2021-11-28 19:43:20 -05:00
FoxxMD
39daa11f2d Merge branch 'edge' 2021-11-15 12:53:28 -05:00
FoxxMD
dac6541e28 Merge branch 'edge' 2021-11-01 16:12:43 -04:00
FoxxMD
97906281e6 Merge branch 'edge' 2021-11-01 14:55:10 -04:00
FoxxMD
487f13f704 Merge branch 'edge' 2021-10-12 11:56:51 -04:00
FoxxMD
631e21452c Merge branch 'edge' 2021-09-28 16:36:13 -04:00
FoxxMD
4f3685a1f5 Merge branch 'edge' 2021-09-21 15:18:38 -04:00
FoxxMD
d2d945db2c Merge branch 'edge' 2021-09-21 15:08:28 -04:00
FoxxMD
910f7f79ef Merge branch 'edge' 2021-09-20 10:54:32 -04:00
FoxxMD
a11b667d5e Merge branch 'edge' 2021-09-13 16:16:55 -04:00
FoxxMD
885e3fa765 Merge branch 'edge' 2021-08-26 16:04:01 -04:00
FoxxMD
465c3c9acf Merge branch 'edge' 2021-08-20 15:02:24 -04:00
FoxxMD
161251a943 Merge branch 'edge' 2021-08-05 14:40:06 -04:00
FoxxMD
ce4cb96d9a Merge branch 'edge' 2021-08-03 23:39:14 -04:00
FoxxMD
c317f95953 Merge branch 'edge' 2021-08-03 22:43:02 -04:00
FoxxMD
d0e0515990 Merge branch 'edge' 2021-08-02 15:44:57 -04:00
FoxxMD
cdddd8de48 Merge branch 'edge' 2021-07-30 18:17:38 -04:00
FoxxMD
f598215d88 Merge branch 'edge' 2021-07-30 14:46:51 -04:00
FoxxMD
0c7218571c Merge branch 'edge' 2021-07-29 13:25:16 -04:00
FoxxMD
acc7c49e0e Merge branch 'edge' 2021-07-29 11:27:42 -04:00
FoxxMD
01839512d5 Merge branch 'edge' 2021-07-29 11:14:33 -04:00
FoxxMD
4680640b0c Merge branch 'develop' 2021-07-28 16:58:36 -04:00
Matt Foxx
b813ebdd96 Create dockerhub.yml 2021-07-28 11:27:04 -04:00
175 changed files with 5971 additions and 3003 deletions

View File

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

53
.github/workflows/pages.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
# 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

12
.gitignore vendored
View File

@@ -381,6 +381,17 @@ 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
@@ -396,3 +407,4 @@ dist
!docs/**/*.json5
!docs/**/*.yaml
!docs/**/*.json
!docker/config/**

View File

@@ -9,6 +9,9 @@
<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" />

2
.nvmrc
View File

@@ -1 +1 @@
16.18.0
16.14.2

View File

@@ -96,11 +96,26 @@ 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

19
Gemfile Normal file
View File

@@ -0,0 +1,19 @@
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

90
Gemfile.lock Normal file
View File

@@ -0,0 +1,90 @@
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,9 +1,13 @@
---
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** (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**](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.**
@@ -16,27 +20,27 @@ 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/subreddit/gettingStarted.md#setup-wiki-page) (like automoderator)
* Complete bot **autonomy**. YAML config is [stored in your subreddit's wiki](/docs/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](/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...)
* [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...)
* Event notification via Discord
* [**Web interface**](#web-ui-and-screenshots) for monitoring, administration, and oauth bot authentication
* [**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
* [Guest Access](/docs/subreddit/README.md#guest-access) enables collaboration and easier setup by allowing temporary access
* [Toxic content prediction](/docs/subreddit/components/README.md#moderatehatespeechcom-predictions) using [moderatehatespeech.com](https://moderatehatespeech.com) machine learning model
* [**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
Feature highlights for **Developers and Hosting (Operators):**
* [Server/client architecture](/docs/serverClientArchitecture.md)
* [Server/client architecture](/docs/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
@@ -44,7 +48,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 support](/docs/operator/installation.md#docker-recommended)
* [Docker container](/docs/operator/installation.md#docker-recommended) and [docker-compose](/docs/operator/installation.md#docker-compose) support
* 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)
@@ -59,7 +63,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/components/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-configuration/README.md#checks) to determine what to do with the **Activity** from that Event. Each **Check** consists of :
#### Kind
@@ -67,11 +71,11 @@ Is this check for a submission or comment?
#### Rules
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**
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**
#### Actions
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.
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.
___
@@ -95,14 +99,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/subreddit/gettingStarted.md)
See the [Moderator's Getting Started Guide](/docs/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](/docs/operator/configuration.md) guide
* For **moderators** consult the [app schema and examples folder](/docs/README.md#configuration-and-usage)
* For **moderators** consult the [Subreddit Configuration Docs](/docs/subreddit-configuration/README.md)
[**Check the full docs for in-depth explanations of all concepts and examples**](/docs)

45
_config.yml Normal file
View File

@@ -0,0 +1,45 @@
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

62
docker-compose.yml Normal file
View File

@@ -0,0 +1,62 @@
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

@@ -0,0 +1,43 @@
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,4 +1,8 @@
# Documentation
---
title: Overview
permalink: /overview.html
nav_order: 2
---
# Table of Contents
@@ -22,8 +26,8 @@
Review **at least** the **How It Works** and **Concepts** below, then:
* 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
* 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
## How It Works
@@ -33,10 +37,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>
<details markdown="block">
<summary>Diagram</summary>
![Flow Diagram](/docs/images/diagram-highlevel.jpg)
![Flow Diagram](images/diagram-highlevel.jpg)
</details>
@@ -92,7 +96,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](/docs/subreddit/components/README.md#runs)
[Full Documentation for Runs](subreddit-configuration/README.md#runs)
### Checks
@@ -105,7 +109,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](/docs/subreddit/components/README.md#checks)
[Full Documentation for Checks](subreddit-configuration/README.md#checks)
### Rule
@@ -113,11 +117,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](/docs/subreddit/components/README.md#rules)
[Full Documentation for Rules](subreddit-configuration/README.md#rules)
#### Available Rules
All available rules can be found in the [components documentation](/docs/subreddit/components/README.md#rules)
All available rules can be found in the [components documentation](subreddit-configuration/README.md#rules)
### Rule Set
@@ -127,7 +131,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](/docs/subreddit/components/README.md#rule-sets)
[Rule Sets Documentation](subreddit-configuration/README.md#rule-sets)
### Action
@@ -135,7 +139,7 @@ An **Action** is some action the bot can take against the checked Activity (comm
#### Available Actions
[Available Actions Documentation](/docs/subreddit/components/README.md#list-of-actions)
[Available Actions Documentation](subreddit-configuration/README.md#list-of-actions)
### Filters
@@ -146,14 +150,14 @@ 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](/docs/subreddit/components/README.md#filters)
[Full Documentation for Filters](subreddit-configuration/README.md#filters)
## Configuration And Usage
* For **Operator/Bot maintainers** see **[Operation Guide](/docs/operator/README.md)**
* For **Operator/Bot maintainers** see **[Operation Guide](operator/README.md)**
* For **Moderators**
* Start with the [Subreddit/Moderator docs](/docs/subreddit/README.md) or [Moderator Getting Started guide](/docs/subreddit/gettingStarted.md)
* Refer to the [Subreddit Components Documentation](/docs/subreddit/components) or the [subreddit-ready examples](/docs/subreddit/components/subredditReady)
* 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)
* 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,12 +1,36 @@
TODO add more development sections...
---
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)
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:
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
@@ -28,7 +52,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](/docs/operator/operatorConfiguration.md) define a proxy for snoowrap at the top-level:
In your [operator configuration](operator/configuration.md) define a proxy for snoowrap at the top-level:
```yaml
snoowrap:
@@ -59,7 +83,7 @@ Content-Length: 155
--data-raw '{
"httpRequest": {},
"priority": 0,
"httpForward": {
"httpForward": {
"host": "oauth.reddit.com",
"port": 443,
"scheme": "HTTPS"
@@ -95,7 +119,7 @@ The lifecycle of a mock call I do:
Content-Type: application/json
Content-Length: 1757
```
```
</details>
@@ -178,7 +202,7 @@ Content-Length: 1757
```
</details>
#### All Responses Timeout
<details markdown="block">
@@ -260,7 +284,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
@@ -287,7 +311,7 @@ Content-Length: 251
</details>
<details>
<details markdown="block">
<summary>CURL</summary>
```bash
@@ -313,7 +337,7 @@ curl --location --request PUT 'http://localhost:8010/mockserver/expectation' \
#### All Responses Drop After Delay (Connection Closed by Server)
<details>
<details markdown="block">
<summary>HTTP</summary>
```HTTP
@@ -340,7 +364,7 @@ Content-Length: 234
</details>
<details>
<details markdown="block">
<summary>CURL</summary>
```bash
@@ -378,7 +402,7 @@ Content-Length: 26
}
```
<details>
<details markdown="block">
<summary>CURL</summary>
```bash

BIN
docs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

169
docs/index.md Normal file
View File

@@ -0,0 +1,169 @@
---
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,6 +1,12 @@
---
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](/docs/operator/README.md).
If you are trying to run a ContextMod instance (the actual software) please refer to the [operator section](../operator/README.md).
# Table of Contents
@@ -18,7 +24,7 @@ If you are trying to run a ContextMod instance (the actual software) please refe
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](/docs/images/subredditStatus.jpg) and control its behavior using the [web editor.](/docs/images/editor.jpg)
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
@@ -42,7 +48,7 @@ Unlike reddit, though, there is a greater level of trust required between you an
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](/docs/subreddit/components/README.md) for it do anything.
* 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.
@@ -51,11 +57,11 @@ Your bot is like an **invite-only version of Automoderator**:
# Getting Started
The [Getting Started](/docs/subreddit/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.
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.](/docs/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.
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.
@@ -63,9 +69,9 @@ A **guided tour** that helps show how to manage the bot at a high-level is avail
## Editing The Bot
Find the [editor in the web interface](/docs/webInterface.md#editingupdating-your-config) to access the built-in editor for 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](/docs/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](../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:
@@ -76,11 +82,11 @@ The editor features:
# Configuration
Use the [Configuration Reference](/docs/subreddit/components/README.md) to learn about all the different components available for building a CM 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](/docs/README.md#how-it-works) and [Core Concepts](/docs/README.md#concepts) to learn the basic of 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-reddit example configurations](/docs/subreddit/components/subredditReady) to familiarize yourself with a complete configuration and ways to use CM.
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
@@ -92,4 +98,4 @@ Guests can do everything a regular mod can except view/add/remove Guest. They ca
**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.](/docs/images/guests.jpg)
[Add guests from the Subreddit tab in the main interface.](../images/guests.jpg)

View File

@@ -1,5 +1,12 @@
---
parent: Moderators
nav_order: 1
---
# Getting Started
This getting started guide is for **reddit moderators** -- that is, someone who wants **an existing ContextMod bot to run on their subreddit.** If you are trying to run a ContextMod
instance (software) please refer to the [operator getting started](/docs/operator/gettingStarted.md) guide.
instance (software) please refer to the [operator getting started](../operator/gettingStarted.md) guide.
# Table of Contents
@@ -14,8 +21,8 @@ instance (software) please refer to the [operator getting started](/docs/operato
Before continuing with this guide you should first make sure you understand how a ContextMod works. Please review this documentation:
* [How It Works](/docs/README.md#how-it-works)
* [Core Concepts](/docs/README.md#concepts)
* [How It Works](../README.md#how-it-works)
* [Core Concepts](../README.md#concepts)
# Choose A Bot
@@ -81,11 +88,11 @@ The default location for this page is at `https://old.reddit.com/r/YOURSUBERDDIT
The bot automatically tries to create its configuration wiki page. You can find the result of this in the log for your subreddit in the web interface.
If this fails for some reason you can create the wiki page through the web interface by navigating to your subreddit's tab, opening the [built-in editor (click **View**)](/docs/images/configBox.png), and following the directions in **Create configuration for...** link found there.
If this fails for some reason you can create the wiki page through the web interface by navigating to your subreddit's tab, opening the [built-in editor (click **View**)](../images/configBox.png), and following the directions in **Create configuration for...** link found there.
If neither of the above approaches work, or you do not wish to use the web interface, expand the section below for directions on how to manually setup the wiki page:
<details>
<details markdown="block">
* Visit the wiki page of the subreddit you want the bot to moderate
* The default location the bot checks for a configuration is at `https://old.reddit.com/r/YOURSUBERDDIT/wiki/botconfig/contextbot`
@@ -104,11 +111,11 @@ If you already have a configuration you may skip the below step and go directly
### Using an Example Config
Visit the [Examples](https://github.com/FoxxMD/context-mod/tree/master/docs/examples) folder to find various examples of individual rules or see the [subreddit-ready examples.](/docs/subreddit/components/subredditReady)
Visit the [Examples](https://github.com/FoxxMD/context-mod/tree/master../examples) folder to find various examples of individual rules or see the [subreddit cookbook examples.](../subreddit-configuration/cookbook)
After you have found a configuration to use as a starting point:
* Copy the URL for the configuration file EX `https://github.com/FoxxMD/context-mod/blob/master/docs/examples/subredditReady/freekarma.json5` and either:
* Copy the URL for the configuration file EX `https://github.com/FoxxMD/context-mod/blob/master../examples/subredditReady/freekarma.json5` and either:
* (Easiest) **Load** it into your [subreddit's built-in editor](#using-the-built-in-editor) and **Save**
* or on the file's page, click the **Raw** button, select all and copy to your clipboard, and [manually save to your wiki page](#manually-saving)
@@ -136,13 +143,13 @@ PROTIP: Find an [example config](#using-an-example-config) to use as a starting
In the web interface each subreddit's tab has access to the built-in editor. Use this built-in editor to automatically create, load, or save the configuration for that subreddit's wiki.
* Visit the tab for the subreddit you want to edit the configuration of
* Open the [built-in editor by click **View**](/docs/images/configBox.png)
* Open the [built-in editor by click **View**](../images/configBox.png)
* Edit your configuration
* Follow the directions on the **Save to r/..** link found at the top of the editor to automatically save your configuration
### Manually Saving
<details>
<details markdown="block">
* Open the wiki page you created in the [wiki setup step](#setup-wiki-page) and click **edit**
* Copy-paste your configuration into the wiki text box

View File

@@ -1,4 +1,9 @@
# Operator Guide
---
has_children: true
nav_order: 4
---
# Operator
An **Operator** is the user **running the ContextMod software.**
@@ -6,18 +11,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](/docs/operator/configuration.md) that affects general bot/subreddit behavior
* Providing [global-level configuration](configuration.md) that affects general bot/subreddit behavior
* Onboarding new bots/subreddits
# Table of Contents
* [Overview](#overview)
* [Client-Server Architecture](/docs/serverClientArchitecture.md)
* [Getting Started](/docs/operator/gettingStarted.md)
* [Installation](/docs/operator/installation.md)
* [Client-Server Architecture](serverClientArchitecture.md)
* [Getting Started](gettingStarted.md)
* [Installation](installation.md)
* [Provisioning a Reddit Client](#provisioning-a-reddit-client)
* [Configuration](/docs/operator/configuration.md)
* [Adding A Bot](/docs/operator/addingBot.md)
* [Configuration](configuration.md)
* [Adding A Bot](addingBot.md)
# Overview
@@ -28,13 +33,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.](/docs/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.](../serverClientArchitecture.md)
# [Getting Started](/docs/operator/gettingStarted.md)
# [Getting Started](gettingStarted.md)
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.
The [Getting Started](gettingStarted.md) guide serves as a straight-forward "how-to" for standing up a CM server from scratch with minimal explanation.
# [Installation](/docs/operator/installation.md)
# [Installation](installation.md)
CM has many installation options:
@@ -42,7 +47,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](/docs/operator/installation.md) docs for more information.
Refer to the [Installation](installation.md) docs for more information.
# Provisioning A Reddit Client
@@ -60,18 +65,18 @@ Click **create app**.
Then write down your **Client ID, Client Secret, and Redirect Uri** somewhere
# [Configuration](/docs/operator/configuration.md)
# [Configuration](configuration.md)
The [Configuration](/docs/operator/configuration.md) documentation covers:
The [Configuration](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](/docs/operator/addingBot.md)
# [Adding A Bot](addingBot.md)
The [Adding A Bot](/docs/operator/addingBot.md) documentation covers:
The [Adding A Bot](addingBot.md) documentation covers:
* What is a Bot?
* What is needed to add a Bot to CM?

View File

@@ -1,3 +1,10 @@
---
parent: Operator
nav_order: 4
---
# Adding A Bot
# Table of Contents
* [What is a Bot?](#what-is-a-bot)
@@ -19,7 +26,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](/docs/operator/README.md#provisioning-a-reddit-client)
* [Provisioned a Reddit Client](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.
@@ -38,7 +45,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](/docs/operator/configuration.md#minimum-config)
* created a [minimum operator configuration](configuration.md#minimum-config)
* that specifies the client id/secret from provisioning your reddit client
* specified **Operator Name** in the configuration
@@ -56,14 +63,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.](/docs/operator/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.](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.](/docs/operator/README.md#provisioning-a-reddit-client)
* **Note:** You will need to update the **redirect uri** you set when [provisioning your reddit client.](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
@@ -82,5 +89,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.](/docs/operator/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.](configuration.md#manually-adding-a-bot)
* After adding the bot you will need to restart CM.

View File

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

View File

@@ -1,3 +1,10 @@
---
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,7 +43,7 @@ configuration.
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](/docs/operator/addingBot.md#cm-oauth-helper-recommended)
* CM can automatically add bots via the [CM OAuth Helper](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
@@ -44,8 +51,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](/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
* [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
The `DATA_DIR` directory can be changed by passing `DATA_DIR` as an environmental variable EX `DATA_DIR=/path/to/directory`
@@ -65,7 +72,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.](/docs/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.](serverClientArchitecture.md)
## CLI Usage
@@ -79,7 +86,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>
<details markdown="block">
```
Usage: index [options] [command]
@@ -124,11 +131,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.](/docs/operator/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.](addingBot.md#cm-oauth-helper-recommended)
You will need have this information available:
* From [provision a reddit client](/docs/operator/README.md#provisioning-a-reddit-client)
* From [provision a reddit client](README.md#provisioning-a-reddit-client)
* Client ID
* Client Secret
* Redirect URI (if different from default `http://localhost:8085/callback`)
@@ -153,7 +160,7 @@ Configured using the `bots` top-level property. Bot configuration can override a
## Adding A Bot
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.
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.
### Manually Adding a Bot
@@ -166,7 +173,7 @@ Minimum information required for a valid bot:
* Refresh Token
* Access Token
<details>
<details markdown="block">
<summary>Example</summary>
```yaml
@@ -211,7 +218,7 @@ Below are examples of the minimum required config to run the application using a
Using **FILE**
<details>
<details markdown="block">
See [Specify File Location](#specify-file-location) for where this file would be located.
@@ -248,7 +255,7 @@ JSON (`config.json5`)
Using **ENV** (`.env`)
<details>
<details markdown="block">
```
OPERATOR=YourRedditUsername
@@ -261,7 +268,7 @@ REDIRECT_URI=http://localhost:8085/callback
Using **ARG**
<details>
<details markdown="block">
```
node src/index.js run --clientId=f4b4df1c7b2 --clientSecret=34v5q1c56ub --redirectUri=http://localhost:8085/callback
@@ -275,7 +282,7 @@ An example of using multiple configuration levels together IE all are provided t
**FILE**
<details>
<details markdown="block">
```json
{
@@ -296,7 +303,7 @@ logging:
**ENV** (`.env`)
<details>
<details markdown="block">
```
CLIENT_SECRET=34v5q1c56ub
@@ -308,7 +315,7 @@ PORT=9008
**ARG**
<details>
<details markdown="block">
```
node src/index.js run --subreddits=sub1 --clientId=34v5q1c56ub
@@ -328,9 +335,9 @@ log level: debug
## Configuring Client for Many Instances
See the [Architecture Docs](/docs/serverClientArchitecture.md) for more information.
See the [Architecture Docs](erverClientArchitecture.md) for more information.
<details>
<details markdown="block">
YAML
@@ -401,8 +408,8 @@ JSON
# Cache Configuration
See the [Cache Configuration](/docs/operator/caching.md) documentation.
See the [Cache Configuration](caching.md) documentation.
# Database Configuration
See the [Database Configuration](/docs/operator/database.md) documentation.
See the [Database Configuration](database.md) documentation.

View File

@@ -1,3 +1,9 @@
---
parent: Operator
---
# Database
# Overview
CM uses a database to store three types of data:
@@ -31,16 +37,16 @@ databaseConfig:
## SQLite
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`.
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`.
**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.](/docs/operator/configuration.md#specify-file-location)
For both sqlite types, if no database/location is specified, it will be created in the [`DATA_DIR` directory.](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.](/docs/operator/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.](installation.md#linux-host)
## MySQL/MariaDB
@@ -95,7 +101,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 more of recorded events
retention: '3 months' # each subreddit will retain 3 months of recorded events
bots:
# all subreddits this bot moderates will have 3 month retention
- name: u/OneBotAccount
@@ -172,7 +178,7 @@ influxConfig:
A pre-built dashboard for [Grafana](https://grafana.com) can be imported to display overall metrics/stats using InfluxDB data.
![Grafana Dashboard](/docs/images/grafana.jpg)
![Grafana Dashboard](../images/grafana.jpg)
* Create a new Data Source using **InfluxDB** type
* Choose **Flux** for the **Query Language**
@@ -181,7 +187,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](/docs/operator/grafana.json)
* Click **Import** and **upload** the [grafana dashboard json file](grafana.json)
* Chose the data source you created from the **InfluxDB CM** dropdown
* Click **Import**

View File

@@ -1,4 +1,11 @@
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.
---
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.
# Table of Contents
@@ -11,11 +18,11 @@ This getting started guide is for **Operators** -- that is, someone who wants to
# Installation
Follow the [installation](/docs/operator/installation.md) documentation. It is recommended to use **Docker** since it is self-contained.
Follow the [installation](installation.md) documentation. It is recommended to use **Docker** since it is self-contained.
# Create a Reddit Client
[Create a reddit client](/docs/operator/README.md#provisioning-a-reddit-client)
[Create a reddit client](README.md#provisioning-a-reddit-client)
# Start ContextMod
@@ -27,11 +34,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](/docs/operator/configuration.md#minimum-configuration) required to run CM.
**Write Config** and then restart CM. You have now created the [minimum configuration](configuration.md#minimum-configuration) required to run CM.
# Add A Bot to CM
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.
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.
Follow the directions here and **create an Authorization Invite** at the bottom of the page.
@@ -47,8 +54,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](/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)
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)
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)
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)
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.
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.

View File

@@ -1,3 +1,8 @@
---
parent: Operator
nav_order: 2
---
# Installation
In order to run a ContextMod instance you must first you must install it somewhere.
@@ -13,7 +18,7 @@ Images available from these registeries:
* [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](/docs/operator/configuration.md#minimum-config):
An example of starting the container using the [minimum configuration](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.
@@ -40,6 +45,34 @@ To get the UID and GID for the current user run these commands from a terminal:
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
```
## Locally
Requirements:
@@ -57,7 +90,7 @@ npm install
tsc -p .
```
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):
An example of running CM using the [minimum configuration](configuration.md#minimum-config) with a [configuration file](configuration.md#file-configuration-recommended):
```bash
node src/index.js run

View File

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

View File

@@ -1,3 +1,10 @@
---
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)
@@ -45,13 +52,6 @@ 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,11 +70,12 @@ 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](/docs/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](../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:
@@ -134,13 +135,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](/docs/README.md#how-it-works) section to see how Checks fit into CM's lifecycle.
Refer to the [How It Works](../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](/docs/README.md#activity) (`submission` or `comment`) it should process
* **kind** -- what type of [Activity](../README.md#activity) (`submission` or `comment`) it should process
```yaml
runs:
@@ -216,11 +217,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](/docs/subreddit/components/advancedConcepts/flowControl.md) for an in-depth explanation and all possible options.
Refer to the main [**Flow Control** documentation](advancedConcepts/flowControl.md) for an in-depth explanation and all possible options.
## Recording Options
`postFail` and `postTrigger` also enable specifying if/how an [Event](/docs/README.md#event) is recorded. Valid options for recording:
`postFail` and `postTrigger` also enable specifying if/how an [Event](../README.md#event) is recorded. Valid options for recording:
* `false` -- do not record this Event
* `true` -- record Event to all available outputs
@@ -250,7 +251,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](/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.
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.
Rules must have a `kind` that identifies what kind of Rule they are.
@@ -293,13 +294,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](/docs/subreddit/components/advancedConcepts/ruleNameReuse.yaml) | [JSON](/docs/subreddit/components/advancedConcepts/ruleNameReuse.json5)**
See **Rule Name Reuse Examples [YAML](advancedConcepts/ruleNameReuse.yaml) | [JSON](advancedConcepts/ruleNameReuse.json5)**
## List of Rules
### Attribution
[**Full Documentation**](/docs/subreddit/components/attribution)
[**Full Documentation**](in-depth/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:
@@ -310,7 +311,7 @@ The **Attribution** rule will aggregate an Author's content Attributions (youtub
### Recent Activity
[**Full Documentation**](/docs/subreddit/components/recentActivity)
[**Full Documentation**](in-depth/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:
@@ -322,14 +323,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](#item-filter)
* Filter found activities using an [Item Filter](in-depth/filters#item-filter)
* Only return activities that match the Activity from the Event being processed
* Using [image detection](/docs/imageComparison.md) (pixel or perceptual hash matching)
* Using [image detection](imageComparison.md) (pixel or perceptual hash matching)
* Only return certain types of activities (only submission or only comments)
### Repeat Activity
[**Full Documentation**](/docs/subreddit/components/repeatActivity)
[**Full Documentation**](in-depth/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.
@@ -344,7 +345,7 @@ Some of the ways the rule can be modified:
### History
[**Full Documentation**](/docs/subreddit/components/history)
[**Full Documentation**](in-depth/history)
The **History** rule can check an Author's submission/comment statistics over a time period:
@@ -354,33 +355,33 @@ The **History** rule can check an Author's submission/comment statistics over a
### Author
[**Full Documentation**](/docs/subreddit/components/author)
[**Full Documentation**](in-depth/author)
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.
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.
### Regex
[**Full Documentation**](/docs/subreddit/components/regex)
[**Full Documentation**](in-depth/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**](/docs/subreddit/components/repost)
[**Full Documentation**](in-depth/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](/docs/subreddit/components/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](repeatActivity) rule.
### Sentiment Analysis
[**Full Documentation**](/docs/subreddit/components/sentiment)
[**Full Documentation**](in-depth/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**](/docs/subreddit/components/mhs)
[**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/)
@@ -419,7 +420,7 @@ runs:
...
```
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).
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).
# Actions
@@ -431,7 +432,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:**](#named-filters)
**Named Actions** work the same as [**Named Rules**](#named-rules) and [**Named Filters:**](in-depth/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:
@@ -463,7 +464,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**](/docs/subreddit/actionTemplating.md)
[**Action Templating Documentation**](actionTemplating.md)
## List of Actions
@@ -536,6 +537,25 @@ 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)
@@ -716,7 +736,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](/docs/webInterface.md) using the **Removal Reasons** popup
* **reasonId** IDs can be found in the [editor](../../webInterface.md) using the **Removal Reasons** popup
If neither note nor reasonId are included then no removal reason is added.
@@ -744,7 +764,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](/docs/subreddit/components/userNotes) enabled for this action to work.
Your subreddit must have [Toolbox UserNotes](in-depth/userNotes) enabled for this action to work.
* `type` is required
* `content` can be [templated](#templating) and use [URL Tokens](#url-tokens)
@@ -754,12 +774,12 @@ actions:
- kind: usernote
type: spamwarn
content: 'Usernote message'
allowDuplicate: boolean # if false then the usernote will not be added if the same note appears for this activity
existingNoteCheck: boolean # if true (default) then the usernote will not be added if the same note appears for this activity
```
### Mod Note
[**Full Documentation**](/docs/subreddit/components/modActions/README.md#mod-note-action)
[**Full Documentation**](in-depth/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.
@@ -779,6 +799,7 @@ 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
@@ -787,133 +808,17 @@ 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**.
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:
...
```
[**Refer to the full Filter documentation for more**](in-depth/filters)
# Common Patterns
@@ -953,7 +858,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](/docs/subreddit/activitiesWindow.md)
[Full Activities `window` documentation](activitiesWindow.md)
## URL Tokens
@@ -1015,7 +920,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](/docs/subreddit/activitiesWindow.md#duration-values) as well as the individual rule/criteria schema to see what this duration is comparing against.
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.
## Filter Defaults
@@ -1049,7 +954,7 @@ In other words -- Checks will not run if the Author of the Activity being proces
## Flow Control Defaults
See [Flow Control Documentation](/docs/subreddit/components/advancedConcepts/flowControl.md#default-behaviors)
See [Flow Control Documentation](advancedConcepts/flowControl.md#default-behaviors)
# Subreddit-Level Configuration
@@ -1059,7 +964,7 @@ See [Filter Defaults](#filter-defaults) and [Flow Control Defaults](#flow-contro
## Polling
**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** 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 Sources
@@ -1191,7 +1096,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](/docs/operator/caching.md)
[Learn more about how Caching works](../operator/caching.md)
## Partial Configurations
@@ -1246,6 +1151,49 @@ 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**
@@ -1268,7 +1216,7 @@ runs:
subreddits:
- MyBadSubreddit
window: 7 days
actions:
actions:
- kind: report
content: 'uses freekarma subreddits and bad subreddits'
```
@@ -1303,6 +1251,33 @@ 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-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.
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.

View File

@@ -1,3 +1,9 @@
---
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.
@@ -51,6 +57,29 @@ All Actions with `content` have access to this data:
| `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 |
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:

View File

@@ -1,3 +1,9 @@
---
parent: Subreddit Configuration
---
# Activities `window`
# Table Of Contents
* [Overview](#overview)
@@ -24,13 +30,13 @@
# Overview
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.
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.
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](/docs/subreddit/components/README.md#filters) before returning them to a Rule
* **Filters** -- How the retrieved Activities should be [filtered](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.
@@ -214,7 +220,7 @@ window:
# Filters
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.
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.
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.
@@ -222,10 +228,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](/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.
* `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.
In this example the filter only returns Activities:

View File

@@ -1,3 +1,10 @@
---
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
@@ -21,7 +28,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](/docs/README.md#Checks) or [Rule Sets](/docs/subreddit/components/advancedConcepts/README.md#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](../README.md#Checks) or 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

@@ -0,0 +1,205 @@
---
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

@@ -0,0 +1,44 @@
#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,9 +1,18 @@
polling:
- newComm
runs:
- checks:
- name: ban discord only spammer
description: ban a user who spams only a discord link many times historically
#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
#
# Remove comments from users who spam discord and telegram links
# -- differs from just using automod:
# 1) removes comment if it is ONLY discord/telegram link
# 2) if not *only* link then checks user's history to see if link is spammed many times and only removes if it is
#
- name: ban chat only spammer
description: ban a user who spams only a chat link many times historically
kind: comment
condition: AND
rules:
@@ -13,9 +22,9 @@ runs:
- kind: remove
- kind: ban
content: spamming discord links
- name: remove discord spam
- name: remove chat spam
description: >-
remove comments from users who only link to discord or mention discord
remove comments from users who only link to chat or mention chat
link many times historically
kind: comment
condition: OR
@@ -24,8 +33,9 @@ runs:
kind: regex
criteria:
- name: only link
# https://regexr.com/70j9m
# single quotes are required to escape special characters
regex: '/^.*(discord\.gg\/[\w\d]+)$/i'
regex: '/^\s*((?:discord\.gg|t\.me|telegram\.me|telegr\.im)\/[\w\d]+)\s*$/i'
- condition: AND
rules:
- name: linkAnywhereSpam
@@ -33,15 +43,16 @@ runs:
criteria:
- name: contains link anywhere
# single quotes are required to escape special characters
regex: '/^.*(discord\.gg\/[\w\d]+).*$/i'
regex: '/((?:discord\.gg|t\.me|telegram\.me|telegr\.im)\/[\w\d]+)/i'
- name: linkAnywhereHistoricalSpam
kind: regex
criteria:
- name: contains links anywhere historically
# single quotes are required to escape special characters
regex: '/^.*(discord\.gg\/[\w\d]+).*$/i'
regex: '/((?:discord\.gg|t\.me|telegram\.me|telegr\.im)\/[\w\d]+)/i'
totalMatchThreshold: '>= 3'
lookAt: comments
window: 10
window: 100
actions:
- kind: remove
note: Chat spam link

View File

@@ -0,0 +1,71 @@
#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

@@ -0,0 +1,54 @@
#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,14 +1,18 @@
polling:
- newComm
runs:
- checks:
# Stop users who spam the same comment many times
#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
#
# Remove comments by users who spam the same comment many times
#
- name: low xp comment spam
description: X-posted comment >=4x
kind: comment
condition: AND
rules:
- name: xPostLow
- name: xPostLowComm
kind: repeatActivity
# number of "non-repeat" comments allowed between "repeat comments"
gapAllowance: 2
@@ -16,11 +20,13 @@ runs:
threshold: '>= 4'
# retrieve either last 50 comments or 6 months' of history, whichever is less
window:
count: 50
count: 100
duration: 6 months
actions:
- kind: report
enable: true
content: 'Remove => Posted same comment {{rules.xpostlow.largestRepeat}}x times'
enable: false
content: 'Remove => Posted same comment {{rules.xpostlowcomm.largestRepeat}}x times'
- kind: remove
enable: true
note: 'Posted same comment {{rules.xpostlowcomm.largestRepeat}}x times'

View File

@@ -1,7 +1,11 @@
polling:
- unmoderated
runs:
- checks:
#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
#
# stop users who post low-effort, crossposted spam submissions
#
# Remove a SUBMISSION if the user has crossposted it at least 4 times in recent history AND
@@ -18,7 +22,7 @@ runs:
gapAllowance: 2
threshold: '>= 4'
window:
count: 50
count: 100
duration: 6 months
- name: lowOrOpComm
kind: history
@@ -34,12 +38,15 @@ runs:
comment: '> 40% OP'
actions:
- kind: report
enable: true
enable: false
content: >-
Remove=>{{rules.xpostlow.largestRepeat}} X-P =>
{{rules.loworopcomm.thresholdSummary}}
- kind: remove
enable: true
note: 'Repeated submission {{rules.xpostlow.largestRepeat}}x and low comment engagement'
- kind: comment
enable: true
content: >-

View File

@@ -0,0 +1,34 @@
#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

@@ -0,0 +1,34 @@
#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

@@ -0,0 +1,45 @@
#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

@@ -0,0 +1,55 @@
#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

@@ -0,0 +1,89 @@
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

@@ -0,0 +1,51 @@
#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,7 +1,10 @@
polling:
- unmoderated
runs:
- checks:
#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
#
# Stop users who make link submissions with a self-promotional agenda (with reddit's suggested 10% rule)
# https://www.reddit.com/wiki/selfpromotion#wiki_guidelines_for_self-promotion_on_reddit
@@ -58,8 +61,11 @@ runs:
({{rules.attr.window}}{{rules.attrsub.window}}){{#rules.loworopcomm.thresholdSummary}}
=>
{{rules.loworopcomm.thresholdSummary}}{{/rules.loworopcomm.thresholdSummary}}
- kind: remove
enable: false
enable: true
note: '>10% of author's history is content from this creator'
- kind: comment
enable: true
content: >-
@@ -69,4 +75,3 @@ runs:
is against [reddit's self promotional
guidelines.](https://www.reddit.com/wiki/selfpromotion#wiki_guidelines_for_self-promotion_on_reddit)
distinguish: true
dryRun: true

View File

@@ -0,0 +1,33 @@
#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

@@ -0,0 +1,31 @@
#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

@@ -0,0 +1,41 @@
#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

@@ -0,0 +1,47 @@
#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,8 +1,13 @@
---
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](/docs/subreddit/components/recentActivity)
* [Recent Activity](in-depth/recentActivity)
* Repeat Activity (In-progress)
To enable comparisons reference the example below (at the top-level of your rule) and configure as needed:
@@ -39,6 +44,7 @@ YAML
```yaml
name: ruleWithImageDetection
kind: recentActivity
imageDetection:
enable: true
threshold: 5
fetchBehavior: extension

View File

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

View File

@@ -0,0 +1,36 @@
---
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,3 +1,8 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Author
## Rule
@@ -9,7 +14,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](/docs/subreddit/componentscomponents/userNotes)
* [Toolbox User Notes](../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).
@@ -18,10 +23,10 @@ Consult the [schema](https://json-schema.app/view/%23%2Fdefinitions%2FAuthorRule
### Examples
* Basic examples
* 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`
* 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`
* Used with other Rules
* 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
* Ignore vetted user [YAML](flairNewUserSubmission.yaml) | [JSON](flairNewUserSubmission.json5) - Short-circuit the Check if the Author has the `vet` flair
## Filter
@@ -35,7 +40,7 @@ All **Rules** and **Checks** have an optional `authorIs` property that takes an
### Examples
* 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.
* 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.
## Flair users and submissions
@@ -45,4 +50,4 @@ Consult [User Flair schema](https://json-schema.app/view/%23%2Fdefinitions%2FUse
### Examples
* 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.
* OnlyFans submissions [YAML](onlyfansFlair.yaml) | [JSON](onlyfansFlair.json5) - Check whether submitter has typical OF keywords in their profile and flair both author + submission accordingly.

View File

@@ -40,7 +40,7 @@
// for this to pass the Author of the Submission must not have the flair "Supreme Memer" and have the name "user1" or "user2"
{
"flairText": ["Supreme Memer"],
"names": ["user1","user2"]
"name": ["user1","user2"]
},
{
// for this to pass the Author of the Submission must not have the flair "Decent Memer"

View File

@@ -30,7 +30,7 @@ runs:
# for this to pass the Author of the Submission must not have the flair "Supreme Memer" and have the name "user1" or "user2"
- flairText:
- Supreme Memer
names:
name:
- user1
- user2
# for this to pass the Author of the Submission must not have the flair "Decent Memer"

View File

@@ -0,0 +1,457 @@
---
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

@@ -0,0 +1,73 @@
---
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,3 +1,10 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# ModerateHateSpeech.com Rule
# Table of Contents
* [Overview](#overview)
@@ -101,7 +108,7 @@ rules:
#### Historical Matching
Like the [Sentiment](/docs/subreddit/components/sentiment#historical) and [Regex](/docs/subreddit/components/regex#historical) rules CM can also use MHS predictions to check content from the Author's history.
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
@@ -116,6 +123,16 @@ rules:
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
@@ -133,7 +150,8 @@ Report if MHS flags as toxic with 95% confidence
```yaml
rules:
- kind: mhs
confidence: '>= 95'
criteria:
confidence: '>= 95'
actions:
- kind: report
content: 'MHS flagged => {{rules.mhs.summary}}'
@@ -158,8 +176,9 @@ Approve if MHS flags as NOT toxic with 95% confidence
```yaml
rules:
- kind: mhs
confidence: '>= 95'
flagged: false
criteria:
confidence: '>= 95'
flagged: false
actions:
- kind: approve
```

View File

@@ -1,3 +1,10 @@
---
grand_parent: Subreddit Configuration
parent: In Depth
---
# Mod Actions
# Table of Contents
* [Overview](#overview)
@@ -9,9 +16,9 @@
# 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.](/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.
[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.
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)
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)
# Mod Note Action
@@ -37,7 +44,7 @@ actions:
# Mod Action Filter
ContextMod can use **Mod Actions** (from moderation log) and **Mod Notes** in an [Author Filter](/docs/subreddit/components/README.md#author-filter).
ContextMod can use **Mod Actions** (from moderation log) and **Mod Notes** in an [Author Filter](../../../README.md#author-filter).
## API Usage
@@ -61,15 +68,15 @@ Mod Action Filtering Used
In general,**do not** use Mod Actions in a Filter if:
* 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
* 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
If you need Mod Notes-like functionality for a high volume subreddit consider using [Toolbox UserNotes](/docs/subreddit/components/userNotes) instead.
If you need Mod Notes-like functionality for a high volume subreddit consider using [Toolbox UserNotes](../userNotes) instead.
In general, **do** use Mod Actions in a Filter if:
* 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**
* 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**
* 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,50 @@
---
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

@@ -0,0 +1,36 @@
---
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" |

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