| 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 })); |
|
|
| |
| 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_3"; |
| const GITHUB_BRANCH = process.env.GITHUB_BRANCH || "main"; |
|
|
| |
| const GITHUB_API = "https://api.github.com"; |
| const BASE_PATH = "sessions"; |
|
|
| |
| const githubApi = axios.create({ |
| baseURL: GITHUB_API, |
| headers: { |
| Authorization: `token ${GITHUB_TOKEN}`, |
| Accept: "application/vnd.github.v3+json", |
| "User-Agent": "Session_3" |
| } |
| }); |
|
|
| |
| 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; |
| } |
| } |
|
|
| |
| 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; |
| } |
| } |
|
|
| |
| 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; |
| } |
| } |
|
|
| |
| 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; |
| } |
| } |
|
|
| |
| async function listSessions() { |
| try { |
| |
| 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) { |
| |
| return []; |
| } |
| throw error; |
| } |
| } catch (error) { |
| console.error("List sessions error:", error); |
| throw error; |
| } |
| } |
|
|
| |
|
|
| |
| app.get("/ping", (req, res) => res.json({ |
| status: "ok", |
| storage: "GitHub", |
| repo: `${GITHUB_OWNER}/${GITHUB_REPO}` |
| })); |
|
|
| |
| 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" }); |
| } |
|
|
| |
| const credsInfo = await fileExists(sessionId, "creds.json"); |
| |
| |
| await uploadToGitHub(sessionId, "creds.json", creds, credsInfo.sha); |
|
|
| |
| 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 }); |
| } |
| }); |
|
|
| |
| 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" }); |
| } |
|
|
| |
| const credsInfo = await fileExists(sessionId, "creds.json"); |
| if (!credsInfo.exists) { |
| return res.status(404).json({ error: "Session not found" }); |
| } |
|
|
| |
| await uploadToGitHub(sessionId, "creds.json", creds, credsInfo.sha); |
|
|
| |
| 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 }); |
| } |
| }); |
|
|
| |
| app.get("/session/:id", async (req, res) => { |
| try { |
| const sessionId = req.params.id; |
| const files = {}; |
|
|
| |
| const creds = await downloadFromGitHub(sessionId, "creds.json"); |
| if (!creds) { |
| return res.status(404).json({ error: "Session creds not found" }); |
| } |
| files["creds.json"] = creds; |
|
|
| |
| 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 }); |
| } |
| }); |
|
|
| |
| app.delete("/session/:id", async (req, res) => { |
| try { |
| const sessionId = req.params.id; |
|
|
| |
| 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 }); |
| } |
| }); |
|
|
| |
| 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 }); |
| } |
| }); |
|
|
| |
| app.get("/session/:id/info", async (req, res) => { |
| try { |
| const sessionId = req.params.id; |
| |
| |
| const credsInfo = await fileExists(sessionId, "creds.json"); |
| if (!credsInfo.exists) { |
| return res.status(404).json({ error: "Session not found" }); |
| } |
|
|
| |
| 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 }); |
| } |
| }); |
|
|
| |
| app.get("/github-test", async (req, res) => { |
| try { |
| |
| const repoResponse = await githubApi.get(`/repos/${GITHUB_OWNER}/${GITHUB_REPO}`); |
| |
| |
| 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 |
| } |
| ); |
|
|
| |
| 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 |
| }); |
| } |
| }); |
|
|
| |
| function getDefaultSettings() { |
| return { |
| autoreact: false, |
| autostatusview: false, |
| autostatusreact: false, |
| autotype: false, |
| autodelete: false, |
| antilink: false, |
| badwords: false, |
| prefix: ".", |
| language: "en", |
| botmode: "public", |
| autorecording: false |
| }; |
| } |
|
|
| |
| 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)}...`); |
| }); |