148 lines
4 KiB
JavaScript
148 lines
4 KiB
JavaScript
import puppeteer from "puppeteer-extra";
|
|
import StealthPlugin from "puppeteer-extra-plugin-stealth";
|
|
import { Client as DiscordClient } from "discord.js-selfbot-v13";
|
|
import express from "express";
|
|
import session from "express-session";
|
|
import path from "path";
|
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
import { WebSocketServer } from "ws";
|
|
import authRouter from "./src/routes/authRoutes.js";
|
|
import fs from "fs";
|
|
|
|
// --- CONFIGURATION ---
|
|
const {
|
|
USER_TOKEN,
|
|
BOT_CLIENT_ID,
|
|
BOT_CLIENT_SECRET,
|
|
BOT_REDIRECT_URI,
|
|
COOKIE_SECRET,
|
|
} = process.env;
|
|
const WEB_PORT = 3000;
|
|
const ADMIN_USER_IDS = ["339753362297847810"];
|
|
const MAX_LOG_SIZE = 20;
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
// --- IN-MEMORY STATE ---
|
|
const activityLog = [];
|
|
const actionsLog = [];
|
|
|
|
// --- WEB SERVER SETUP ---
|
|
const app = express();
|
|
|
|
// Make config and data available to routers/controllers via app.locals
|
|
app.locals.config = {
|
|
BOT_CLIENT_ID,
|
|
BOT_CLIENT_SECRET,
|
|
BOT_REDIRECT_URI,
|
|
ADMIN_USER_IDS,
|
|
};
|
|
app.locals.data = {
|
|
activityLog,
|
|
actionsLog,
|
|
};
|
|
|
|
app.set("view engine", "ejs");
|
|
app.set("views", path.join(__dirname, "views"));
|
|
app.set("trust proxy", 1); // Required for secure cookies if behind a proxy
|
|
|
|
app.use(
|
|
session({
|
|
secret: COOKIE_SECRET || "a-very-secret-string-for-teto-is-required",
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
secure: process.env.NODE_ENV === "production",
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
},
|
|
}),
|
|
);
|
|
|
|
// --- STATIC ASSETS & ROUTES ---
|
|
app.use(express.static(path.join(__dirname, "public")));
|
|
app.use("/", authRouter);
|
|
|
|
// --- DISCORD BOT & SERVER INITIALIZATION ---
|
|
(async () => {
|
|
// Puppeteer setup (currently optional)
|
|
puppeteer.use(StealthPlugin());
|
|
/*
|
|
const browser = await puppeteer.launch({ headless: false });
|
|
// ... more puppeteer logic if needed
|
|
*/
|
|
|
|
// Start the web server AND capture the HTTP server instance it creates
|
|
const server = app.listen(WEB_PORT, () => {
|
|
console.log(`Dashboard server running on http://localhost:${WEB_PORT}`);
|
|
});
|
|
|
|
// Create the WebSocket server and attach it to our existing HTTP server
|
|
const wss = new WebSocketServer({ server });
|
|
|
|
// Function to broadcast data to all connected WebSocket clients
|
|
const broadcast = (data) => {
|
|
// The 'wss.clients' property is a Set of all connected clients
|
|
wss.clients.forEach((client) => {
|
|
// Check if the connection is still open before sending
|
|
if (client.readyState === client.OPEN) {
|
|
// WebSocket only sends strings, so we stringify our object
|
|
client.send(JSON.stringify(data));
|
|
}
|
|
});
|
|
};
|
|
|
|
const logItem = (logArray, item) => {
|
|
logArray.unshift(item);
|
|
if (logArray.length > MAX_LOG_SIZE) logArray.pop();
|
|
|
|
if (logArray === activityLog) {
|
|
broadcast({ type: "activityLogUpdate", payload: item });
|
|
}
|
|
};
|
|
|
|
wss.on("connection", (ws) => {
|
|
console.log("Dashboard client connected via WebSocket.");
|
|
ws.on("close", () => {
|
|
console.log("Dashboard client disconnected.");
|
|
});
|
|
});
|
|
|
|
const client = new DiscordClient({ checkUpdate: false });
|
|
|
|
// --- DYNAMIC EVENT HANDLER LOADING ---
|
|
const eventsPath = path.join(__dirname, "src", "events");
|
|
const eventFiles = fs
|
|
.readdirSync(eventsPath)
|
|
.filter((file) => file.endsWith(".js"));
|
|
|
|
const context = {
|
|
client,
|
|
logItem,
|
|
activityLog,
|
|
actionsLog,
|
|
MAX_LOG_SIZE,
|
|
};
|
|
|
|
for (const file of eventFiles) {
|
|
const filePath = path.join(eventsPath, file);
|
|
const event = (await import(pathToFileURL(filePath))).default;
|
|
|
|
if (event.name && event.execute) {
|
|
if (event.once) {
|
|
client.once(event.name, (...args) => event.execute(context, ...args));
|
|
} else {
|
|
client.on(event.name, (...args) => event.execute(context, ...args));
|
|
}
|
|
}
|
|
}
|
|
// End dynamic event handler loading
|
|
|
|
try {
|
|
await client.login(USER_TOKEN);
|
|
} catch (error) {
|
|
console.error("Failed to login to Discord. Check your USER_TOKEN.", error);
|
|
process.exit(1);
|
|
}
|
|
})();
|