teto_ai/bot.js

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`);
});
})();