PHPackages                             blaspsoft/blasp - 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. [Validation &amp; Sanitization](/categories/validation)
4. /
5. blaspsoft/blasp

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

blaspsoft/blasp
===============

Blasp is a powerful and customisable profanity filter package for Laravel applications

v4.0.1(1mo ago)329174.3k↑14.8%25[1 PRs](https://github.com/Blaspsoft/blasp/pulls)1MITPHPPHP ^8.2CI passing

Since Oct 19Pushed 1mo ago3 watchersCompare

[ Source](https://github.com/Blaspsoft/blasp)[ Packagist](https://packagist.org/packages/blaspsoft/blasp)[ Docs](https://github.com/blaspsoft/blasp)[ RSS](/packages/blaspsoft-blasp/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (24)Used By (1)

 [![Blasp Icon](./assets/icon.png)](./assets/icon.png)

> **Official API Available!** This package powers [blasp.app](https://blasp.app/) - a universal profanity filtering REST API that works with any language. Free tier with 1,000 requests/month, multi-language support, and custom word lists.

 [![GitHub Workflow Status (main)](https://github.com/Blaspsoft/blasp/actions/workflows/main.yml/badge.svg)](https://github.com/Blaspsoft/blasp/actions/workflows/main.yml) [![Total Downloads](https://camo.githubusercontent.com/cd724b55b48ab27c6fbc76878571c49c5c80fbe2d71f90c491ca1389bdb318b0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f626c617370736f66742f626c617370)](https://packagist.org/packages/blaspsoft/blasp) [![Latest Version](https://camo.githubusercontent.com/2a018b6c5356d2f5300776b6fe9e468b918f0d7da5aa5471d3264c3b7549a0d1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f626c617370736f66742f626c617370)](https://packagist.org/packages/blaspsoft/blasp) [![License](https://camo.githubusercontent.com/39aa3e9b48f79fac8e3be7f28e05aeb374e2fc0b56ef3c269c9486c138447320/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f626c617370736f66742f626c617370)](https://packagist.org/packages/blaspsoft/blasp)

Blasp - Advanced Profanity Filter for Laravel
=============================================

[](#blasp---advanced-profanity-filter-for-laravel)

Blasp is a powerful, extensible profanity filter for Laravel. Version 4 is a ground-up rewrite with a driver-based architecture, severity scoring, masking strategies, Eloquent model integration, and a clean fluent API.

Features
--------

[](#features)

- **Driver Architecture** — `regex` (detects obfuscation, substitutions, separators), `pattern` (fast exact matching), `phonetic` (catches sound-alike evasions), or `pipeline` (chains multiple drivers together). Extend with custom drivers.
- **Multi-Language** — English, Spanish, German, French with language-specific normalizers. Check one, many, or all at once.
- **Severity Scoring** — Words categorised as mild/moderate/high/extreme. Filter by minimum severity and get a 0-100 score.
- **Masking Strategies** — Character mask (`*`, `#`), grawlix (`!@#$%`), or a custom callback.
- **Eloquent Integration** — `Blaspable` trait auto-sanitizes or rejects profanity on model save.
- **Middleware** — Reject or sanitize profane request fields with configurable severity.
- **Validation Rules** — Fluent validation rule with language, severity, and score threshold support.
- **Testing Utilities** — `Blasp::fake()` for test doubles with assertions.
- **Events** — `ProfanityDetected`, `ContentBlocked`, and `ModelProfanityDetected`.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 8.0+

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

[](#installation)

```
composer require blaspsoft/blasp
```

Publish configuration:

```
# Everything (config + language files)
php artisan vendor:publish --tag="blasp"

# Config only
php artisan vendor:publish --tag="blasp-config"

# Language files only
php artisan vendor:publish --tag="blasp-languages"
```

Quick Start
-----------

[](#quick-start)

```
use Blaspsoft\Blasp\Facades\Blasp;

$result = Blasp::check('This is a fucking sentence');

$result->isOffensive();  // true
$result->clean();         // "This is a ******* sentence"
$result->original();      // "This is a fucking sentence"
$result->score();         // 30
$result->count();         // 1
$result->uniqueWords();   // ['fucking']
$result->severity();      // Severity::High
```

Fluent API
----------

[](#fluent-api)

All builder methods return a `PendingCheck` and can be chained:

```
// Language selection
Blasp::in('spanish')->check($text);
Blasp::in('english', 'french')->check($text);
Blasp::inAllLanguages()->check($text);

// Language shortcuts
Blasp::english()->check($text);
Blasp::spanish()->check($text);
Blasp::german()->check($text);
Blasp::french()->check($text);

// Driver selection
Blasp::driver('regex')->check($text);     // Full obfuscation detection (default)
Blasp::driver('pattern')->check($text);   // Fast exact matching
Blasp::driver('phonetic')->check($text);  // Sound-alike detection (e.g. "phuck", "sheit")
Blasp::driver('pipeline')->check($text);  // Chain multiple drivers (config-based)

// Ad-hoc pipeline — chain any drivers without config
Blasp::pipeline('regex', 'phonetic')->check($text);
Blasp::pipeline('pattern', 'phonetic')->in('english')->mask('#')->check($text);

// Shorthand modes
Blasp::strict()->check($text);   // Forces regex driver
Blasp::lenient()->check($text);  // Forces pattern driver

// Masking
Blasp::mask('*')->check($text);        // Character mask (default)
Blasp::mask('#')->check($text);        // Custom character
Blasp::mask('grawlix')->check($text);  // !@#$% cycling
Blasp::mask(fn($word, $len) => '[CENSORED]')->check($text);  // Callback

// Severity filtering
use Blaspsoft\Blasp\Enums\Severity;
Blasp::withSeverity(Severity::High)->check($text);  // Ignores mild/moderate

// Allow/block lists (merged with config)
Blasp::allow('damn', 'hell')->check($text);
Blasp::block('customword')->check($text);

// Chain everything
Blasp::spanish()
    ->mask('#')
    ->withSeverity(Severity::Moderate)
    ->check($text);

// Batch checking
$results = Blasp::checkMany(['text one', 'text two']);
```

Result Object
-------------

[](#result-object)

The `Result` object is returned by every `check()` call:

MethodReturnsDescription`isOffensive()``bool`Text contains profanity`isClean()``bool`Text is clean`clean()``string`Text with profanities masked`original()``string`Original unmodified text`score()``int`Severity score (0-100)`count()``int`Total profanity matches`uniqueWords()``array`Unique base words detected`severity()``?Severity`Highest severity in matches`words()``Collection``MatchedWord` objects with position, length, severity`toArray()``array`Full result as array`toJson()``string`Full result as JSON`Result` implements `JsonSerializable`, `Stringable` (returns clean text), and `Countable`.

Detection Types
---------------

[](#detection-types)

The regex driver detects obfuscated profanity:

TypeExampleDetected AsStraight match`fucking``fucking`Substitution`fÛck!ng`, `f4ck``fucking`, `fuck`Separators`f-u-c-k-i-n-g`, `f@ck``fucking`, `fuck`Doubled`ffuucckkiinngg``fucking`Combination`f-uuck!ng``fucking`> **Separator limit:** The regex driver allows up to 3 separator characters between each letter (e.g., `f--u--c--k`). This covers all realistic obfuscation patterns while keeping regex complexity low enough for PHP-FPM environments.

The pattern driver only detects straight word-boundary matches.

The phonetic driver uses `metaphone()` + Levenshtein distance to catch words that *sound like* profanity but are spelled differently:

TypeExampleDetected AsPhonetic spelling`phuck``fuck`Shortened form`fuk``fuck`Sound-alike`sheit``shit`Configure sensitivity in `config/blasp.php` under `drivers.phonetic`. A curated false-positive list prevents common words like "fork", "duck", and "beach" from being flagged.

### Pipeline Driver

[](#pipeline-driver)

The pipeline driver chains multiple drivers together so a single `check()` call runs all of them. It uses **union merge** semantics — text is flagged if **any** driver finds a match.

```
// Config-based: set 'default' => 'pipeline' or use driver('pipeline')
Blasp::driver('pipeline')->check('phuck this sh1t');

// Ad-hoc: pick drivers on the fly (no config needed)
Blasp::pipeline('regex', 'phonetic')->check('phuck this sh1t');
Blasp::pipeline('regex', 'pattern', 'phonetic')->check($text);
```

When multiple drivers detect the same word at the same position, duplicates are removed — only the longest match is kept. Masks are applied from the merged result, and the score is recalculated across all matches.

Configure the default sub-drivers in `config/blasp.php`:

```
'drivers' => [
    'pipeline' => [
        'drivers' => ['regex', 'phonetic'],  // Drivers to chain
    ],
],
```

Eloquent Integration
--------------------

[](#eloquent-integration)

The `Blaspable` trait automatically checks model attributes during save:

```
use Blaspsoft\Blasp\Blaspable;

class Comment extends Model
{
    use Blaspable;

    protected array $blaspable = ['body', 'title'];
}
```

```
// Sanitize mode (default) — profanity is masked, model saves
$comment = Comment::create(['body' => 'This is fucking great']);
$comment->body; // "This is ******* great"

// Check what happened
$comment->hadProfanity();            // true
$comment->blaspResults();            // ['body' => Result, 'title' => Result]
$comment->blaspResult('body');       // Result instance
```

### Per-Model Overrides

[](#per-model-overrides)

```
class Comment extends Model
{
    use Blaspable;

    protected array $blaspable = ['body', 'title'];
    protected string $blaspMode = 'reject';     // 'sanitize' (default) | 'reject'
    protected string $blaspLanguage = 'spanish'; // null = config default
    protected string $blaspMask = '#';           // null = config default
}
```

### Reject Mode

[](#reject-mode)

In reject mode, saving a model with profanity throws `ProfanityRejectedException` and the model is not persisted:

```
use Blaspsoft\Blasp\Exceptions\ProfanityRejectedException;

try {
    $comment = Comment::create(['body' => 'profane text']);
} catch (ProfanityRejectedException $e) {
    $e->attribute; // 'body'
    $e->result;    // Result instance
    $e->model;     // The unsaved model
}
```

### Disabling Checking

[](#disabling-checking)

```
Comment::withoutBlaspChecking(function () {
    Comment::create(['body' => 'unchecked content']);
});
```

### Events

[](#events)

A `ModelProfanityDetected` event fires whenever profanity is detected on a model attribute (both sanitize and reject modes):

```
use Blaspsoft\Blasp\Events\ModelProfanityDetected;

Event::listen(ModelProfanityDetected::class, function ($event) {
    $event->model;     // The model instance
    $event->attribute; // Which attribute had profanity
    $event->result;    // Result instance
});
```

Middleware
----------

[](#middleware)

Use `CheckProfanity` to filter incoming request fields. A `blasp` middleware alias is registered automatically:

```
// Using the short alias (recommended)
Route::post('/comment', CommentController::class)
    ->middleware('blasp');

// With parameters: action, severity
Route::post('/comment', CommentController::class)
    ->middleware('blasp:sanitize,mild');

// Or using the class directly
use Blaspsoft\Blasp\Middleware\CheckProfanity;

Route::post('/comment', CommentController::class)
    ->middleware(CheckProfanity::class);
```

ActionBehaviour`reject` (default)Returns 422 JSON with field errors`sanitize`Replaces profane fields in the request and continuesConfigure which fields to check in `config/blasp.php`:

```
'middleware' => [
    'action' => 'reject',
    'fields' => ['*'],                            // '*' = all fields
    'except' => ['password', 'email', '_token'],  // Always skipped
    'severity' => 'mild',
],
```

Validation Rules
----------------

[](#validation-rules)

### String Rule

[](#string-rule)

```
$request->validate([
    'comment' => ['required', 'blasp_check'],
    'bio'     => ['required', 'blasp_check:spanish'],
]);
```

### Fluent Rule Object

[](#fluent-rule-object)

```
use Blaspsoft\Blasp\Rules\Profanity;
use Blaspsoft\Blasp\Enums\Severity;

$request->validate([
    'comment' => ['required', Profanity::in('english')],
    'bio'     => ['required', Profanity::severity(Severity::High)],
    'tagline' => ['required', Profanity::maxScore(50)],
]);
```

Blade Directive
---------------

[](#blade-directive)

The `@clean` directive sanitizes and escapes text for safe display in views:

```
@clean($comment->body)

{{-- Equivalent to: {{ app('blasp')->check($comment->body)->clean() }} --}}
```

Output is HTML-escaped via `e()` for XSS safety.

Str / Stringable Macros
-----------------------

[](#str--stringable-macros)

Blasp registers macros on Laravel's `Str` and `Stringable` classes:

```
use Illuminate\Support\Str;

// Static methods
Str::isProfane('fuck this');        // true
Str::isProfane('hello');            // false
Str::cleanProfanity('fuck this');   // '**** this'
Str::cleanProfanity('hello');       // 'hello'

// Fluent Stringable methods
Str::of('fuck this')->isProfane();          // true
Str::of('fuck this')->cleanProfanity();     // Stringable('**** this')
Str::of('hello')->cleanProfanity()->upper(); // 'HELLO' (chaining works)
```

Configuration
-------------

[](#configuration)

Full `config/blasp.php` reference:

```
return [
    'default'   => env('BLASP_DRIVER', 'regex'),       // 'regex' | 'pattern' | 'phonetic' | 'pipeline'
    'language'  => env('BLASP_LANGUAGE', 'english'),    // Default language
    'mask'      => '*',                                 // Default mask character
    'severity'  => 'mild',                              // Minimum severity
    'events'    => false,                               // Fire ProfanityDetected events

    'cache' => [
        'enabled' => true,
        'driver'  => env('BLASP_CACHE_DRIVER'),
        'ttl'     => 86400,
        'results' => true,          // Cache check() results by content hash
    ],

    'middleware' => [
        'action'   => 'reject',
        'fields'   => ['*'],
        'except'   => ['password', 'email', '_token'],
        'severity' => 'mild',
    ],

    'model' => [
        'mode' => env('BLASP_MODEL_MODE', 'sanitize'),  // 'sanitize' | 'reject'
    ],

    'drivers' => [
        'pipeline' => [
            'drivers' => ['regex', 'phonetic'],    // Sub-drivers to chain
        ],
        'phonetic' => [
            'phonemes' => 4,                       // metaphone code length (2-8)
            'min_word_length' => 3,                // skip short words
            'max_distance_ratio' => 0.6,           // levenshtein threshold (0.3-0.8)
            'supported_languages' => ['english'],  // metaphone is English-oriented
            'false_positives' => ['fork', '...'],  // never flag these words
        ],
    ],

    'allow'  => [],    // Global allow-list
    'block'  => [],    // Global block-list

    'separators'      => [...],  // Characters treated as separators
    'substitutions'   => [...],  // Character leet-speak mappings
    'false_positives' => [...],  // Words that should never be flagged
];
```

Custom Drivers
--------------

[](#custom-drivers)

Implement `DriverInterface` and register with the manager:

```
use Blaspsoft\Blasp\Core\Contracts\DriverInterface;
use Blaspsoft\Blasp\Core\Result;
use Blaspsoft\Blasp\Core\Dictionary;
use Blaspsoft\Blasp\Core\Contracts\MaskStrategyInterface;

class MyDriver implements DriverInterface
{
    public function detect(string $text, Dictionary $dictionary, MaskStrategyInterface $mask, array $options = []): Result
    {
        // Your detection logic
    }
}

// Register in a service provider
Blasp::extend('my-driver', fn($app) => new MyDriver());

// Use it
Blasp::driver('my-driver')->check($text);
```

Caching
-------

[](#caching)

Blasp caches `check()` results by default. When the same text is checked with the same configuration (language, driver, severity, allow/block lists), the cached result is returned instantly.

```
// First call — runs full analysis, caches result
$result = Blasp::check('some text');

// Second call — returns cached result
$result = Blasp::check('some text');
```

Configure caching in `config/blasp.php`:

```
'cache' => [
    'enabled' => true,                      // Master switch for all caching
    'driver'  => env('BLASP_CACHE_DRIVER'), // null = default cache driver
    'ttl'     => 86400,                     // Cache lifetime in seconds
    'results' => true,                      // Cache check() results (disable independently)
],
```

Result caching is automatically bypassed when using a `CallbackMask` (closures can't be serialized). Clear both dictionary and result caches with:

```
php artisan blasp:clear
```

Or programmatically:

```
Dictionary::clearCache();
```

Artisan Commands
----------------

[](#artisan-commands)

```
# Clear the profanity cache
php artisan blasp:clear

# Test text from the command line
php artisan blasp:test "some text to check" --lang=english --detail

# List available languages with word counts
php artisan blasp:languages
```

Testing
-------

[](#testing)

### Faking

[](#faking)

```
use Blaspsoft\Blasp\Facades\Blasp;
use Blaspsoft\Blasp\Core\Result;

// Replace with a fake — all checks return clean by default
Blasp::fake();

// Pre-configure specific responses
Blasp::fake([
    'bad text'   => Result::withMatches(['fuck']),
    'clean text' => Result::none('clean text'),
]);

$result = Blasp::check('bad text');
$result->isOffensive(); // true

// Assertions
Blasp::assertChecked();
Blasp::assertCheckedTimes(1);
Blasp::assertCheckedWith('bad text');
```

### Disabling Filtering

[](#disabling-filtering)

```
Blasp::withoutFiltering(function () {
    // All checks return clean results
});
```

Events
------

[](#events-1)

Enable global events with `'events' => true` in config:

EventFired WhenProperties`ProfanityDetected``check()` finds profanity`result`, `originalText``ContentBlocked`Middleware detects profanity`result`, `request`, `field`, `action``ModelProfanityDetected`Blaspable trait detects profanity`model`, `attribute`, `result``ModelProfanityDetected` always fires (not gated by the `events` config).

Migrating from v3
-----------------

[](#migrating-from-v3)

### Namespace Changes

[](#namespace-changes)

v3v4`Blaspsoft\Blasp\Facades\Blasp``Blaspsoft\Blasp\Facades\Blasp` (unchanged)`Blaspsoft\Blasp\ServiceProvider``Blaspsoft\Blasp\BlaspServiceProvider`The Laravel auto-discovery handles provider/alias registration automatically. The facade namespace is the same as v3, so no import changes are needed for the facade.

### Config Changes

[](#config-changes)

v3 Keyv4 KeyNotes`default_language``language``default_language` still works as alias`mask_character``mask``mask_character` still works as alias`cache_driver``cache.driver``cache_driver` still works as alias—`default`New: driver selection (`regex`/`pattern`)—`severity`New: minimum severity level—`events`New: enable global events—`allow` / `block`New: global allow/block lists—`middleware`New: middleware configuration section—`model`New: Blaspable trait configuration### Result API Changes

[](#result-api-changes)

v3 Methodv4 Method`hasProfanity()``isOffensive()``getCleanString()``clean()``getSourceString()``original()``getProfanitiesCount()``count()``getUniqueProfanitiesFound()``uniqueWords()`All v3 methods still work as deprecated aliases.

### Builder API Changes

[](#builder-api-changes)

v3 Methodv4 Method`maskWith($char)``mask($char)``allLanguages()``inAllLanguages()``language($lang)``in($lang)``configure($profanities, $falsePositives)``block(...$words)` / `allow(...$words)`All v3 methods still work as deprecated aliases.

### New in v4

[](#new-in-v4)

- **Driver architecture** — `regex` and `pattern` drivers, custom driver support
- **Severity system** — Mild/Moderate/High/Extreme levels with scoring
- **Masking strategies** — Grawlix and callback masking
- **Blaspable trait** — Automatic Eloquent model profanity checking
- **Middleware** — Request-level profanity filtering
- **Fluent validation rule** — `Profanity::in('spanish')->severity(Severity::High)`
- **Testing utilities** — `Blasp::fake()`, assertions, `withoutFiltering()`
- **Events** — `ProfanityDetected`, `ContentBlocked`, `ModelProfanityDetected`
- **Artisan commands** — `blasp:clear`, `blasp:test`, `blasp:languages`
- **Batch checking** — `Blasp::checkMany([...])`
- **Multi-language in one call** — `Blasp::in('english', 'spanish')->check($text)`

Contributing
------------

[](#contributing)

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for detailed version history.

License
-------

[](#license)

Blasp is open-sourced software licensed under the [MIT license](LICENSE).

###  Health Score

60

—

FairBetter than 99% of packages

Maintenance90

Actively maintained with recent releases

Popularity54

Moderate usage in the ecosystem

Community22

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 83.3% 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 ~27 days

Recently: every ~14 days

Total

20

Last Release

53d ago

Major Versions

v1.2.2 → v2.0.02025-02-27

v2.1.0 → v3.0.02025-09-05

v3.1.9 → v4.0.02026-03-26

PHP version history (2 changes)v1.0.0PHP ^7.4|^8.0

v2.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/c728f738aa352593e59935f2b03a4bcafb2c721535f28684909a3b183c8467b7?d=identicon)[Deemonic](/maintainers/Deemonic)

---

Top Contributors

[![deemonic](https://avatars.githubusercontent.com/u/25927364?v=4)](https://github.com/deemonic "deemonic (130 commits)")[![charleskoko](https://avatars.githubusercontent.com/u/55494612?v=4)](https://github.com/charleskoko "charleskoko (22 commits)")[![damiantw](https://avatars.githubusercontent.com/u/19997758?v=4)](https://github.com/damiantw "damiantw (1 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (1 commits)")[![lucasltavares](https://avatars.githubusercontent.com/u/22200813?v=4)](https://github.com/lucasltavares "lucasltavares (1 commits)")[![moe-mizrak](https://avatars.githubusercontent.com/u/12977885?v=4)](https://github.com/moe-mizrak "moe-mizrak (1 commits)")

---

Tags

content-moderationlaravelphpprofanity-checkprofanity-detectionprofanity-filterprofanity-libraryprofanity-validatorprofanityfilterblaspsoftblasp

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/blaspsoft-blasp/health.svg)

```
[![Health](https://phpackages.com/badges/blaspsoft-blasp/health.svg)](https://phpackages.com/packages/blaspsoft-blasp)
```

###  Alternatives

[spatie/laravel-honeypot

Preventing spam submitted through forms

1.6k6.0M60](/packages/spatie-laravel-honeypot)[proengsoft/laravel-jsvalidation

Validate forms transparently with Javascript reusing your Laravel Validation Rules, Messages, and FormRequest

1.1k2.3M49](/packages/proengsoft-laravel-jsvalidation)[stevebauman/purify

An HTML Purifier / Sanitizer for Laravel

5325.6M19](/packages/stevebauman-purify)[axlon/laravel-postal-code-validation

Worldwide postal code validation for Laravel and Lumen

3853.3M1](/packages/axlon-laravel-postal-code-validation)[sunspikes/clamav-validator

Custom Laravel 5 anti-virus validator for file uploads.

3651.8M3](/packages/sunspikes-clamav-validator)[laravel-validation-rules/credit-card

Validate credit card number, expiration date, cvc

2412.2M5](/packages/laravel-validation-rules-credit-card)

PHPackages © 2026

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