PHPackages                             askvortsov/flarum-auto-moderator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. askvortsov/flarum-auto-moderator

ActiveFlarum-extension[Utility &amp; Helpers](/categories/utility)

askvortsov/flarum-auto-moderator
================================

Powerful automation engine.

v0.1.3(2y ago)1418.4k↑1725%7[2 issues](https://github.com/askvortsov1/flarum-automod/issues)[1 PRs](https://github.com/askvortsov1/flarum-automod/pulls)2MITPHP

Since May 20Pushed 2y ago2 watchersCompare

[ Source](https://github.com/askvortsov1/flarum-automod)[ Packagist](https://packagist.org/packages/askvortsov/flarum-auto-moderator)[ RSS](/packages/askvortsov-flarum-auto-moderator/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (6)Versions (5)Used By (2)

Auto Moderator
==============

[](#auto-moderator)

[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667) [![Latest Stable Version](https://camo.githubusercontent.com/0b43a5dc4bfa41f12dcd56ae1814eece90ae043f5e36f7880e0ca0c4c35510e5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f61736b766f7274736f76312f666c6172756d2d6175746f6d6f642e737667)](https://packagist.org/packages/askvortsov/flarum-automod)

A [Flarum](http://flarum.org) extension.

Core Concept
------------

[](#core-concept)

The idea is simple: **When X, if Y, do Z**.

Let's define some key terms:

- **Trigger:** A set of events (usually just one) that can trigger an automation. For example, "Posted", "LoggedIn", "Post liked".
- **Metric:** A numerical quantity. For example, post count or number of likes received.
- **Requirement:** An abstract boolean condition. For example, not being suspended, having an email that matches some regex, etc.
- **Action:** Some side effect / mutation to perform. This could include anything from adding/removing a group to sending an email to suspending a user.

Code-wise, these are represented by "Drivers", implementing one of `TriggerDriverInterface`, `MetricDriverInterface`, etc.

*Requirement* and *Action* drivers take a list of "settings", which they specify validation rules for. This means you can build a `UserEmailMatchesRegex : RequirementDriverInterface`, or a `AddUserToGroup : ActionDriverInterface`, and then create multiple instances of the drivers with any regex or group ID.

All these are tied together by **Rules**. Rules are stored as \[A DATABASE TABLE OR A SETTING, IDK\], and specify:

- A trigger for when the rule should run
- A list of metrics "instances". Each instance includes:
    - which metric driver is used
    - a numerical range (could also be a one-sided min or max range). If the value computed by the metric driver falls **in** this range, the metric is satisfied. E.g. "between 10 and 100" likes received
    - a "negation" Boolean. If true, the metric will be satisfied if the value computed by the metric driver falls **outside** of the range
- A list of requirement "instances". Each instance includes:
    - which requirement driver is being used.
    - A value for the requirement driver's config. It will be plugged into the requirement driver to compute whether the requirement is satisfied. E.g. a users email needs to end with "flarum.org"
    - A "negation" Boolean. As with metrics, this allows inverting the requirement driver's output
- a list of actions instances. Each includes:
    - which action driver is used
    - a "settings" value, that will be plugged into an action driver to run the action (e.g. which group to remove a user from)

Trigger drivers specify a list of "subject models", e.g. the author and post in a post created event. These determine which metrics, requirements, and actions are available when defining a rule for some trigger, since "running" a metric, requirement, or action always requires some subject (e.g. which user are we calculating num likes received for, which post are we auto-flagging, etc)

Whenever any event that has rules attached via triggers runs, we "evaluate" all valid rules, and if all the rule's metrics and requirements are satisfied, the rule's actions will run.

A rule is invalid if (1) it has requirements or actions where settings don't pass validation, (2) any of it's components depend on an extension that isn't currently enabled, or (3) any of it's components reference drivers that don't currently exist.

This makes for an **extremely** powerful extension. Since extensions can add their own metrics, requirements, and actions, this extension can automate away a lot of moderation. Beyond the examples listed below, some things that could be possible are:

- Automating assignment of achievements / badges
- Sending emails/notifications to users when they reach thresholds (or just when they register)
- Establishing a system of "trust levels" like [Discourse](https://blog.discourse.org/2018/06/understanding-discourse-trust-levels/)
- Onboard/offboard users to/from external systems when they receive/lose certain group membership
- auto-flagging posts that fail some test

Testability
-----------

[](#testability)

Because this system is so generic, we can separate testing the framework for (validating, evaluating, running) rules, from each of the drivers.

Testing drivers is super easy, which makes it cheap and easy to add any drivers we want. See this extension's test suite for examples.

TODO:
-----

[](#todo)

- Implement the frontend for creating, viewing, and editing rules. Maybe there could be a feature to import a `Rule` as JSON, so that rules could be easily shared between forums?
    - We could allow registering form components / config for the settings of certain drivers, so that e.g. "AddUserToGroup" actions could be configured with a real group selector, not just a number field.
    - I've already implemented a metric range selector component.
- Add a ton more drivers.
    - Actions e.g. send emails, flag posts, create warmings
    - metrics e.g. posts read, time spent, days visited, days since account creation
    - requirements e.g. "user has bio", "post matches regex", etc
- more tests for rule evaluation and validation
- add support for "dated" metrics, e.g. "num discussions created in the past X days"
- cache / store calculated metric values for use by other extensions
- making metric values available to action implementations

### Already Implemented

[](#already-implemented)

- interfaces for the various drivers
    - a bunch of instances of each driver
    - tests for each instance
- an extender for adding new drivers
- A `Rule` class, including the core validation and evaluation logic for rules
    - And some tests for this, although more would be nice!

Metrics vs Requirements
-----------------------

[](#metrics-vs-requirements)

Any metric driver could be implemented as a requirement driver, since requirements are more powerful. But if your requirements are about numerical conditions, metric drivers are better because:

- it's easy to specify a range of numbers that is valid
- the output of the metric driver contains the actual value, and so could be used for other features, e.g. calculating a "reputation" score per-user

EVERYTHING BELOW THIS LINE IS OUTDATED
======================================

[](#everything-below-this-line-is-outdated)

---

Examples
--------

[](#examples)

### Example 1: Group Management

[](#example-1-group-management)

**Criteria:** Users that receive 50 or more likes and have started at least 10 discussions should placed in the "Active" group.

Here, the metrics are "received 50 or more likes" and "have started at least 10 discussions". Unsurprisingly, they come with the triggers (`PostWasLiked`, `PostWasUnliked`) and (`Discussion\Started`) respectively.

The actions are:

- When the criteria is met, add the user to the "Active" group
- When the criteria is lost, remove the user from the "Active" group

### Example 2: Suspension

[](#example-2-suspension)

**Criteria:** If a user gets 15 warnings or more and is not an admin, suspend them.

Here, the metrics are "gets 15 warnings or more" and the requirements are "is not an admin". The triggers would be a new warning for the metric. The requirement has no triggers.

The actions are:

- When the criteria is met, suspend them
- When the criteria is lost, unsuspend them

### Example 3: Auto Activation

[](#example-3-auto-activation)

**Criteria:** If a user's email matches a regex, activate their email.

The requirement is "a user's email matches a regex". The triggers are saving a user.

The actions are:

- When the criteria is met, auto activate the user's email
- When the criteria are not met, don't

### Example 4: Default Group

[](#example-4-default-group)

**Criteria:** Add a user to a group

There are no metrics or requirements, so this will be applied to all users on login.

The actions are:

- Add all users to a group on login

Screenshots
-----------

[](#screenshots)

[![Admin](https://camo.githubusercontent.com/54b6f89b01f1c2112c8930c519c97e2d02e4c57cba7fe1e1e5d33e71775884c7/68747470733a2f2f692e696d6775722e636f6d2f6b397a667764392e706e67)](https://camo.githubusercontent.com/54b6f89b01f1c2112c8930c519c97e2d02e4c57cba7fe1e1e5d33e71775884c7/68747470733a2f2f692e696d6775722e636f6d2f6b397a667764392e706e67)[![Criterion Edit](https://camo.githubusercontent.com/089d01e6598abdb2c59b1999290b1d9006be4f872ed636d9cc68a9b4003fc001/68747470733a2f2f692e696d6775722e636f6d2f444967636a34382e706e67)](https://camo.githubusercontent.com/089d01e6598abdb2c59b1999290b1d9006be4f872ed636d9cc68a9b4003fc001/68747470733a2f2f692e696d6775722e636f6d2f444967636a34382e706e67)[![Edit User](https://camo.githubusercontent.com/a47cd5ccaa6f9ee6222b91176097f4acd1af6bd12881a4bacf1b4388302cb615/68747470733a2f2f692e696d6775722e636f6d2f386b5a5a516d542e706e67)](https://camo.githubusercontent.com/a47cd5ccaa6f9ee6222b91176097f4acd1af6bd12881a4bacf1b4388302cb615/68747470733a2f2f692e696d6775722e636f6d2f386b5a5a516d542e706e67)

Extensibility
-------------

[](#extensibility)

This extension is extremely flexible. It can be considered a framework for automoderation actions.

Extensions can use the `Askvortsov\AutoModerator\Extend\AutoModerator` extender to add:

- Action drivers
- Metric drivers
- Requirement drivers

You should look at the source code of the default drivers for examples. They're fairly exhaustive of what's offered.

If your extension adds action or requirement drivers that [consume settings](#settings), you have 2 options:

- Provide translation keys for the settings you need in the driver's `availableSettings` method. This is very easy, but also very restrictive. You can only use strings, and can't add any restrictions or UI.
- You can declare a settings form component for your driver. See `js/src/admin/components/SuspendSelector` for an example. The component should take a settings stream as `this.attrs.settings`. The contents of the stream should be an object that maps setting keys to values. The component is responsible for updating the stream on input. You can register a form component by adding its class to `app.autoModeratorForms[DRIVER CATEGORY][TYPE]`, where `DRIVER CATEGORY` is `"action"` or `"requirement"`, and `TYPE` is the type string you registered your driver with in `extend.php`. See `js/src/admin/index.js` for the underlying data structure and examples.

Contributions
-------------

[](#contributions)

Contributions and PRs are welcome! Any PRs adding new drivers should come with unit tests (like with all existing drivers).

Compatibility
-------------

[](#compatibility)

Compatible starting with Flarum 1.0.

Installation
------------

[](#installation)

```
composer require askvortsov/flarum-automod:*
```

Updating
--------

[](#updating)

```
composer update askvortsov/flarum-automod
```

Links
-----

[](#links)

- [Packagist](https://packagist.org/packages/askvortsov/flarum-automod)
- [Github](https://github.com/askvortsov1/flarum-automod)
- [Discuss](https://discuss.flarum.org/d/27306-flarum-automoderator)

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance17

Infrequent updates — may be unmaintained

Popularity36

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 89.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~279 days

Total

4

Last Release

986d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/545a920fc6d01092248f49fb305da628a1bcff5b357a9b162cf0872e2d5ff3c1?d=identicon)[askvortsov](/maintainers/askvortsov)

---

Top Contributors

[![askvortsov1](https://avatars.githubusercontent.com/u/38059171?v=4)](https://github.com/askvortsov1 "askvortsov1 (116 commits)")[![flarum-bot](https://avatars.githubusercontent.com/u/39334649?v=4)](https://github.com/flarum-bot "flarum-bot (9 commits)")[![jaspervriends](https://avatars.githubusercontent.com/u/4417659?v=4)](https://github.com/jaspervriends "jaspervriends (2 commits)")[![iPurpl3x](https://avatars.githubusercontent.com/u/18526076?v=4)](https://github.com/iPurpl3x "iPurpl3x (1 commits)")[![nxta](https://avatars.githubusercontent.com/u/5470282?v=4)](https://github.com/nxta "nxta (1 commits)")

---

Tags

flarum

### Embed Badge

![Health badge](/badges/askvortsov-flarum-auto-moderator/health.svg)

```
[![Health](https://phpackages.com/badges/askvortsov-flarum-auto-moderator/health.svg)](https://phpackages.com/packages/askvortsov-flarum-auto-moderator)
```

###  Alternatives

[fof/byobu

Well integrated, advanced private discussions.

61105.8k9](/packages/fof-byobu)[fof/user-bio

Add a user bio to user profiles

2196.5k9](/packages/fof-user-bio)[fof/links

Manage Flarum primary navbar menu links

39118.3k2](/packages/fof-links)[fof/drafts

Allow users to create post and discussion drafts

1771.1k5](/packages/fof-drafts)[fof/nightmode

Add a Night Mode option for your users to use on your Flarum forum

3774.5k2](/packages/fof-nightmode)[fof/best-answer

Mark a post as the best answer in a discussion

26135.2k15](/packages/fof-best-answer)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
