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