TermX / app.py
userbymahadi's picture
Update app.py
7d4ca5f verified
from fastapi import FastAPI, HTTPException, Query, File, UploadFile
from fastapi.responses import PlainTextResponse, HTMLResponse
import subprocess
import os
import shutil
app = FastAPI()
print("--- NEW VERSION STARTING ---")
SECURITY_TOKEN = os.getenv("SECURITY_TOKEN")
@app.get("/")
def read_root():
return {"status": "online", "message": "TermX API is running"}
@app.get("/termx", response_class=PlainTextResponse)
def run_command(cmd: str = Query(...), token: str = Query(...)):
if token != SECURITY_TOKEN:
raise HTTPException(status_code=403, detail="Invalid Token!")
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.stdout if result.stdout else result.stderr
except Exception as e:
return f"Error: {str(e)}"
# ফাইল আপলোড এন্ডপয়েন্ট
@app.post("/upload")
async def upload_file(token: str = Query(...), file: UploadFile = File(...)):
if token != SECURITY_TOKEN:
raise HTTPException(status_code=403, detail="Invalid Token!")
try:
file_path = os.path.join(os.getcwd(), file.filename)
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
return {"message": f"Successfully uploaded {file.filename}"}
except Exception as e:
return {"error": str(e)}
# =========================
# ✅ NEW FUNCTION (ADDED)
# =========================
@app.get("/openweb", response_class=HTMLResponse)
def open_web(token: str = Query(...)):
if token != SECURITY_TOKEN:
raise HTTPException(status_code=403, detail="Invalid Token!")
return """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modern File Upload</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
:root {
--primary: #6750A4;
--secondary: #625B71;
--bg: #f5f5f7;
--card: #ffffff;
--success: #2e7d32;
--error: #c62828;
}
* { box-sizing: border-box; font-family: 'Inter', sans-serif; }
body {
margin: 0;
background: var(--bg);
display: flex;
justify-content: center;
padding: 20px;
}
.container { width: 100%; max-width: 500px; }
.card {
background: var(--card);
border-radius: 20px;
padding: 20px;
box-shadow: 0 8px 20px rgba(0,0,0,0.08);
}
h2 {
margin-top: 0;
color: var(--primary);
text-align: center;
}
.upload-box {
border: 2px dashed var(--primary);
border-radius: 16px;
padding: 30px;
text-align: center;
cursor: pointer;
}
.upload-box:hover { background: #f0ebff; }
.upload-box i {
font-size: 48px;
color: var(--primary);
}
.file-info { margin-top: 15px; }
table { width: 100%; border-collapse: collapse; }
td {
padding: 6px;
font-size: 14px;
}
button {
width: 100%;
margin-top: 15px;
padding: 12px;
border: none;
border-radius: 12px;
background: var(--primary);
color: white;
font-size: 16px;
cursor: pointer;
}
.progress {
margin-top: 10px;
height: 6px;
background: #ddd;
border-radius: 5px;
overflow: hidden;
}
.progress-bar {
height: 100%;
width: 0%;
background: var(--primary);
}
.status {
margin-top: 10px;
text-align: center;
}
.success { color: var(--success); }
.error { color: var(--error); }
@media (max-width: 600px) {
.card { padding: 15px; }
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<h2>📁 File Upload</h2>
<div class="upload-box" id="dropArea">
<i class="material-icons">cloud_upload</i>
<p>Click or Drag file here</p>
<input type="file" id="fileInput" hidden>
</div>
<div class="file-info" id="fileInfo"></div>
<button onclick="uploadFile()">Upload File</button>
<div class="progress">
<div class="progress-bar" id="progressBar"></div>
</div>
<div class="status" id="status"></div>
</div>
</div>
<script>
const fileInput = document.getElementById("fileInput");
const dropArea = document.getElementById("dropArea");
const fileInfo = document.getElementById("fileInfo");
let selectedFile = null;
dropArea.addEventListener("click", () => fileInput.click());
fileInput.addEventListener("change", (e) => {
handleFile(e.target.files[0]);
});
dropArea.addEventListener("dragover", (e) => {
e.preventDefault();
});
dropArea.addEventListener("drop", (e) => {
e.preventDefault();
handleFile(e.dataTransfer.files[0]);
});
function handleFile(file) {
selectedFile = file;
fileInfo.innerHTML = `
<table>
<tr><td><b>Name:</b></td><td>${file.name}</td></tr>
<tr><td><b>Size:</b></td><td>${(file.size/1024).toFixed(2)} KB</td></tr>
<tr><td><b>Type:</b></td><td>${file.type}</td></tr>
</table>
`;
}
function uploadFile() {
if (!selectedFile) {
alert("Select a file first!");
return;
}
const formData = new FormData();
formData.append("file", selectedFile);
const xhr = new XMLHttpRequest();
xhr.open("POST", "/upload?token=MDMahadiHFOpenClawClawx2026", true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
let percent = (e.loaded / e.total) * 100;
document.getElementById("progressBar").style.width = percent + "%";
}
};
xhr.onload = function() {
const status = document.getElementById("status");
if (xhr.status === 200) {
status.innerHTML = "✅ Upload successful!";
status.className = "status success";
} else {
status.innerHTML = "❌ Upload failed!";
status.className = "status error";
}
};
xhr.onerror = function() {
document.getElementById("status").innerHTML = "❌ Network error!";
};
xhr.send(formData);
}
</script>
</body>
</html>"""