azrael-antismurf
Version:
Lightweight smurf/dupe-detection scoring for signups: disposable domains, fuzzy matches, entropy, IP/device reuse. Includes a daily disposable-domain refresher, CLI, and multi-source merge.
92 lines (69 loc) • 2.44 kB
Markdown
# azrael
Lightweight, dependency-free risk scoring to spot smurf / duplicate accounts during signup.
**Signals included:**
- Disposable domains (pluggable list)
- Email & username normalization
- Fuzzy similarity (Levenshtein)
- Shannon entropy (randomness) & vowel ratio heuristic
- IP/device fingerprint reuse
- Optional MX check for email domains
- **Daily disposable-domain refresher** from one or **multiple** URLs (newline- or JSON-array formatted) with merge + dedup
- **CLI**: `npx azrael refresh <urls...>` to fetch, merge, and print or write to file
## Install
```bash
npm i azrael
```
## Quick start (CommonJS)
```js
const az = require('azrael');
// Optional: start daily refresh from multiple curated lists
az.startDisposableRefresher({
urls: [
'https://your.cdn.example/disposable_1.txt',
'https://another.example/domains.json'
],
intervalMs: 24 * 60 * 60 * 1000,
logger: console,
});
const score = az.scoreAccount({ email: 'u.ser+tag@gmail.com', username: 'userone_' });
console.log({ score, decision: az.decideAction(score) });
```
## CLI
Fetch, merge, dedup, and output a combined list.
```bash
npx azrael refresh https://list1.txt https://list2.json \
--out disposable_domains.txt # optional: write to file
--json # output JSON array instead of newline list
--silent # suppress logs
```
Without `--out`, prints to `stdout`.
## Refresher options
```js
az.startDisposableRefresher({
urls: [url1, url2, ...], // preferred
url: url1, // still supported for single source
intervalMs: 86_400_000,
initial: true,
logger: console,
parse, // optional custom parser
});
az.stopDisposableRefresher();
// Manual one-off refresh
await az.refreshDisposableDomainsFromUrls([url1, url2], { logger, parse });
```
Accepted formats:
- Newline-separated `domain.tld` per line (comments starting with `#` ignored)
- JSON array of strings: `["mailinator.com", "yopmail.com"]`
## API
```js
scoreAccount(input, weights?) => number // 0..100
decideAction(score, thresholds?) => 'allow' | 'challenge' | 'review' | 'block'
// helpers
normalizeEmail, normalizeUsername, levenshtein, normalizedDistance,
shannonEntropy, vowelRatio, isDisposableDomain, getEmailParts, hasMXRecord,
setDisposableDomains, addDisposableDomains, getDisposableDomains,
startDisposableRefresher, stopDisposableRefresher,
refreshDisposableDomainsFromUrl, refreshDisposableDomainsFromUrls,
mergeDisposableDomainLists,
defaultWeights, defaultThresholds
```