Metadata-Version: 2.4
Name: dismoy
Version: 1.0.0
Summary: All-in-one Discord selfbot — moderation, utility, fun, monitoring. Hybrid plugin system.
Author: mocasus
License: MIT
Project-URL: Homepage, https://github.com/mocasus/dismoy
Project-URL: Repository, https://github.com/mocasus/dismoy
Project-URL: Issues, https://github.com/mocasus/dismoy/issues
Keywords: discord,selfbot,automation,moderation,utility,monitoring
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: discord.py-self>=2.0.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Dynamic: license-file

# 🎫 Dismoy

<p align="center">
  <img src="assets/banner.png" alt="Dismoy Banner" width="640">
</p>

<p align="center">
  <strong>All-in-one Discord selfbot — moderation, utility, fun, monitoring.</strong><br>
  Hybrid plugin system. Triple distribution (pip · npm · git clone).
</p>

<p align="center">
  <img src="https://img.shields.io/badge/version-1.0.0-blue" alt="Version">
  <img src="https://img.shields.io/badge/Python-3.9+-brightgreen" alt="Python">
  <img src="https://img.shields.io/badge/Node.js-14+-brightgreen" alt="Node">
  <img src="https://img.shields.io/badge/discord.py--self-2.1.0-purple" alt="discord.py-self">
  <img src="https://img.shields.io/badge/license-MIT-green" alt="License">
  <img src="https://img.shields.io/badge/preview-pages.dev-orange" alt="Preview">
</p>

<p align="center">
  <a href="#-quick-start">Quick Start</a> ·
  <a href="#-what-is-this">What is this?</a> ·
  <a href="#-features">Features</a> ·
  <a href="#-commands">Commands</a> ·
  <a href="#-plugin-system">Plugins</a> ·
  <a href="#-architecture">Architecture</a> ·
  <a href="#-file-reference">File Reference</a>
</p>

---

## ⚠️ Disclaimer

**Automating user accounts violates Discord's Terms of Service.** Using Dismoy may result in account termination. This project is for educational purposes only. The authors are not responsible for any account bans or data loss. Use at your own risk.

---

## 🔍 What is this?

Dismoy is a **Discord selfbot** — a script that automates a Discord **user account** (not a bot account). It uses [`discord.py-self`](https://github.com/dolfies/discord.py-self), a fork of discord.py that connects to Discord's **user API** (the same API the official Discord client uses), instead of the bot API.

### Selfbot vs Bot — what's the difference?

| Aspect | Bot Account | Selfbot (User Account) |
|--------|-------------|------------------------|
| Token type | Bot token (from Dev Portal) | User token (from client) |
| Library | discord.py, discord.js | discord.py-self, discord.js-self |
| Slash commands | ✅ Yes | ❌ No (interactions = bot only) |
| Intents limit | Capped (message content needs approval) | No limits — sees everything |
| Voice | ✅ Yes (with voice lib) | ✅ Yes (native) |
| ToS | ✅ Compliant | ❌ Violates ToS |
| Detection | Impossible (official API) | Detectable via patterns |

### What does Dismoy do?

Dismoy is an **all-in-one automation toolkit** for your Discord user account. It runs in the background and provides:

- **Moderation tools** — automatically delete spam, filter keywords, protect your DMs
- **Utility tools** — auto-reply when AFK, schedule messages, clean up your DMs, backup servers
- **Fun tools** — auto-react to messages, snipe nitro giveaways, mass-react in channels
- **Monitoring tools** — log all messages, track when users go online/offline, scrape server data

All of this runs **as your account** — no bot invite needed, no permissions to set up, just your token.

### Why was this built?

This project was inspired by the [discord-userdoccers](https://github.com/discord-userdoccers/discord-userdoccers) project — a community effort to document Discord's undocumented user API. Dismoy is a practical application of that knowledge: a working, modular, extensible selfbot built on top of that API.

---

## 🚀 Quick Start

### Option A: npm (recommended)

```bash
npm install -g dismoy
dmy              # First run → setup wizard → auto-start
```

Or without installing:

```bash
npx dismoy       # Same flow
```

### Option B: pip

```bash
pip install dismoy
dismoy           # First run → setup wizard → auto-start
```

### Option C: git clone

```bash
git clone https://github.com/mocasus/dismoy.git
cd dismoy
pip install -r requirements.txt
python main.py   # First run → setup wizard → auto-start
```

All three methods produce the same result. The npm wrapper is a thin shim that installs the Python package under the hood — it handles venv creation, dependency installation, and updates automatically.

---

## ✨ Features

### 🛡️ Moderation Module

Automated protection for servers and DMs you're in.

| Feature | What it does | Config key |
|---------|-------------|------------|
| **Keyword Filter** | Auto-deletes any message containing filtered words. Manage via `!filter add/remove/list`. | `filtered_words` |
| **Anti-Spam** | Detects rapid message bursts (5+ messages in 5 seconds) and auto-deletes them. Per-user tracking with sliding window. | `antispam` |
| **DM Guard** | Restricts DM interactions to friends only. Toggle on/off via `!dmguard`. | `dmguard` |

**How anti-spam works:** Each user has a `deque(maxlen=10)` that stores message timestamps. When a new message arrives, timestamps older than 5 seconds are popped. If 5+ timestamps remain, the message is deleted and the counter resets. This is a sliding window approach — more accurate than fixed window.

### 🔧 Utility Module

Quality-of-life automation for your account.

| Feature | What it does | Command |
|---------|-------------|---------|
| **AFK Mode** | Auto-replies to mentions with a custom message. Includes timestamp of when you went AFK. | `!afk <message>` |
| **Auto-Reply** | Trigger-based responses — if someone types a trigger word, bot replies automatically. Multiple rules supported. | `!autoreply add <trigger> \| <response>` |
| **Scheduled Messages** | Send messages at a specific time (HH:MM format). Background task checks every 30 seconds. | `!schedule <HH:MM> <message>` |
| **DM Cleaner** | Bulk-delete your own messages in any DM channel. 0.5s delay between deletions for rate limit safety. | `!dmclean <count>` |
| **Guild Backup** | Exports guild channels, roles, and member count to a timestamped JSON file in `~/.dismoy/backups/`. | `!backup <guild_id>` |

**How scheduled messages work:** A background `asyncio` task runs every 30 seconds, comparing current time (HH:MM) against scheduled items. If a match is found, the message is sent and the item is removed from the queue. Messages that don't match are kept for the next cycle.

### 🎉 Fun Module

Social automation and sniping tools.

| Feature | What it does | Command |
|---------|-------------|---------|
| **Auto-React** | Automatically adds a chosen emoji reaction to every message you send. | `!autoreact <emoji>` |
| **Nitro Sniper** | Detects Discord nitro gift links in any message across all servers + DMs. Extracts the gift code and attempts to claim it. | `!sniper` (toggle) |
| **Giveaway Sniper** | Detects giveaway messages from known giveaway bots. Auto-reacts with 🎉 and clicks "Join"/"Enter" buttons if present. | `!sniper` (toggle) |
| **Mass React** | Reacts to the last 20 messages in a channel with a chosen emoji. 0.3s delay between reactions for rate limit safety. | `!massreact <emoji>` |

**How nitro sniper works:** Every incoming message is scanned for `discord.gift/` or `discordapp.com/gifts/` URLs. If found, the gift code is extracted via regex. After a 1-second delay (to avoid suspicion), the bot attempts to redeem the code. Known giveaway bot IDs are checked for giveaway detection.

### 👁️ Monitoring Module

Surveillance and logging tools.

| Feature | What it does | Command |
|---------|-------------|---------|
| **Message Logger** | Logs every incoming message to a daily JSONL file (`~/.dismoy/logs/messages/YYYYMMDD.jsonl`). Each entry includes timestamp, guild, channel, author, content, and attachment URLs. | `!log on/off` |
| **Online Tracker** | Monitors status changes (online/idle/dnd/offline) for specific users. Uses the `on_member_update` event. Logs to console + activity feed. | `!track <user_id>` |
| **Server Activity** | Maintains a rolling log of the last 100 events per guild (messages, status changes). Viewable via command. | `!activity` |
| **Scraper** | Exports guild members (up to 1000) and channels to a JSON file in `~/.dismoy/scrapes/`. Includes name, ID, display name, roles, join date. | `!scrape <guild_id>` |

**How message logger works:** Each message is serialized to a JSON object and appended to a JSONL (JSON Lines) file. JSONL format means one JSON object per line — easy to parse with `jq`, `python -m json.tool`, or any JSONL reader. Files are rotated daily.

---

## 📋 Commands

Prefix is configurable (default `!`). All commands are typed as your own messages and executed instantly.

### Core Commands

| Command | Description |
|---------|-------------|
| `!ping` | Check bot latency |
| `!help` | Show all available commands grouped by module |
| `!modules` | Show loaded module status (enabled/disabled per module) |
| `!reload` | Reload all modules without restarting the bot |

### Moderation

| Command | Description |
|---------|-------------|
| `!filter add <word>` | Add keyword to filter list |
| `!filter remove <word>` | Remove keyword from filter |
| `!filter list` | Show all filtered keywords |
| `!antispam` | Toggle anti-spam protection |
| `!dmguard` | Toggle DM guard |

### Utility

| Command | Description |
|---------|-------------|
| `!afk <message>` | Set AFK mode with custom message |
| `!afk` | Disable AFK mode |
| `!autoreply add <trigger> \| <response>` | Add auto-reply rule (pipe separates trigger from response) |
| `!autoreply list` | Show all auto-reply rules |
| `!autoreply remove <trigger>` | Remove auto-reply rule |
| `!schedule <HH:MM> <message>` | Schedule a message (24h format) |
| `!dmclean <count>` | Delete your last N messages in current DM channel |
| `!backup <guild_id>` | Export guild data to JSON file |

### Fun

| Command | Description |
|---------|-------------|
| `!autoreact <emoji>` | Enable auto-react with chosen emoji |
| `!autoreact off` | Disable auto-react |
| `!massreact <emoji>` | React to last 20 messages with emoji |
| `!sniper` | Toggle nitro + giveaway sniper |
| `!sniper status` | Show sniper status |

### Monitoring

| Command | Description |
|---------|-------------|
| `!log on` / `!log off` | Toggle message logging |
| `!track <user_id>` | Start tracking a user's online status |
| `!track list` | Show all tracked users |
| `!track clear` | Clear tracked users |
| `!scrape <guild_id>` | Scrape guild members + channels to JSON |
| `!activity` | Show recent server activity (last 10 events) |

---

## 🔧 Setup Wizard

First run triggers an interactive setup wizard:

```
╔══════════════════════════════════════╗
║   🎫 Dismoy — Discord Selfbot       ║
║   v1.0.0 • mocasus                  ║
╚══════════════════════════════════════╝

🎫 Welcome to Dismoy setup!

🔑 Discord user token: ****
⚙️  Command prefix [!]: !
📦 Enable moderation? [Y/n]: y
📦 Enable utility? [Y/n]: y
📦 Enable fun? [Y/n]: y
📦 Enable monitoring? [Y/n]: y
🔌 Enable custom plugins? [Y/n]: y
📝 Log level [INFO]: INFO

✅ Config saved to ~/.dismoy/config.yaml
🚀 Starting Dismoy...
```

The wizard creates a config file at `~/.dismoy/config.yaml` and a plugins directory at `~/.dismoy/plugins/`.

---

## ⚙️ Configuration

Config is stored at `~/.dismoy/config.yaml`:

```yaml
token: "your_user_token"
prefix: "!"
modules:
  moderation:
    enabled: true
    settings:
      filtered_words: ["spam", "scam"]
      antispam: false
      dmguard: false
  utility:
    enabled: true
    settings: {}
  fun:
    enabled: true
    settings:
      nitro_sniper: true
      giveaway_sniper: true
  monitoring:
    enabled: true
    settings:
      message_logging: false
plugins:
  enabled: true
  directory: ~/.dismoy/plugins
logging:
  level: INFO
  file: ~/.dismoy/logs/dismoy.log
```

### Directory Structure After Setup

```
~/.dismoy/
├── config.yaml              # Main configuration
├── plugins/                 # Drop .py files here → auto-loaded
├── logs/
│   ├── dismoy.log           # Main log file
│   └── messages/            # Message logger output
│       └── 20260708.jsonl   # Daily JSONL files
├── backups/                 # Guild backup JSON files
├── scrapes/                 # Scraper output JSON files
└── venv/                    # Python virtual environment (npm only)
```

---

## 🔌 Plugin System

Dismoy supports **custom plugins** — drop a `.py` file in `~/.dismoy/plugins/` and it auto-loads on startup. No restart needed for development (use `!reload`).

### Plugin API

```python
"""My custom plugin."""

async def setup(bot):
    """Called when plugin loads."""
    print("My plugin loaded!")

async def on_ready(bot):
    """Called when bot connects to Discord."""
    print(f"Connected as {bot.user}")

async def on_message(bot, message):
    """Called on every incoming message."""
    if message.author.id == bot.user.id:
        return  # Skip own messages

    # Your logic here
    if "hello" in message.content.lower():
        print(f"Someone said hello in {message.channel}")
```

### Available Hooks

| Hook | When it's called | Parameters |
|------|-------------------|------------|
| `setup(bot)` | Plugin load | `bot` — DismoyBot instance (discord.Client subclass) |
| `on_ready(bot)` | Bot connected to Discord | `bot` — DismoyBot instance |
| `on_message(bot, message)` | Any incoming message | `bot`, `message` — discord.Message object |

### Plugin Objects

- **`bot`** — Full `discord.Client` instance with all discord.py-self methods
- **`config`** — Bot config dict (loaded from `config.yaml`)
- **`bot.prefix`** — Command prefix string
- **`bot.handle_command`** — Override to add custom commands (see built-in modules for examples)

### Example: Custom Command Plugin

```python
"""Custom commands plugin."""

async def setup(bot):
    original = bot.handle_command

    async def extended_handle(message):
        from dismoy.utils.helpers import extract_code_from_message
        command, args = extract_code_from_message(message.content, bot.prefix)

        if command == "hello":
            await message.edit(content="👋 Hello from my plugin!")
            return

        await original(message)  # Fall through to other handlers

    bot.handle_command = extended_handle
```

An example plugin is included at [`dismoy/plugins/example_plugin.py`](dismoy/plugins/example_plugin.py).

---

## 🏗️ Architecture

### Overview

Dismoy uses a **hybrid modular architecture**:

1. **Core** — `DismoyBot` class (extends `discord.Client`), handles connection, event dispatch, command routing
2. **Built-in modules** — 4 modules loaded based on config. Each module can register commands, hook into events, and maintain state
3. **Plugin system** — Custom plugins loaded from `~/.dismoy/plugins/`. Same API as built-in modules

### How Modules Work

Each module is a Python file with these optional functions:

```python
async def setup(bot, settings):
    """Called on load. Register commands, initialize state."""

async def on_ready(bot):
    """Called when bot connects to Discord."""

async def on_message(bot, message):
    """Called on every incoming message."""
```

The bot's `on_message` event **chains through all enabled modules** in order: moderation → utility → fun → monitoring → plugins. Each module's `on_message` is called sequentially.

### Command Chaining

Commands use a **decorator chain pattern**. Each module wraps `bot.handle_command` with its own handler:

```
User sends: "!filter add spam"
         │
         ▼
bot.handle_command (outermost = last loaded module)
         │
         ▼
monitoring.handle_command → not my command → pass through
         │
         ▼
fun.handle_command → not my command → pass through
         │
         ▼
utility.handle_command → not my command → pass through
         │
         ▼
moderation.handle_command → "filter add" → handle → return
```

If no module handles the command, the original handler runs (core commands like `!ping`, `!help`).

### How the npm Wrapper Works

The npm package contains only `cli.js` (~7KB, zero dependencies). It:

1. **First run:** Clones the repo to `~/.dismoy/`, creates a Python venv, installs dependencies, runs setup wizard
2. **Subsequent runs:** Spawns Python directly from venv
3. **Update:** `git pull` + `pip install -r requirements.txt`
4. **Commands:** `dmy setup`, `dmy start`, `dmy update`, `dmy modules`, `dmy version`

The short command `dmy` is provided as a convenience alias.

### Data Flow

```
Discord Gateway
       │
       ▼
discord.py-self (websocket)
       │
       ▼
DismoyBot.on_message()
       │
       ├── Is it a command? → handle_command chain → module handles it
       │
       └── Not a command → on_message chain → each module processes it
                               │
                               ├── moderation: keyword filter + antispam check
                               ├── utility: AFK response + auto-reply check
                               ├── fun: nitro/giveaway detection
                               └── monitoring: log to JSONL + track activity
```

---

## 📁 File Reference

Every file in the repo, explained:

### Root

| File | Purpose |
|------|---------|
| `main.py` | Git clone entry point. Calls `dismoy.cli.main()`. |
| `pyproject.toml` | pip package config. Defines `dismoy` console script entry point, dependencies, metadata. |
| `requirements.txt` | Python dependencies: discord.py-self, pyyaml, rich. |
| `LICENSE` | MIT license. |
| `.gitignore` | Ignores `__pycache__`, `.env`, `config.yaml`, `data/`, `logs/`, `node_modules/`. |
| `README.md` | This file. |
| `assets/logo.png` | Placeholder logo (replace with your own). |
| `assets/banner.png` | Placeholder banner. |

### `dismoy/` — Core Package

| File | Purpose |
|------|---------|
| `__init__.py` | Package metadata: `__version__`, `__author__`, `__license__`. |
| `__main__.py` | Entry point for `python -m dismoy`. Calls `cli.main()`. |
| `cli.py` | CLI argument parsing + interactive setup wizard. Handles `setup`, `start`, `modules`, `version` subcommands. |
| `bot.py` | `DismoyBot` class — extends `discord.Client`. Manages module loading, event dispatch, command routing, plugin loading. |
| `config.py` | Config management — loads/saves YAML at `~/.dismoy/config.yaml`. Provides `DEFAULT_CONFIG_DIR`, `DEFAULT_CONFIG_FILE`, `DEFAULT_PLUGINS_DIR`. |

### `dismoy/modules/` — Built-in Modules

| File | Module | Key Functions |
|------|--------|---------------|
| `moderation.py` | 🛡️ Moderation | Keyword filter (`filtered_words` set), anti-spam (sliding window deque per user), DM guard toggle. Commands: `filter`, `antispam`, `dmguard`. |
| `utility.py` | 🔧 Utility | AFK mode (auto-reply on mention), auto-reply (trigger→response dict), scheduled messages (background asyncio task, 30s interval), DM cleaner (bulk delete with rate limit), guild backup (JSON export). Commands: `afk`, `autoreply`, `schedule`, `dmclean`, `backup`. |
| `fun.py` | 🎉 Fun | Auto-react (emoji on own messages), nitro sniper (regex URL detection + code extraction), giveaway sniper (known bot ID detection + auto-react + button click), mass react. Commands: `autoreact`, `massreact`, `sniper`. |
| `monitoring.py` | 👁️ Monitoring | Message logger (JSONL daily files), online tracker (`on_member_update` event), server activity (rolling 100-event log per guild), guild scraper (up to 1000 members + channels to JSON). Commands: `log`, `track`, `scrape`, `activity`. |

### `dismoy/plugins/` — Plugin System

| File | Purpose |
|------|---------|
| `loader.py` | `PluginLoader` class — scans directory for `.py` files, loads each as a Python module via `importlib`, calls `setup()` hook. Supports `load_all()` and `reload_all()`. |
| `example_plugin.py` | Template plugin with all hooks demonstrated. Copy this to `~/.dismoy/plugins/` to start. |

### `dismoy/utils/` — Utilities

| File | Purpose |
|------|---------|
| `__init__.py` | Exports: `setup_logger`, `rate_limit`, `extract_code_from_message`, `is_nitro_gift`, `is_giveaway_bot`. |
| `logger.py` | Sets up `RichHandler` for colored console output + optional file handler for persistent logging. |
| `helpers.py` | `rate_limit()` decorator (sliding window), `extract_code_from_message()` (parses `!command args` format), `is_nitro_gift()` (regex for Discord gift URLs), `is_giveaway_bot()` (checks against known giveaway bot IDs). |

### `npm/` — npm Wrapper Package

| File | Purpose |
|------|---------|
| `package.json` | npm package config. Defines `dismoy` and `dmy` bin commands. Zero runtime dependencies. |
| `cli.js` | Thin CLI bridge (~7KB). Handles first-run setup (clone + venv + install), start, update, modules, version commands. Uses only Node.js built-in modules (no npm deps). |

### `.github/workflows/`

| File | Purpose |
|------|---------|
| `ci.yml` | GitHub Actions CI. Runs `py_compile` on all Python files across Python 3.9, 3.10, 3.11, 3.12. |

---

## 🎨 Logo

The current logo is a **placeholder**. Replace `assets/logo.png` with your own.

**AI generation prompt (two-tone flat vector):**

> Minimalist logo for a Discord selfbot called "Dismoy". A ticket icon (stubby rectangle with notch cutouts on both sides) in white, centered on a dark rounded square background (#1E1F22). Below the ticket, a small "D" monogram. Two-tone flat vector only — background dark, icon white. No gradients, no glow, no sparkle, no 3D effects. Clean geometric style.

Generate this in ChatGPT, Midjourney, or Ideogram, then replace `assets/logo.png` and `assets/banner.png`.

---

## 🔐 Getting Your Discord User Token

1. Open Discord in your browser (not the desktop app)
2. Press `F12` to open Developer Tools
3. Go to the **Network** tab
4. Send any message in any channel
5. Find the request in the Network tab (look for `messages` endpoint)
6. In the **Request Headers**, find `Authorization`
7. Copy the value — that's your user token

**⚠️ NEVER share your token. Anyone with your token has full access to your account.**

---

## 📦 Distribution

| Method | Command | Entry Point | Short Command |
|--------|---------|-------------|---------------|
| **npm** | `npm install -g dismoy` | `dismoy` | `dmy` |
| **pip** | `pip install dismoy` | `dismoy` | — |
| **npx** | `npx dismoy` | (no install) | — |
| **git clone** | `git clone` + `python main.py` | `python main.py` | — |

### Publishing

**npm:**
```bash
cd npm && npm publish
```

**pip:**
```bash
python -m build && twine upload dist/*
```

---

## 📄 License

MIT © [mocasus](https://github.com/mocasus)
