SkillAgentSearch skills...

Blasp

๐Ÿคฌ ๐Ÿšซ Blasp is a profanity filter package for Laravel that helps detect and mask profane words in a given sentence. It offers a robust set of features for handling variations of offensive language, including substitutions, obscured characters, and doubled letters.

Install / Use

/learn @Blaspsoft/Blasp

README

<p align="center"> <img src="./assets/icon.png" alt="Blasp Icon" width="150" height="150"/> </p>

Official API Available! This package powers 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.

<p align="center"> <a href="https://github.com/Blaspsoft/blasp/actions/workflows/main.yml"><img alt="GitHub Workflow Status (main)" src="https://github.com/Blaspsoft/blasp/actions/workflows/main.yml/badge.svg"></a> <a href="https://packagist.org/packages/blaspsoft/blasp"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/blaspsoft/blasp"></a> <a href="https://packagist.org/packages/blaspsoft/blasp"><img alt="Latest Version" src="https://img.shields.io/packagist/v/blaspsoft/blasp"></a> <a href="https://packagist.org/packages/blaspsoft/blasp"><img alt="License" src="https://img.shields.io/packagist/l/blaspsoft/blasp"></a> </p>

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

  • 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

  • PHP 8.2+
  • Laravel 8.0+

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

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

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

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

| Method | Returns | Description | |--------|---------|-------------| | 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

The regex driver detects obfuscated profanity:

| Type | Example | Detected As | |------|---------|-------------| | Straight 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:

| Type | Example | Detected As | |------|---------|-------------| | Phonetic 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

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

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

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

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

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

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

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

// Using the short alias (recommended)
Route::post('/comment', CommentController::class)

Related Skills

View on GitHub
GitHub Stars325
CategoryContent
Updated5h ago
Forks25

Languages

PHP

Security Score

100/100

Audited on Mar 26, 2026

No findings