236 lines
7.4 KiB
JavaScript
236 lines
7.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 } from "url";
|
|
import fetch from "node-fetch"; // Import fetch
|
|
|
|
// --- CONFIGURATION ---
|
|
const { USER_TOKEN, BOT_CLIENT_ID, BOT_CLIENT_SECRET, BOT_REDIRECT_URI } =
|
|
process.env;
|
|
const WEB_PORT = 3000;
|
|
// IMPORTANT: Replace with the Discord User IDs of people allowed to access the dashboard.
|
|
const ADMIN_USER_IDS = ["339753362297847810"];
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
// --- IN-MEMORY STATE ---
|
|
const activityLog = [];
|
|
const actionsLog = [];
|
|
const MAX_LOG_SIZE = 20;
|
|
|
|
const logItem = (logArray, item) => {
|
|
logArray.unshift(item);
|
|
if (logArray.length > MAX_LOG_SIZE) logArray.pop();
|
|
};
|
|
|
|
// --- WEB SERVER SETUP ---
|
|
const app = express();
|
|
|
|
app.set("view engine", "ejs");
|
|
app.set("views", path.join(__dirname, "views"));
|
|
app.set("trust proxy", 1);
|
|
|
|
app.use(
|
|
session({
|
|
secret: "a-very-secret-string-for-teto",
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
secure: true,
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
},
|
|
}),
|
|
);
|
|
|
|
// --- OAUTH2 AUTHENTICATION & DASHBOARD ROUTES ---
|
|
app.get("/auth/discord", (req, res) => {
|
|
const authUrl = `https://discord.com/api/oauth2/authorize?client_id=${BOT_CLIENT_ID}&redirect_uri=${encodeURIComponent(BOT_REDIRECT_URI)}&response_type=code&scope=identify`;
|
|
res.redirect(authUrl);
|
|
});
|
|
|
|
app.get("/auth/callback", async (req, res) => {
|
|
const code = req.query.code;
|
|
if (!code) return res.status(400).send("No code provided.");
|
|
|
|
try {
|
|
const params = {
|
|
client_id: BOT_CLIENT_ID,
|
|
client_secret: BOT_CLIENT_SECRET,
|
|
code,
|
|
grant_type: "authorization_code",
|
|
redirect_uri: BOT_REDIRECT_URI,
|
|
};
|
|
console.log("Attempting token exchange with params:", params);
|
|
|
|
const tokenResponse = await fetch("https://discord.com/api/oauth2/token", {
|
|
method: "POST",
|
|
body: new URLSearchParams(params),
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
});
|
|
const tokenData = await tokenResponse.json();
|
|
|
|
if (tokenData.error) {
|
|
console.error("Token Exchange Error:", tokenData); // Log the full error response
|
|
return res
|
|
.status(500)
|
|
.send(
|
|
`Error exchanging code for token. Details: ${JSON.stringify(tokenData)}`,
|
|
);
|
|
}
|
|
|
|
const userResponse = await fetch("https://discord.com/api/users/@me", {
|
|
headers: { Authorization: `Bearer ${tokenData.access_token}` },
|
|
});
|
|
const userData = await userResponse.json();
|
|
|
|
if (!ADMIN_USER_IDS.includes(userData.id)) {
|
|
return res
|
|
.status(403)
|
|
.send("You are not authorized to view this dashboard.");
|
|
}
|
|
|
|
req.session.user = {
|
|
id: userData.id,
|
|
username: userData.username,
|
|
discriminator: userData.discriminator,
|
|
avatar: userData.avatar,
|
|
};
|
|
req.session.save((err) => {
|
|
if (err) {
|
|
console.error("Error saving session:", err);
|
|
return res
|
|
.status(500)
|
|
.send("An error occurred while saving the session.");
|
|
}
|
|
console.log("Session saved successfully, redirecting.");
|
|
res.redirect("/");
|
|
});
|
|
} catch (error) {
|
|
console.error("OAuth2 Callback Error:", error);
|
|
res.status(500).send("An error occurred during authentication.");
|
|
}
|
|
});
|
|
|
|
app.get("/logout", (req, res, next) => {
|
|
req.session.destroy((err) => {
|
|
if (err) return next(err);
|
|
res.redirect("/");
|
|
});
|
|
});
|
|
|
|
const checkAuth = (req, res, next) => {
|
|
if (req.session.user) return next();
|
|
res.redirect("/auth/discord");
|
|
};
|
|
|
|
app.use(express.static(path.join(__dirname, "public")));
|
|
|
|
app.get("/", checkAuth, (req, res) => {
|
|
const systemResources = {
|
|
memory: { percentage: 91, used: 7.3, total: 8 },
|
|
vram: { percentage: 69, used: 5.5, total: 8 },
|
|
avgResponse: 32,
|
|
shutdown: "3d 0h",
|
|
sessionEnd: "Jul 24, 2025, 07:21 PM",
|
|
};
|
|
res.render("index", {
|
|
user: req.session.user,
|
|
activityLog,
|
|
actionsLog,
|
|
systemResources,
|
|
});
|
|
});
|
|
|
|
// --- DISCORD BOT LOGIC (no changes here) ---
|
|
(async () => {
|
|
puppeteer.use(StealthPlugin());
|
|
|
|
// This part is disabled for now but can be re-enabled if needed for screenshots
|
|
/*
|
|
const browser = await puppeteer.launch({
|
|
executablePath: '/usr/bin/discord',
|
|
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.once("ready", () => {
|
|
console.log(`Selfbot ready as ${client.user.tag} (${client.user.id})`);
|
|
|
|
// Add dummy data
|
|
logItem(actionsLog, {
|
|
message: "Responded to Alice in",
|
|
channel: "#gaming",
|
|
icon: "💬",
|
|
});
|
|
logItem(actionsLog, {
|
|
message: "Joined Voice Chat",
|
|
channel: "#general",
|
|
icon: "🎤",
|
|
});
|
|
logItem(actionsLog, {
|
|
message: "Analyzed image from Charlie in",
|
|
channel: "#memes",
|
|
icon: "👁️",
|
|
});
|
|
|
|
const now = new Date();
|
|
logItem(activityLog, {
|
|
message: `[${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Memory consolidation complete`,
|
|
});
|
|
now.setSeconds(now.getSeconds() - 4);
|
|
logItem(activityLog, {
|
|
message: `[${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Learning: Alice enjoys my French bread jokes`,
|
|
});
|
|
now.setSeconds(now.getSeconds() - 4);
|
|
logItem(activityLog, {
|
|
message: `[${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Updating conversation context in vector database...`,
|
|
});
|
|
now.setSeconds(now.getSeconds() - 4);
|
|
logItem(activityLog, {
|
|
message: `[${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Alice reacted with 😊 - response was well received`,
|
|
});
|
|
now.setSeconds(now.getSeconds() - 4);
|
|
logItem(activityLog, {
|
|
message: `[${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Monitoring user reactions and engagement...`,
|
|
});
|
|
});
|
|
|
|
client.on("messageCreate", (msg) => {
|
|
if (msg.author.id === client.user.id) return;
|
|
|
|
const message = `[${new Date().toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Message from ${msg.author.tag} in #${msg.channel.name || "DM"}: "${msg.content.slice(0, 50)}..."`;
|
|
logItem(activityLog, { message });
|
|
|
|
// Example of logging a bot action
|
|
if (msg.content.toLowerCase().includes("hello teto")) {
|
|
msg.channel.send("Hello there!");
|
|
logItem(actionsLog, {
|
|
message: `Responded to ${msg.author.tag}`,
|
|
channel: `#${msg.channel.name || "DM"}`,
|
|
icon: "💬",
|
|
});
|
|
}
|
|
});
|
|
|
|
client.on("disconnect", () => {
|
|
const message = `[${new Date().toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" })}] Bot disconnected.`;
|
|
logItem(activityLog, { message });
|
|
});
|
|
|
|
client.login(USER_TOKEN);
|
|
|
|
app.listen(WEB_PORT, () => {
|
|
console.log(`Dashboard server running on https://teto.getsilly.org`);
|
|
});
|
|
})();
|