Skip to content

Instantly share code, notes, and snippets.

@hsnsbhshsh
Created March 7, 2026 04:27
Show Gist options
  • Select an option

  • Save hsnsbhshsh/387b6ddb598e32c984f566bc54e7a442 to your computer and use it in GitHub Desktop.

Select an option

Save hsnsbhshsh/387b6ddb598e32c984f566bc54e7a442 to your computer and use it in GitHub Desktop.
Untitled
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sora Downloader Pro - فحص الخادم</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #0f172a, #1e293b);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
border-radius: 30px;
padding: 35px;
width: 100%;
max-width: 550px;
box-shadow: 0 30px 60px rgba(0,0,0,0.5);
}
h1 {
text-align: center;
color: #0f172a;
margin-bottom: 5px;
font-size: 28px;
}
.subtitle {
text-align: center;
color: #64748b;
margin-bottom: 25px;
font-size: 14px;
}
/* مؤشر حالة الخادم */
.server-status {
background: #f8fafc;
border-radius: 50px;
padding: 15px 20px;
margin-bottom: 25px;
display: flex;
align-items: center;
gap: 15px;
border: 1px solid #e2e8f0;
}
.status-indicator {
width: 14px;
height: 14px;
border-radius: 50%;
background: #94a3b8;
transition: all 0.3s;
position: relative;
}
.status-indicator.working {
background: #22c55e;
box-shadow: 0 0 15px #22c55e;
animation: pulse 2s infinite;
}
.status-indicator.checking {
background: #f59e0b;
animation: blink 1s infinite;
}
.status-indicator.error {
background: #ef4444;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(34, 197, 94, 0); }
100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}
@keyframes blink {
0% { opacity: 1; }
50% { opacity: 0.3; }
100% { opacity: 1; }
}
.status-text {
flex: 1;
font-weight: 600;
color: #334155;
}
.status-details {
font-size: 12px;
color: #64748b;
font-family: monospace;
background: #e2e8f0;
padding: 5px 10px;
border-radius: 20px;
}
.input-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #475569;
font-weight: 500;
font-size: 14px;
}
#video-url {
width: 100%;
padding: 15px;
border: 2px solid #e2e8f0;
border-radius: 15px;
font-size: 15px;
transition: all 0.3s;
direction: ltr;
}
#video-url:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 4px rgba(59,130,246,0.1);
}
#video-url:disabled {
background: #f1f5f9;
cursor: not-allowed;
}
.download-btn {
width: 100%;
padding: 15px;
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
color: white;
border: none;
border-radius: 15px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
margin-bottom: 15px;
}
.download-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(59,130,246,0.3);
}
.download-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
background: linear-gradient(135deg, #94a3b8, #64748b);
}
.status-box {
padding: 15px;
border-radius: 12px;
margin: 15px 0;
display: none;
font-size: 14px;
}
.status-box.success {
background: #d1fae5;
border: 1px solid #a7f3d0;
color: #065f46;
display: block;
}
.status-box.error {
background: #fee2e2;
border: 1px solid #fecaca;
color: #991b1b;
display: block;
}
.status-box.info {
background: #dbeafe;
border: 1px solid #bfdbfe;
color: #1e40af;
display: block;
}
.result-box {
background: #f8fafc;
border-radius: 15px;
padding: 20px;
border: 1px solid #e2e8f0;
margin-top: 15px;
}
.download-link {
display: block;
padding: 15px;
background: #22c55e;
color: white;
text-decoration: none;
border-radius: 12px;
text-align: center;
font-weight: 600;
margin-bottom: 10px;
transition: 0.3s;
}
.download-link:hover {
background: #16a34a;
}
.copy-btn {
width: 100%;
padding: 12px;
background: #64748b;
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
font-size: 14px;
transition: 0.3s;
}
.copy-btn:hover {
background: #475569;
}
.examples {
margin-top: 20px;
}
.example-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.example-btn {
flex: 1;
padding: 10px;
background: #f1f5f9;
border: 1px solid #e2e8f0;
border-radius: 8px;
cursor: pointer;
font-size: 12px;
color: #334155;
transition: 0.3s;
min-width: 100px;
}
.example-btn:hover:not(:disabled) {
background: #e2e8f0;
}
.example-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.loading-spinner {
display: inline-block;
width: 18px;
height: 18px;
border: 3px solid rgba(255,255,255,0.3);
border-radius: 50%;
border-top-color: white;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.server-url {
text-align: center;
margin-top: 20px;
font-size: 11px;
color: #94a3b8;
font-family: monospace;
background: #f1f5f9;
padding: 8px;
border-radius: 20px;
}
.last-check {
font-size: 11px;
color: #94a3b8;
margin-top: 5px;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1>🎬 Sora Video Downloader</h1>
<div class="subtitle">مع فحص الخادم التلقائي</div>
<!-- حالة الخادم -->
<div class="server-status" id="serverStatus">
<div class="status-indicator" id="statusIndicator"></div>
<div class="status-text" id="statusText">جاري فحص الخادم...</div>
<div class="status-details" id="statusDetails">brahim-1ofn.onrender.com</div>
</div>
<div class="input-group">
<label for="video-url">🔗 رابط فيديو Sora</label>
<input type="text" id="video-url" placeholder="https://sora.chatgpt.com/p/..."
value="https://sora.chatgpt.com/p/s_6902318491e88191893d935b08d8c428">
</div>
<button class="download-btn" onclick="downloadVideo()" id="downloadBtn">
<span>⬇️</span> تحميل الفيديو
</button>
<div class="status-box" id="status"></div>
<div id="result"></div>
<div class="examples">
<div class="example-buttons">
<button class="example-btn" onclick="fillExample('https://sora.chatgpt.com/p/s_6902318491e88191893d935b08d8c428')">
📋 رابط 1
</button>
<button class="example-btn" onclick="fillExample('https://sora.chatgpt.com/p/s_6902318491e88191893d935b08d8c429')">
📋 رابط 2
</button>
<button class="example-btn" onclick="checkServerAgain()">
🔄 فحص الخادم
</button>
</div>
</div>
<div class="server-url">
الخادم: https://brahim-1ofn.onrender.com
</div>
<div class="last-check" id="lastCheck"></div>
</div>
<script>
const SERVER_URL = 'https://brahim-1ofn.onrender.com';
const DOWNLOAD_URL = `${SERVER_URL}/download`;
// فحص الخادم عند تحميل الصفحة
async function checkServer() {
const indicator = document.getElementById('statusIndicator');
const statusText = document.getElementById('statusText');
const downloadBtn = document.getElementById('downloadBtn');
const videoInput = document.getElementById('video-url');
const exampleBtns = document.querySelectorAll('.example-btn');
// تغيير الحالة إلى "جاري الفحص"
indicator.className = 'status-indicator checking';
statusText.innerHTML = 'جاري فحص الخادم...';
downloadBtn.disabled = true;
videoInput.disabled = true;
exampleBtns.forEach(btn => btn.disabled = true);
try {
// محاولة الاتصال بالخادم
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
const response = await fetch(SERVER_URL, {
method: 'GET',
signal: controller.signal
});
clearTimeout(timeoutId);
if (response.ok) {
const text = await response.text();
if (text.includes('الخادم يعمل') || text.includes('working') || text.includes('بنجاح')) {
// خادم شغال
indicator.className = 'status-indicator working';
statusText.innerHTML = '✅ الخادم شغال وجاهز';
downloadBtn.disabled = false;
videoInput.disabled = false;
exampleBtns.forEach(btn => btn.disabled = false);
document.getElementById('lastCheck').innerHTML = `آخر فحص: ${new Date().toLocaleTimeString('ar-EG')}`;
} else {
throw new Error('الخادم لا يستجيب بشكل صحيح');
}
} else {
throw new Error('الخادم لا يستجيب');
}
} catch (error) {
// خادم معطل
indicator.className = 'status-indicator error';
statusText.innerHTML = '❌ الخادم معطل أو لا يستجيب';
downloadBtn.disabled = true;
videoInput.disabled = true;
exampleBtns.forEach(btn => btn.disabled = true);
document.getElementById('lastCheck').innerHTML = `آخر محاولة: ${new Date().toLocaleTimeString('ar-EG')} - فشل`;
// عرض رسالة للمستخدم
showStatus('⚠️ الخادم غير متصل حالياً. حاول مرة أخرى لاحقاً.', 'error');
}
}
async function downloadVideo() {
const videoUrl = document.getElementById('video-url').value.trim();
const downloadBtn = document.getElementById('downloadBtn');
const statusEl = document.getElementById('status');
const resultEl = document.getElementById('result');
if (!videoUrl) {
showStatus('❌ الرجاء إدخال رابط الفيديو', 'error');
return;
}
// تغيير حالة الزر
downloadBtn.disabled = true;
downloadBtn.innerHTML = '<span class="loading-spinner"></span> جاري التحميل...';
showStatus('🔄 جاري معالجة الرابط...', 'info');
resultEl.innerHTML = '';
try {
const response = await fetch(DOWNLOAD_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
video_url: videoUrl
})
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || 'خطأ في الخادم');
}
const downloadUrl = data.download_url || data.url;
if (downloadUrl) {
showStatus('✅ تم العثور على الفيديو!', 'success');
resultEl.innerHTML = `
<div class="result-box">
<a href="${downloadUrl}" class="download-link" target="_blank">
⬇️ تحميل الفيديو الآن
</a>
<button class="copy-btn" onclick="copyToClipboard('${downloadUrl}')">
📋 نسخ رابط التحميل
</button>
</div>
`;
// تحميل تلقائي
setTimeout(() => window.open(downloadUrl, '_blank'), 1000);
} else {
throw new Error('لم يتم العثور على رابط التحميل');
}
} catch (error) {
showStatus(`❌ ${error.message}`, 'error');
console.error(error);
// فحص الخادم مرة أخرى
checkServer();
} finally {
// إعادة الزر لحالته
downloadBtn.disabled = false;
downloadBtn.innerHTML = '<span>⬇️</span> تحميل الفيديو';
}
}
function showStatus(message, type) {
const statusEl = document.getElementById('status');
statusEl.textContent = message;
statusEl.className = `status-box ${type}`;
}
function fillExample(url) {
document.getElementById('video-url').value = url;
}
function checkServerAgain() {
checkServer();
}
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
alert('✅ تم نسخ الرابط');
}).catch(() => {
alert('❌ الرجاء نسخ الرابط يدوياً');
});
}
// فحص الخادم عند تحميل الصفحة
window.onload = function() {
checkServer();
};
// تحميل بالضغط على Enter
document.getElementById('video-url').addEventListener('keypress', (e) => {
if (e.key === 'Enter') downloadVideo();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment