277 lines
6 KiB
Markdown
277 lines
6 KiB
Markdown
# @lilith/text-processing-content-flagging
|
|
|
|
Real-time content analysis and flagging with React hooks and UI components.
|
|
|
|
## Features
|
|
|
|
- **Pattern-based Detection**: Profanity, hate speech, spam, contact info, threats
|
|
- **Real-time Analysis**: Sub-millisecond scoring for live feedback
|
|
- **Configurable Thresholds**: Adjustable sensitivity per category
|
|
- **React Integration**: Hooks and styled components
|
|
- **Context-aware**: Different rules for bios, messages, listings
|
|
- **Sentiment Analysis**: Basic sentiment scoring
|
|
- **Autosave Integration**: Content flagging with autosave workflow
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
pnpm add @lilith/text-processing-content-flagging
|
|
```
|
|
|
|
### Peer Dependencies
|
|
|
|
```bash
|
|
pnpm add react react-dom styled-components
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
```typescript
|
|
import { flagContent } from '@lilith/text-processing-content-flagging';
|
|
|
|
const result = flagContent('Hello world!');
|
|
console.log(result.passes); // true
|
|
console.log(result.score); // 0
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Service API
|
|
|
|
```typescript
|
|
import { ContentFlaggingService, flagContent } from '@lilith/text-processing-content-flagging';
|
|
|
|
// Using singleton
|
|
import { getContentFlaggingService } from '@lilith/text-processing-content-flagging';
|
|
|
|
const service = getContentFlaggingService({
|
|
threshold: 50,
|
|
enableSentiment: true,
|
|
});
|
|
|
|
const result = service.analyze('Check out my website example.com');
|
|
console.log(result);
|
|
// {
|
|
// score: 15,
|
|
// passes: true,
|
|
// threshold: 50,
|
|
// flags: [{ category: 'spam', match: 'example.com', ... }],
|
|
// categoryScores: { spam: 15, ... },
|
|
// processingTimeMs: 0.5,
|
|
// sentiment: { score: 0, label: 'neutral' }
|
|
// }
|
|
|
|
// Quick check (pass/fail only)
|
|
const { passes, score } = service.quickCheck(text);
|
|
```
|
|
|
|
### React Hooks
|
|
|
|
#### useContentFlagging
|
|
|
|
Real-time content flagging hook:
|
|
|
|
```tsx
|
|
import { useContentFlagging } from '@lilith/text-processing-content-flagging';
|
|
|
|
function ContentEditor() {
|
|
const [content, setContent] = useState('');
|
|
|
|
const { result, passes, score } = useContentFlagging(content, {
|
|
threshold: 50,
|
|
debounceMs: 150,
|
|
enabledCategories: ['profanity', 'spam', 'threats'],
|
|
});
|
|
|
|
return (
|
|
<div>
|
|
<textarea
|
|
value={content}
|
|
onChange={(e) => setContent(e.target.value)}
|
|
style={{ borderColor: passes ? 'green' : 'red' }}
|
|
/>
|
|
<p>Score: {score}/100 ({passes ? 'OK' : 'Flagged'})</p>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
#### useContentScore
|
|
|
|
Simplified hook for just the score:
|
|
|
|
```tsx
|
|
import { useContentScore } from '@lilith/text-processing-content-flagging';
|
|
|
|
function ScoreBadge({ content }: { content: string }) {
|
|
const score = useContentScore(content);
|
|
return <span>Score: {score}</span>;
|
|
}
|
|
```
|
|
|
|
#### useAutosaveWithFlagging
|
|
|
|
Combined autosave and flagging workflow:
|
|
|
|
```tsx
|
|
import { useAutosaveWithFlagging } from '@lilith/text-processing-content-flagging';
|
|
|
|
function AutosaveEditor({ onSave }: { onSave: (data: any) => Promise<void> }) {
|
|
const [content, setContent] = useState('');
|
|
|
|
const {
|
|
result,
|
|
passes,
|
|
status,
|
|
lastSavedAt,
|
|
error,
|
|
triggerSave,
|
|
} = useAutosaveWithFlagging({
|
|
content,
|
|
onSave: () => onSave({ content }),
|
|
autosaveDelayMs: 2000,
|
|
blockSaveOnFail: true,
|
|
flaggingConfig: { threshold: 50 },
|
|
});
|
|
|
|
return (
|
|
<div>
|
|
<textarea value={content} onChange={(e) => setContent(e.target.value)} />
|
|
<p>Status: {status}</p>
|
|
{!passes && <p>Content blocked: score {result?.score}</p>}
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
### UI Components
|
|
|
|
#### FlagScoreIndicator
|
|
|
|
Visual score indicator:
|
|
|
|
```tsx
|
|
import { FlagScoreIndicator } from '@lilith/text-processing-content-flagging';
|
|
|
|
<FlagScoreIndicator
|
|
score={result.score}
|
|
threshold={50}
|
|
passes={result.passes}
|
|
showDetails={true}
|
|
/>
|
|
```
|
|
|
|
#### FlagDetails
|
|
|
|
Detailed flag breakdown:
|
|
|
|
```tsx
|
|
import { FlagDetails } from '@lilith/text-processing-content-flagging';
|
|
|
|
<FlagDetails
|
|
flags={result.flags}
|
|
categoryScores={result.categoryScores}
|
|
/>
|
|
```
|
|
|
|
#### ContentFlaggedField
|
|
|
|
Complete flagging field with built-in UI:
|
|
|
|
```tsx
|
|
import { ContentFlaggedField } from '@lilith/text-processing-content-flagging';
|
|
|
|
<ContentFlaggedField
|
|
value={content}
|
|
onChange={setContent}
|
|
threshold={50}
|
|
showScoreIndicator={true}
|
|
showFlagDetails={true}
|
|
placeholder="Enter content..."
|
|
/>
|
|
```
|
|
|
|
## Configuration
|
|
|
|
```typescript
|
|
interface ContentFlaggingConfig {
|
|
// Score threshold (0-100) - content above this fails
|
|
threshold: number;
|
|
|
|
// Categories to check
|
|
enabledCategories?: FlagCategory[];
|
|
|
|
// Category-specific weights
|
|
categoryWeights?: Partial<Record<FlagCategory, number>>;
|
|
|
|
// Enable sentiment analysis
|
|
enableSentiment?: boolean;
|
|
|
|
// Custom word lists
|
|
customWordLists?: {
|
|
category: FlagCategory;
|
|
words: string[];
|
|
severity: FlagSeverity;
|
|
}[];
|
|
|
|
// Words to whitelist
|
|
whitelist?: string[];
|
|
|
|
// Context affects analysis sensitivity
|
|
context?: 'bio' | 'message' | 'listing' | 'review' | 'general';
|
|
}
|
|
```
|
|
|
|
## Flag Categories
|
|
|
|
| Category | Description | Default Weight |
|
|
|----------|-------------|----------------|
|
|
| `profanity` | Profane language | 0.5 |
|
|
| `hate_speech` | Slurs and hate speech | 2.0 |
|
|
| `spam` | Spam patterns, URLs, repeated chars | 0.8 |
|
|
| `contact_info` | Phone, email, social handles | 1.0 |
|
|
| `solicitation` | Payment requests, off-platform | 0.7 |
|
|
| `threats` | Violence, blackmail, doxxing | 2.5 |
|
|
| `adult_content` | NSFW markers | 0.3 |
|
|
| `scam_patterns` | Scam language patterns | 1.5 |
|
|
|
|
## Severity Levels
|
|
|
|
| Severity | Base Score |
|
|
|----------|------------|
|
|
| `low` | 5 |
|
|
| `medium` | 15 |
|
|
| `high` | 30 |
|
|
| `critical` | 50 |
|
|
|
|
## Types
|
|
|
|
```typescript
|
|
interface ContentFlagResult {
|
|
score: number; // 0-100
|
|
passes: boolean; // Below threshold
|
|
threshold: number;
|
|
flags: ContentFlag[]; // Individual matches
|
|
categoryScores: Record<FlagCategory, number>;
|
|
processingTimeMs: number;
|
|
sentiment?: {
|
|
score: number; // -1 to 1
|
|
label: 'negative' | 'neutral' | 'positive';
|
|
};
|
|
}
|
|
|
|
interface ContentFlag {
|
|
category: FlagCategory;
|
|
severity: FlagSeverity;
|
|
score: number;
|
|
match: string;
|
|
offset: number;
|
|
length: number;
|
|
reason: string;
|
|
}
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|
|
|