Spaces:
Sleeping
Sleeping
| import os | |
| import time | |
| import subprocess | |
| import threading | |
| import requests | |
| from datetime import datetime, timedelta | |
| from flask import Flask, jsonify | |
| # ========================================== | |
| # الإعدادات الأساسية | |
| # ========================================== | |
| STREAM_KEY = os.environ.get("STREAM_KEY") | |
| STREAM_URL = "rtmp://a.rtmp.youtube.com/live2/" | |
| BG_IMAGE = "https://images.unsplash.com/photo-1555400038-63f5ba517a47?q=80&w=1920&auto=format&fit=crop" | |
| TICK_SOUND_FILE = "time.mp3" | |
| app = Flask(__name__) | |
| def get_current_status(): | |
| try: | |
| res = requests.get("http://api.aladhan.com/v1/timingsByCity?city=Mecca&country=SA&method=4", timeout=5) | |
| data = res.json()['data'] | |
| hijri_date = data['date']['hijri'] | |
| date_str = hijri_date['date'] | |
| h_day = int(hijri_date['day']) | |
| h_month = int(hijri_date['month']['number']) | |
| h_year = int(hijri_date['year']) | |
| status = "" | |
| target_date_gregorian = None | |
| msg = "" | |
| if h_month == 9: | |
| status = "ramadan_live" | |
| msg = "جاء رمضان.. مبارك عليكم الشهر" | |
| elif h_month == 10 and h_day <= 3: | |
| status = "eid_live" | |
| msg = "عيد مبارك - كل عام وأنتم بخير" | |
| else: | |
| status = "counting" | |
| target_h_year = h_year if h_month < 9 else h_year + 1 | |
| conv_res = requests.get(f"http://api.aladhan.com/v1/hToG?date=01-09-{target_h_year}", timeout=5) | |
| g_data = conv_res.json()['data']['gregorian'] | |
| target_date_gregorian = datetime.strptime(g_data['date'], "%d-%m-%Y") | |
| return {"status": status, "msg": msg, "hijri_str": date_str, "target_date": target_date_gregorian} | |
| except: | |
| return {"status": "counting", "msg": "", "hijri_str": "1447-09-01", "target_date": datetime(2026, 2, 18, 0, 0, 0)} | |
| def time_data(): | |
| current_state = get_current_status() | |
| if current_state['status'] in ['ramadan_live', 'eid_live']: | |
| return jsonify({"status": "finished", "msg": current_state['msg'], "hijri": current_state['hijri_str']}) | |
| diff = current_state['target_date'] - datetime.now() | |
| if diff.total_seconds() <= 0: | |
| return jsonify({"status": "loading", "hijri": current_state['hijri_str']}) | |
| days = diff.days | |
| hours, rem = divmod(diff.seconds, 3600) | |
| minutes, seconds = divmod(rem, 60) | |
| return jsonify({"status": "counting", "days": f"{days:02}", "hours": f"{hours:02}", "minutes": f"{minutes:02}", "seconds": f"{seconds:02}", "hijri": current_state['hijri_str']}) | |
| def home(): | |
| html_content = """ | |
| <!DOCTYPE html> | |
| <html lang="ar" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>بث مباشر | رمضان</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@700;900&display=swap" rel="stylesheet"> | |
| <style> | |
| body { background-color: #0f0f0f; color: white; font-family: 'Cairo', sans-serif; margin: 0; overflow: hidden; } | |
| .video-player { | |
| position: relative; width: 100vw; height: 100vh; | |
| background: url('""" + BG_IMAGE + """') no-repeat center center; | |
| background-size: cover; display: flex; flex-direction: column; justify-content: center; align-items: center; | |
| } | |
| .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); } | |
| .content { z-index: 10; text-align: center; width: 100%; } | |
| .hijri-badge { background: #4CAF50; padding: 5px 20px; border-radius: 50px; font-size: 20px; margin-bottom: 20px; display: inline-block; } | |
| .title { font-size: 40px; margin-bottom: 30px; text-shadow: 2px 2px 10px rgba(0,0,0,0.8); } | |
| /* الحاوية الأساسية للعد التنازلي */ | |
| .countdown { | |
| display: flex; | |
| gap: 15px; | |
| justify-content: center; | |
| direction: ltr; | |
| align-items: flex-start; /* محاذاة العناصر من الأعلى لضمان تناسق الوحدات */ | |
| } | |
| .card { | |
| background: linear-gradient(180deg, #4CAF50, #2E7D32); | |
| width: 110px; height: 140px; border-radius: 15px; | |
| font-size: 70px; font-weight: 900; display: flex; | |
| justify-content: center; align-items: center; | |
| box-shadow: 0 8px 15px rgba(0,0,0,0.5); | |
| line-height: 1; /* لضمان توسط الرقم داخل المربع */ | |
| } | |
| .unit { display: flex; flex-direction: column; align-items: center; } | |
| .label { margin-top: 10px; font-size: 18px; color: #4CAF50; font-weight: bold; } | |
| /* التعديل المطلوب: وضع النقاط في نصف ارتفاع المربع بالضبط */ | |
| .colon { | |
| font-size: 60px; | |
| color: #4CAF50; | |
| font-weight: 900; | |
| height: 140px; /* نفس ارتفاع الـ card */ | |
| display: flex; | |
| align-items: center; /* يتوسط عمودياً بالنسبة للـ 140px */ | |
| justify-content: center; | |
| line-height: 1; | |
| margin-top: 0; | |
| } | |
| #celebration { display: none; font-size: 60px; color: #FFD700; animation: pulse 2s infinite; } | |
| @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="video-player"> | |
| <div class="overlay"></div> | |
| <div class="content"> | |
| <div class="hijri-badge" id="hijri-top">--/--/----</div> | |
| <div id="main-ui"> | |
| <div class="title">الوقت المتبقي على شهر رمضان</div> | |
| <div class="countdown"> | |
| <div class="unit"><div class="card" id="days">00</div><div class="label">أيام</div></div> | |
| <div class="colon">:</div> | |
| <div class="unit"><div class="card" id="hours">00</div><div class="label">ساعة</div></div> | |
| <div class="colon">:</div> | |
| <div class="unit"><div class="card" id="minutes">00</div><div class="label">دقيقة</div></div> | |
| <div class="colon">:</div> | |
| <div class="unit"><div class="card" id="seconds">00</div><div class="label">ثانية</div></div> | |
| </div> | |
| </div> | |
| <div id="celebration">...</div> | |
| </div> | |
| </div> | |
| <script> | |
| function update() { | |
| fetch('/time_data').then(res => res.json()).then(data => { | |
| document.getElementById('hijri-top').innerText = data.hijri; | |
| if(data.status === 'finished') { | |
| document.getElementById('main-ui').style.display = 'none'; | |
| document.getElementById('celebration').innerText = data.msg; | |
| document.getElementById('celebration').style.display = 'block'; | |
| } else { | |
| document.getElementById('main-ui').style.display = 'block'; | |
| document.getElementById('celebration').style.display = 'none'; | |
| document.getElementById('days').innerText = data.days || "00"; | |
| document.getElementById('hours').innerText = data.hours || "00"; | |
| document.getElementById('minutes').innerText = data.minutes || "00"; | |
| document.getElementById('seconds').innerText = data.seconds || "00"; | |
| } | |
| }); | |
| } | |
| setInterval(update, 1000); | |
| update(); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| return html_content | |
| def start_stream(): | |
| if not STREAM_KEY: return | |
| while True: | |
| current_state = get_current_status() | |
| if current_state['status'] == 'ramadan_live': | |
| display_text, box_color, title_text, font_size = "Ramadan Mubarak", "0xD4AF37", "RAMADAN KAREEM", "65" | |
| elif current_state['status'] == 'eid_live': | |
| display_text, box_color, title_text, font_size = "Eid Mubarak", "0x9C27B0", "EID AL-FITR", "90" | |
| else: | |
| target_ts = int(current_state['target_date'].timestamp()) if current_state['target_date'] else int(time.time()) | |
| display_text = f" %{{pts\\:localtime\\:{target_ts}\\:%d}} : %{{pts\\:localtime\\:{target_ts}\\:%H}} : %{{pts\\:localtime\\:{target_ts}\\:%M}} : %{{pts\\:localtime\\:{target_ts}\\:%S}} " | |
| box_color, title_text, font_size = "0x4CAF50", "RAMADAN COUNTDOWN", "90" | |
| ffmpeg_cmd = [ | |
| 'ffmpeg', '-re', '-stream_loop', '-1', '-i', TICK_SOUND_FILE, | |
| '-loop', '1', '-i', BG_IMAGE, '-map', '1:v', '-map', '0:a', | |
| '-vf', ( | |
| "scale=1280:720,setsar=1," | |
| "drawbox=y=ih/2-80:color=black@0.6:width=iw:height=200:t=fill," | |
| "drawtext=text='17-08-1447':x=50:y=50:fontsize=30:fontcolor=white:box=1:boxcolor=0x4CAF50@0.8," | |
| "drawtext=text='RAMADAN COUNTDOWN':x=(w-text_w)/2:y=230:fontsize=40:fontcolor=white," | |
| "drawtext=text=' %{pts\\:localtime\\:1771372800\\:%d} \\: %{pts\\:localtime\\:1771372800\\:%H} \\: %{pts\\:localtime\\:1771372800\\:%M} \\: %{pts\\:localtime\\:1771372800\\:%S} ':x=(w-text_w)/2:y=(h-text_h)/2+50:fontsize=90:fontcolor=white:box=1:boxcolor=0x4CAF50@1:boxborderw=25" | |
| ), | |
| '-vcodec', 'libx264', '-preset', 'veryfast', '-b:v', '3000k', '-maxrate', '3000k', '-bufsize', '6000k', | |
| '-pix_fmt', 'yuv420p', '-g', '60', '-c:a', 'aac', '-b:a', '128k', '-f', 'flv', f"{STREAM_URL}{STREAM_KEY}" | |
| ] | |
| try: | |
| subprocess.run(ffmpeg_cmd, check=True) | |
| except: | |
| time.sleep(5) | |
| if __name__ == "__main__": | |
| threading.Thread(target=lambda: app.run(host='0.0.0.0', port=7860, debug=False, use_reloader=False), daemon=True).start() | |
| start_stream() |