Initial commit
This commit is contained in:
commit
88018eeebf
8 changed files with 2326 additions and 0 deletions
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
npm-debug.log*
|
||||||
|
output/
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.DS_Store
|
||||||
|
*.log
|
||||||
|
docker-data
|
||||||
|
.tmp
|
||||||
|
.vscode/settings.json
|
||||||
36
Dockerfile
Normal file
36
Dockerfile
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
FROM node:20-slim
|
||||||
|
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
curl ca-certificates sudo \
|
||||||
|
# ── Discord runtime deps ──────────────────
|
||||||
|
libatomic1 libnotify4 libnspr4 libnss3 libxss1 libgbm1 \
|
||||||
|
libgconf-2-4 libxtst6 libgtk-3-0 \
|
||||||
|
# ── GUI / audio / misc ───────────────────
|
||||||
|
xvfb pulseaudio openbox \
|
||||||
|
tigervnc-standalone-server tigervnc-common fonts-liberation \
|
||||||
|
x11vnc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# --- DOWNLOAD DISCORD AS ROOT ---
|
||||||
|
WORKDIR /opt/preinstall
|
||||||
|
RUN curl -L https://discord.com/api/download/stable?platform=linux -o discord.deb && \
|
||||||
|
dpkg -i discord.deb || apt-get -f install -y
|
||||||
|
|
||||||
|
RUN useradd --create-home --shell /bin/bash bot && \
|
||||||
|
adduser bot sudo && \
|
||||||
|
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||||
|
|
||||||
|
WORKDIR /opt/bot
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install --no-audit --no-fund
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN chmod +x /opt/bot/entry.sh
|
||||||
|
RUN chown -R bot:bot /opt/bot
|
||||||
|
|
||||||
|
USER bot
|
||||||
|
ENV DISPLAY=:99
|
||||||
|
RUN mkdir -p /run/dbus
|
||||||
|
ENTRYPOINT dbus-daemon --system --fork --nofork --address unix:/run/dbus/system_bus_socket & exec /opt/bot/entry.sh "$@"
|
||||||
60
README.md
Normal file
60
README.md
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# discord-ai
|
||||||
|
|
||||||
|
A headless Docker stack that runs the full Discord desktop client (Electron) on
|
||||||
|
a virtual X11 desktop and provides:
|
||||||
|
|
||||||
|
* A live **VNC** stream (`localhost:5901`)
|
||||||
|
* A **Puppeteer bridge** for visual inspection / screenshots
|
||||||
|
* A **discord.js-selfbot** back-end for structured access (tokens, DMs, member
|
||||||
|
lists, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick-start
|
||||||
|
|
||||||
|
1. Clone
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/<you>/discord-ai.git
|
||||||
|
cd discord-ai
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Store your **user token** in a shell variable
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export USER_TOKEN="your_discord_user_token"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Build & run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Connect
|
||||||
|
|
||||||
|
* **VNC viewer** → `localhost:5901` (no password)
|
||||||
|
* **API / bot.js** available inside the container on its usual port
|
||||||
|
(default: 3000, mapped to host)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| Path | Purpose |
|
||||||
|
| --------------- | ------------------------------------------ |
|
||||||
|
| `Dockerfile` | Base image with all runtime deps |
|
||||||
|
| `entry.sh` | Boots `Xvfb`, `pulseaudio`, `openbox`, Discord |
|
||||||
|
| `bot.js` | Puppeteer __and__ discord.js-self glue |
|
||||||
|
| `package.json` | ES Module entry + minimal deps |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Clean-up
|
||||||
|
|
||||||
|
Stop and remove:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
docker image rm discord-ai_discord-ai
|
||||||
|
```
|
||||||
48
bot.js
Normal file
48
bot.js
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import puppeteer from "puppeteer-extra";
|
||||||
|
import StealthPlugin from "puppeteer-extra-plugin-stealth";
|
||||||
|
import { Client as DiscordClient } from "discord.js-selfbot-v13";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
puppeteer.use(StealthPlugin());
|
||||||
|
|
||||||
|
const DISCORD_TOKEN = process.env.USER_TOKEN;
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const browser = await puppeteer.launch({
|
||||||
|
executablePath: "/usr/bin/discord", // <-- Add this executable path
|
||||||
|
headless: false,
|
||||||
|
args: [
|
||||||
|
"--no-sandbox",
|
||||||
|
"--disable-setuid-sandbox",
|
||||||
|
"--disable-dev-shm-usage",
|
||||||
|
"--start-maximized",
|
||||||
|
],
|
||||||
|
defaultViewport: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [page] = await browser.pages();
|
||||||
|
console.log("Puppeteer has attached to Discord's browser.");
|
||||||
|
|
||||||
|
const client = new DiscordClient({ checkUpdate: false });
|
||||||
|
client.login(DISCORD_TOKEN);
|
||||||
|
|
||||||
|
client.once("ready", () => {
|
||||||
|
console.log(`Selfbot ready as ${client.user.tag} (${client.user.id})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on("messageCreate", (msg) => {
|
||||||
|
if (msg.author.id === client.user.id) return;
|
||||||
|
console.log(`[#${msg.channel.name}] ${msg.author.tag}: ${msg.content}`);
|
||||||
|
takeScreenshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function takeScreenshot() {
|
||||||
|
await page.screenshot({ path: "/tmp/output/last.png" });
|
||||||
|
console.log("Took a screenshot, saved to /tmp/output/last.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on("SIGTERM", async () => {
|
||||||
|
await browser.close();
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
})();
|
||||||
20
docker-compose.yaml
Normal file
20
docker-compose.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
discord-ai:
|
||||||
|
build: .
|
||||||
|
container_name: discord-ai
|
||||||
|
cap_add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
environment:
|
||||||
|
# supply the user token at runtime:
|
||||||
|
USER_TOKEN: "${USER_TOKEN}"
|
||||||
|
volumes:
|
||||||
|
# live-peek folder so you can grab screenshots outside the container
|
||||||
|
- ./output:/tmp/output
|
||||||
|
ports:
|
||||||
|
- "5901:5901" # VNC
|
||||||
|
- "3000:3000" # optional HTTP server if you add one
|
||||||
|
tmpfs:
|
||||||
|
- /tmp:size=512M
|
||||||
|
restart: unless-stopped
|
||||||
25
entry.sh
Normal file
25
entry.sh
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rm -f /tmp/.X99-lock
|
||||||
|
|
||||||
|
export PULSE_SERVER=unix:/tmp/pulseaudio.socket
|
||||||
|
|
||||||
|
Xvfb :99 -screen 0 1920x1080x24 -ac +extension GLX +render -noreset &
|
||||||
|
pulseaudio --daemonize --exit-idle-time=-1 --disallow-exit &
|
||||||
|
openbox
|
||||||
|
|
||||||
|
# start a simple vnc server that re-uses the same desktop
|
||||||
|
x11vnc -display :99 -shared -forever -nopw -rfbport 5901 -bg
|
||||||
|
|
||||||
|
# Launch discord with the sandbox disabled. This is critical.
|
||||||
|
discord \
|
||||||
|
--no-sandbox \
|
||||||
|
--disable-dev-shm-usage \
|
||||||
|
--disable-gpu \
|
||||||
|
--disable-background-timer-throttling \
|
||||||
|
--disable-renderer-backgrounding \
|
||||||
|
--disable-features=GpuProcess $@
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
exec node bot.js "$@"
|
||||||
2117
package-lock.json
generated
Normal file
2117
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
9
package.json
Normal file
9
package.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"puppeteer-core": "^21.0.0",
|
||||||
|
"discord.js-selfbot-v13": "^3.0.0",
|
||||||
|
"puppeteer-extra": "^3.3.6",
|
||||||
|
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue