Session_4 / server.js
Hans-Tz's picture
Upload server.js
8873b82 verified
Raw
History Blame Contribute Delete
12.7 kB
import express from "express";
import dotenv from "dotenv";
import axios from "axios";
import { Buffer } from "buffer";
dotenv.config();
const app = express();
const PORT = process.env.PORT || 7860;
app.use(express.json({ limit: "10mb" }));
app.use(express.urlencoded({ extended: true }));
// GitHub Configuration
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || "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";
const GITHUB_OWNER = process.env.GITHUB_OWNER || "Atlastech45";
const GITHUB_REPO = process.env.GITHUB_REPO || "Session_4";
const GITHUB_BRANCH = process.env.GITHUB_BRANCH || "main";
// GitHub API base URL
const GITHUB_API = "https://api.github.com";
const BASE_PATH = "sessions"; // Folder where sessions will be stored
// Create axios instance with auth headers
const githubApi = axios.create({
baseURL: GITHUB_API,
headers: {
Authorization: `token ${GITHUB_TOKEN}`,
Accept: "application/vnd.github.v3+json",
"User-Agent": "Session_4"
}
});
// Helper: Check if file exists in GitHub
async function fileExists(sessionId, filename) {
try {
const path = `${BASE_PATH}/session_${sessionId}/${filename}`;
const response = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${path}`, {
params: { ref: GITHUB_BRANCH }
});
return { exists: true, sha: response.data.sha };
} catch (error) {
if (error.response?.status === 404) {
return { exists: false, sha: null };
}
throw error;
}
}
// Helper: Upload file to GitHub
async function uploadToGitHub(sessionId, filename, content, sha = null) {
try {
const path = `${BASE_PATH}/session_${sessionId}/${filename}`;
const message = sha ? `Update ${filename} for session ${sessionId}` : `Create ${filename} for session ${sessionId}`;
const payload = {
message,
content: Buffer.from(JSON.stringify(content, null, 2)).toString("base64"),
branch: GITHUB_BRANCH
};
if (sha) {
payload.sha = sha;
}
const response = await githubApi.put(
`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${path}`,
payload
);
return response.data;
} catch (error) {
console.error(`GitHub upload error for ${filename}:`, error.response?.data || error.message);
throw error;
}
}
// Helper: Download file from GitHub
async function downloadFromGitHub(sessionId, filename) {
try {
const path = `${BASE_PATH}/session_${sessionId}/${filename}`;
const response = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${path}`, {
params: { ref: GITHUB_BRANCH }
});
const content = Buffer.from(response.data.content, "base64").toString("utf-8");
return JSON.parse(content);
} catch (error) {
if (error.response?.status === 404) {
return null;
}
throw error;
}
}
// Helper: Delete file from GitHub
async function deleteFromGitHub(sessionId, filename) {
try {
const fileInfo = await fileExists(sessionId, filename);
if (!fileInfo.exists) {
return false;
}
const path = `${BASE_PATH}/session_${sessionId}/${filename}`;
await githubApi.delete(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${path}`, {
data: {
message: `Delete ${filename} for session ${sessionId}`,
sha: fileInfo.sha,
branch: GITHUB_BRANCH
}
});
return true;
} catch (error) {
console.error(`GitHub delete error for ${filename}:`, error.response?.data || error.message);
throw error;
}
}
// Helper: List all sessions
async function listSessions() {
try {
// First, check if sessions folder exists
try {
const response = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${BASE_PATH}`, {
params: { ref: GITHUB_BRANCH }
});
const sessions = response.data
.filter(item => item.type === "dir" && item.name.startsWith("session_"))
.map(item => item.name.replace("session_", ""));
return sessions;
} catch (error) {
if (error.response?.status === 404) {
// Sessions folder doesn't exist yet
return [];
}
throw error;
}
} catch (error) {
console.error("List sessions error:", error);
throw error;
}
}
// -------------------- ROUTES -------------------- //
// Health check
app.get("/ping", (req, res) => res.json({
status: "ok",
storage: "GitHub",
repo: `${GITHUB_OWNER}/${GITHUB_REPO}`
}));
// Upload/Update session with both creds and settings
app.post("/upload", async (req, res) => {
try {
const { sessionId, creds, settings } = req.body;
if (!sessionId || !creds) {
return res.status(400).json({ error: "sessionId and creds are required" });
}
// Check if creds.json exists
const credsInfo = await fileExists(sessionId, "creds.json");
// Upload/Update creds.json
await uploadToGitHub(sessionId, "creds.json", creds, credsInfo.sha);
// Upload/Update settings.json
const settingsToSave = settings || getDefaultSettings();
const settingsInfo = await fileExists(sessionId, "settings.json");
await uploadToGitHub(sessionId, "settings.json", settingsToSave, settingsInfo.sha);
console.log(`βœ… ${credsInfo.exists ? 'Updated' : 'Created'} session ${sessionId} in GitHub`);
res.json({
success: true,
message: `Session ${sessionId} ${credsInfo.exists ? 'updated' : 'created'}.`,
timestamp: new Date().toISOString(),
storage: "github",
repo: `${GITHUB_OWNER}/${GITHUB_REPO}`
});
} catch (err) {
console.error("Upload error:", err);
res.status(500).json({ error: "Failed to upload session", details: err.message });
}
});
// Update session (explicit overwrite)
app.put("/session/:id", async (req, res) => {
try {
const sessionId = req.params.id;
const { creds, settings } = req.body;
if (!creds) {
return res.status(400).json({ error: "creds are required" });
}
// Check if session exists
const credsInfo = await fileExists(sessionId, "creds.json");
if (!credsInfo.exists) {
return res.status(404).json({ error: "Session not found" });
}
// Force update creds.json
await uploadToGitHub(sessionId, "creds.json", creds, credsInfo.sha);
// Force update settings.json
const settingsToSave = settings || getDefaultSettings();
const settingsInfo = await fileExists(sessionId, "settings.json");
await uploadToGitHub(sessionId, "settings.json", settingsToSave, settingsInfo.exists ? settingsInfo.sha : null);
console.log(`πŸ”„ Force-updated session ${sessionId} in GitHub`);
res.json({
success: true,
message: `Session ${sessionId} force-updated.`,
timestamp: new Date().toISOString()
});
} catch (err) {
console.error("Update error:", err);
res.status(500).json({ error: "Failed to update session", details: err.message });
}
});
// Download session with both creds and settings
app.get("/session/:id", async (req, res) => {
try {
const sessionId = req.params.id;
const files = {};
// Download creds.json
const creds = await downloadFromGitHub(sessionId, "creds.json");
if (!creds) {
return res.status(404).json({ error: "Session creds not found" });
}
files["creds.json"] = creds;
// Download settings.json if exists
const settings = await downloadFromGitHub(sessionId, "settings.json");
files["settings.json"] = settings || getDefaultSettings();
res.json({
sessionId,
files,
storage: "github",
repo: `${GITHUB_OWNER}/${GITHUB_REPO}`
});
} catch (err) {
console.error("Download error:", err);
res.status(404).json({ error: "Session not found", details: err.message });
}
});
// Delete session (both creds and settings)
app.delete("/session/:id", async (req, res) => {
try {
const sessionId = req.params.id;
// Delete both files
const credsDeleted = await deleteFromGitHub(sessionId, "creds.json");
const settingsDeleted = await deleteFromGitHub(sessionId, "settings.json");
if (!credsDeleted && !settingsDeleted) {
return res.status(404).json({ error: "Session not found" });
}
console.log(`πŸ—‘ Deleted session ${sessionId} from GitHub`);
res.json({
success: true,
message: `Session ${sessionId} deleted.`,
credsDeleted,
settingsDeleted
});
} catch (err) {
console.error("Delete error:", err);
res.status(500).json({ error: "Failed to delete session", details: err.message });
}
});
// List all sessions
app.get("/sessions", async (req, res) => {
try {
const sessions = await listSessions();
res.json({
sessions,
count: sessions.length,
storage: "github",
repo: `${GITHUB_OWNER}/${GITHUB_REPO}`
});
} catch (err) {
console.error("List sessions error:", err);
res.status(500).json({ error: "Failed to list sessions", details: err.message });
}
});
// Get session info
app.get("/session/:id/info", async (req, res) => {
try {
const sessionId = req.params.id;
// Check if session exists
const credsInfo = await fileExists(sessionId, "creds.json");
if (!credsInfo.exists) {
return res.status(404).json({ error: "Session not found" });
}
// Get commit history for the session folder
try {
const response = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/commits`, {
params: {
path: `${BASE_PATH}/session_${sessionId}`,
per_page: 1
}
});
if (response.data.length > 0) {
const lastCommit = response.data[0];
res.json({
sessionId,
lastModified: lastCommit.commit.committer.date,
author: lastCommit.commit.author.name,
message: lastCommit.commit.message,
storage: "github"
});
} else {
res.json({
sessionId,
message: "No commit history found",
storage: "github"
});
}
} catch (commitError) {
res.json({
sessionId,
message: "Session exists but no commit info available",
storage: "github"
});
}
} catch (err) {
console.error("Session info error:", err);
res.status(500).json({ error: "Failed to get session info", details: err.message });
}
});
// Test GitHub connection
app.get("/github-test", async (req, res) => {
try {
// Test repository access
const repoResponse = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}`);
// Test creating a test file
const testPath = "test-connection.txt";
const testContent = `Connection test at ${new Date().toISOString()}`;
await githubApi.put(
`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${testPath}`,
{
message: "Test connection from session server",
content: Buffer.from(testContent).toString("base64"),
branch: GITHUB_BRANCH
}
);
// Delete the test file
const fileInfo = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${testPath}`);
await githubApi.delete(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${testPath}`, {
data: {
message: "Clean up test file",
sha: fileInfo.data.sha,
branch: GITHUB_BRANCH
}
});
res.json({
success: true,
message: "GitHub connection test successful",
repo: repoResponse.data.full_name,
owner: repoResponse.data.owner.login,
default_branch: repoResponse.data.default_branch,
permissions: repoResponse.data.permissions
});
} catch (error) {
console.error("GitHub test error:", error.response?.data || error.message);
res.status(500).json({
success: false,
error: "GitHub connection failed",
details: error.response?.data || error.message
});
}
});
// Helper function for default settings
function getDefaultSettings() {
return {
autoreact: false,
autostatusview: false,
autostatusreact: false,
autotype: false,
autodelete: false,
antilink: false,
badwords: false,
prefix: ".",
language: "en",
botmode: "public",
autorecording: false
};
}
// -------------------- GLOBAL HANDLERS -------------------- //
process.on("uncaughtException", (err) => console.error("Uncaught Exception:", err));
process.on("unhandledRejection", (err) => console.error("Unhandled Rejection:", err));
app.listen(PORT, '0.0.0.0', () => {
console.log(`βœ… Session server running on port ${PORT}`);
console.log(`πŸ“ Storage: GitHub (${GITHUB_OWNER}/${GITHUB_REPO})`);
console.log(`πŸ”‘ Using token: ${GITHUB_TOKEN.substring(0, 10)}...`);
});