Alide21 commited on
Commit
8a400ec
·
verified ·
1 Parent(s): 9a338dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -63
app.py CHANGED
@@ -6,46 +6,40 @@ import os
6
  from huggingface_hub import HfApi
7
  from datetime import datetime
8
 
9
- # إعدادات الأمان
10
  HF_TOKEN = os.getenv("HF_TOKEN")
11
  REPO_ID = "Alide21/speech_quran"
12
  api = HfApi()
13
 
14
- # CSS متطور لتحويل شكل الصفحة جذرياً
15
  custom_css = """
16
- body { background-color: #f4f1ea !important; }
17
- .gradio-container { font-family: 'Amiri', serif !important; direction: rtl !important; }
18
  .main-card {
19
- background: white !important;
20
- border-radius: 20px !important;
21
- padding: 25px !important;
22
- box-shadow: 0 10px 25px rgba(0,0,0,0.1) !important;
23
- border: 1px solid #e0d5b1 !important;
24
  }
25
  .ayah-box {
26
- background-color: #fdfdfd !important;
27
- border: 2px solid #d3af37 !important;
28
- padding: 40px 20px !important;
29
  border-radius: 15px !important;
30
- font-size: 32px !important;
 
31
  color: #2c3e50 !important;
32
- line-height: 1.8 !important;
33
  text-align: center !important;
 
34
  margin-bottom: 20px !important;
35
- font-weight: bold !important;
36
  }
37
- .stats-badge {
38
- background: #d3af37 !important;
39
  color: white !important;
40
- padding: 5px 15px !important;
41
- border-radius: 50px !important;
42
  font-weight: bold !important;
 
43
  }
44
- button.primary {
45
- background: linear-gradient(45deg, #d4af37, #b8860b) !important;
46
- border: none !important;
47
- }
48
- button.secondary { background: white !important; border: 1px solid #d3af37 !important; color: #d3af37 !important; }
49
  """
50
 
51
  def clean_text(text):
@@ -53,11 +47,10 @@ def clean_text(text):
53
 
54
  def load_quran_data():
55
  all_verses = []
56
- # سنحمل الفاتحة وسور أخرى للتجربة السريعة (يمكنك توسيع المدى لـ 115)
57
  for s in range(1, 115):
58
  try:
59
  url = f"https://raw.githubusercontent.com/CheeseWithSauce/TheHolyQuranJSONFormat/refs/heads/main/tajweedsurahs/{s:03}.json"
60
- res = requests.get(url, timeout=5)
61
  if res.status_code == 200:
62
  data = res.json()
63
  s_name = data.get("name_ar", "")
@@ -83,90 +76,99 @@ def get_stats():
83
 
84
  def save_submission(audio_path, current_idx, session_count):
85
  if audio_path is None:
86
- return "⚠️ يرجى التسجيل أولاً", gr.update(), gr.update(), current_idx, session_count, get_stats()
87
 
88
  verse = ALL_AYAT[current_idx]
89
  ext = audio_path.split('.')[-1]
 
90
  file_name = f"{verse['surah']}|{verse['ayah']}.{ext}"
91
 
92
  try:
93
- api.upload_file(path_or_fileobj=audio_path, path_in_repo=f"data/{file_name}",
94
- repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
 
 
 
 
 
95
 
96
- # البحث عن الآية التالية التي طولها مناسب
97
  next_idx = current_idx + 1
98
  while next_idx < len(ALL_AYAT) and len(ALL_AYAT[next_idx]["text"]) > 200:
99
  next_idx += 1
100
 
101
- if next_idx >= len(ALL_AYAT): next_idx = random.randint(0, len(ALL_AYAT)-1)
102
 
103
  new_v = ALL_AYAT[next_idx]
104
  new_sess = session_count + 1
105
  total = get_stats()
106
 
107
- return (f"✅ تم الحفظ بنجاح! آياتك اليوم: {new_sess}",
108
- f"<div class='ayah-box'>{new_v['text']}</div>",
109
- f"سورة {new_v['surah_name']} - آية {new_v['ayah']}",
110
  next_idx, new_sess, total)
111
  except Exception as e:
112
- return f"❌ خطأ: {str(e)}", gr.update(), gr.update(), current_idx, session_count, get_stats()
113
 
114
  def jump_to_verse(s_num, a_num):
115
  for i, v in enumerate(ALL_AYAT):
116
  if v["surah"] == s_num and v["ayah"] == a_num:
117
  if len(v["text"]) > 200:
118
- return f"<div class='ayah-box' style='color:red'>⚠️ الآية المختارة طويلة جداً ({len(v['text'])} رمز)</div>", gr.update(), i
119
- return f"<div class='ayah-box'>{v['text']}</div>", f"سورة {v['surah_name']} - آية {v['ayah']}", i
120
- return "<div class='ayah-box'>⚠️ لم يتم العثور على الآية</div>", gr.update(), 0
121
-
122
- with gr.Blocks(css=custom_css) as demo:
123
- # حالات مخفية
124
- current_verse_idx = gr.State(value=random.randint(0, len(ALL_AYAT)-1))
 
125
  session_counter = gr.State(value=0)
126
 
127
  with gr.Column(elem_classes="main-card"):
128
- gr.Markdown("<div style='text-align:center'><h1>🌙 منصة خادم القرآن</h1><p>ساهم بتسجيل صوتك لتدريب نماذج الذكاء الاصطناعي على تصحيح التلاوة</p></div>")
129
 
130
  with gr.Row():
131
- total_db = gr.Markdown(f"**إجمالي القاعدة:** <span class='stats-badge'>{get_stats()}</span>")
132
- user_sess = gr.Markdown("**مساهماتك الآن:** <span class='stats-badge'>0</span>")
133
-
134
- # عرض الآية
135
- initial_v = ALL_AYAT[current_verse_idx.value]
136
- ayah_info = gr.Markdown(f"### سورة {initial_v['surah_name']} - آية {initial_v['ayah']}", elem_id="info")
137
- ayah_display = gr.HTML(f"<div class='ayah-box'>{initial_v['text']}</div>")
138
-
139
- audio_input = gr.Audio(sources=["microphone", "upload"], type="filepath", label="سجل تلاوتك")
 
 
140
 
141
  with gr.Row():
142
  submit_btn = gr.Button("إرسال التسجيل ✅", variant="primary")
143
- random_btn = gr.Button("آية عشوائية 🎲", variant="secondary")
144
 
145
- status_msg = gr.Markdown("", text_align="center")
146
 
147
- with gr.Accordion("🔍 اختيار آية مخصصة", open=False):
148
  with gr.Row():
149
- s_input = gr.Number(label="رقم السورة", value=1, precision=0)
150
- a_input = gr.Number(label="رقم الآية", value=1, precision=0)
151
  go_btn = gr.Button("انتقال")
152
 
153
  # JavaScript لمنع الخروج
154
- demo.load(None, None, None, js="""() => { window.onbeforeunload = () => "تنبيه: ستفقد التسجيل غير المحفوظ!"; }""")
155
 
156
- # الأوامر البرمجية
157
  def get_random():
158
  idx = random.randint(0, len(ALL_AYAT)-1)
159
  v = ALL_AYAT[idx]
160
  return f"<div class='ayah-box'>{v['text']}</div>", f"### سورة {v['surah_name']} - آية {v['ayah']}", idx
161
 
162
  random_btn.click(get_random, outputs=[ayah_display, ayah_info, current_verse_idx])
163
-
164
  go_btn.click(jump_to_verse, inputs=[s_input, a_input], outputs=[ayah_display, ayah_info, current_verse_idx])
165
-
166
  submit_btn.click(
167
  save_submission,
168
  inputs=[audio_input, current_verse_idx, session_counter],
169
  outputs=[status_msg, ayah_display, ayah_info, current_verse_idx, session_counter, total_db]
170
- ).then(lambda count: f"**مساهماتك الآن:** <span class='stats-badge'>{count}</span>", inputs=session_counter, outputs=user_sess)
171
 
172
- demo.launch()
 
 
6
  from huggingface_hub import HfApi
7
  from datetime import datetime
8
 
9
+ # إعدادات الأمان والاتصال
10
  HF_TOKEN = os.getenv("HF_TOKEN")
11
  REPO_ID = "Alide21/speech_quran"
12
  api = HfApi()
13
 
14
+ # تحسين المظهريم مذهب وفخم)
15
  custom_css = """
16
+ .gradio-container { background-color: #fcfaf5 !important; direction: rtl !important; font-family: 'Amiri', serif !important; }
 
17
  .main-card {
18
+ border: 2px solid #d4af37 !important;
19
+ border-radius: 25px !important;
20
+ padding: 30px !important;
21
+ background: white !important;
22
+ box-shadow: 0 15px 35px rgba(212, 175, 55, 0.1) !important;
23
  }
24
  .ayah-box {
25
+ background: #fdf6e3 !important;
 
 
26
  border-radius: 15px !important;
27
+ padding: 40px 20px !important;
28
+ font-size: 30px !important;
29
  color: #2c3e50 !important;
30
+ line-height: 2 !important;
31
  text-align: center !important;
32
+ border-bottom: 4px solid #d4af37 !important;
33
  margin-bottom: 20px !important;
 
34
  }
35
+ .stats-info {
36
+ background: #d4af37 !important;
37
  color: white !important;
38
+ padding: 8px 20px !important;
39
+ border-radius: 15px !important;
40
  font-weight: bold !important;
41
+ text-align: center !important;
42
  }
 
 
 
 
 
43
  """
44
 
45
  def clean_text(text):
 
47
 
48
  def load_quran_data():
49
  all_verses = []
 
50
  for s in range(1, 115):
51
  try:
52
  url = f"https://raw.githubusercontent.com/CheeseWithSauce/TheHolyQuranJSONFormat/refs/heads/main/tajweedsurahs/{s:03}.json"
53
+ res = requests.get(url, timeout=10)
54
  if res.status_code == 200:
55
  data = res.json()
56
  s_name = data.get("name_ar", "")
 
76
 
77
  def save_submission(audio_path, current_idx, session_count):
78
  if audio_path is None:
79
+ return "⚠️ يرجى تسجيل الصوت أولاً قبل الإرسال", gr.update(), gr.update(), current_idx, session_count, get_stats()
80
 
81
  verse = ALL_AYAT[current_idx]
82
  ext = audio_path.split('.')[-1]
83
+ # الصيغة المطلوبة {رقم السورة}|{رقم الآية}
84
  file_name = f"{verse['surah']}|{verse['ayah']}.{ext}"
85
 
86
  try:
87
+ api.upload_file(
88
+ path_or_fileobj=audio_path,
89
+ path_in_repo=f"data/{file_name}",
90
+ repo_id=REPO_ID,
91
+ repo_type="dataset",
92
+ token=HF_TOKEN
93
+ )
94
 
95
+ # الانتقال للآية التالية تلقائياً مع فحص الطول
96
  next_idx = current_idx + 1
97
  while next_idx < len(ALL_AYAT) and len(ALL_AYAT[next_idx]["text"]) > 200:
98
  next_idx += 1
99
 
100
+ if next_idx >= len(ALL_AYAT): next_idx = 0
101
 
102
  new_v = ALL_AYAT[next_idx]
103
  new_sess = session_count + 1
104
  total = get_stats()
105
 
106
+ msg = f"✅ تم الحفظ بنجاح! آياتك في هذه الجلسة: {new_sess}"
107
+ return (msg, f"<div class='ayah-box'>{new_v['text']}</div>",
108
+ f"### سورة {new_v['surah_name']} - آية {new_v['ayah']}",
109
  next_idx, new_sess, total)
110
  except Exception as e:
111
+ return f"❌ فشل الرفع: {str(e)}", gr.update(), gr.update(), current_idx, session_count, get_stats()
112
 
113
  def jump_to_verse(s_num, a_num):
114
  for i, v in enumerate(ALL_AYAT):
115
  if v["surah"] == s_num and v["ayah"] == a_num:
116
  if len(v["text"]) > 200:
117
+ return f"<div class='ayah-box' style='color:#e74c3c'>⚠️ الآية طويلة جداً ({len(v['text'])} حرف)</div>", f"سورة {v['surah_name']} - آية {v['ayah']}", i
118
+ return f"<div class='ayah-box'>{v['text']}</div>", f"### سورة {v['surah_name']} - آية {v['ayah']}", i
119
+ return "<div class='ayah-box' style='color:#e74c3c'>⚠️ لم يتم العثور على الآية</div>", "غير موجود", 0
120
+
121
+ # بناء الواجهة
122
+ with gr.Blocks(title="خادم القرآن") as demo:
123
+ # تخزين المتغيرات برمجياً
124
+ current_verse_idx = gr.State(value=random.randint(0, len(ALL_AYAT)-1) if ALL_AYAT else 0)
125
  session_counter = gr.State(value=0)
126
 
127
  with gr.Column(elem_classes="main-card"):
128
+ gr.Markdown("<div style='text-align:center'><h1>🌙 مشروع جامع التلاوات</h1><p>صوتك يساعد في تدريب ذكاء اصطناعي لخدمة كتاب الله</p></div>")
129
 
130
  with gr.Row():
131
+ total_db = gr.Number(label="إجمالي التسجيلات", value=get_stats(), interactive=False)
132
+ user_sess = gr.Number(label="آيات سجلتها الآن", value=0, interactive=False)
133
+
134
+ # عرض الآية الحالية
135
+ if ALL_AYAT:
136
+ init_idx = current_verse_idx.value
137
+ initial_v = ALL_AYAT[init_idx]
138
+ ayah_info = gr.Markdown(f"### سورة {initial_v['surah_name']} - آية {initial_v['ayah']}")
139
+ ayah_display = gr.HTML(f"<div class='ayah-box'>{initial_v['text']}</div>")
140
+
141
+ audio_input = gr.Audio(sources=["microphone", "upload"], type="filepath", label="سجل أو ارفع الملف")
142
 
143
  with gr.Row():
144
  submit_btn = gr.Button("إرسال التسجيل ✅", variant="primary")
145
+ random_btn = gr.Button("آية عشوائية 🎲")
146
 
147
+ status_msg = gr.Markdown("")
148
 
149
+ with gr.Accordion("🔍 اختيار آية محددة", open=False):
150
  with gr.Row():
151
+ s_input = gr.Number(label="رقم السورة (1-114)", precision=0)
152
+ a_input = gr.Number(label="رقم الآية", precision=0)
153
  go_btn = gr.Button("انتقال")
154
 
155
  # JavaScript لمنع الخروج
156
+ demo.load(None, None, None, js="""() => { window.onbeforeunload = () => "تنبيه: هل تريد الخروج قبل حفظ تسجيلك؟"; }""")
157
 
158
+ # المنطق البرمجي للأزرار
159
  def get_random():
160
  idx = random.randint(0, len(ALL_AYAT)-1)
161
  v = ALL_AYAT[idx]
162
  return f"<div class='ayah-box'>{v['text']}</div>", f"### سورة {v['surah_name']} - آية {v['ayah']}", idx
163
 
164
  random_btn.click(get_random, outputs=[ayah_display, ayah_info, current_verse_idx])
 
165
  go_btn.click(jump_to_verse, inputs=[s_input, a_input], outputs=[ayah_display, ayah_info, current_verse_idx])
166
+
167
  submit_btn.click(
168
  save_submission,
169
  inputs=[audio_input, current_verse_idx, session_counter],
170
  outputs=[status_msg, ayah_display, ayah_info, current_verse_idx, session_counter, total_db]
171
+ )
172
 
173
+ # تشغيل الموقع مع الـ CSS الصحيح
174
+ demo.launch(css=custom_css)