Skydata001 commited on
Commit
ab40db7
·
verified ·
1 Parent(s): 34ac40d

Rename main.py to app.py

Browse files
Files changed (2) hide show
  1. app.py +320 -0
  2. main.py +0 -233
app.py ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import cv2
3
+ import numpy as np
4
+ from PIL import Image
5
+ import io
6
+ import zipfile
7
+ import os
8
+ from datetime import datetime
9
+ import tempfile
10
+
11
+ from sprite_processor import SpriteProcessor
12
+ from frame_detector import FrameDetector
13
+ from frame_namer import FrameNamer
14
+
15
+ # Page config
16
+ st.set_page_config(
17
+ page_title="AI Sprite Frame Extractor",
18
+ page_icon="🎮",
19
+ layout="wide",
20
+ initial_sidebar_state="expanded"
21
+ )
22
+
23
+ # Custom CSS
24
+ st.markdown("""
25
+ <style>
26
+ .main-header {
27
+ text-align: center;
28
+ padding: 2rem 0;
29
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
30
+ border-radius: 15px;
31
+ margin-bottom: 2rem;
32
+ }
33
+ .main-header h1 {
34
+ color: white;
35
+ font-size: 3rem;
36
+ margin: 0;
37
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
38
+ }
39
+ .main-header p {
40
+ color: rgba(255,255,255,0.9);
41
+ font-size: 1.2rem;
42
+ margin-top: 0.5rem;
43
+ }
44
+ .feature-card {
45
+ background: linear-gradient(145deg, #f5f7fa 0%, #c3cfe2 100%);
46
+ padding: 1.5rem;
47
+ border-radius: 10px;
48
+ margin: 1rem 0;
49
+ border-left: 4px solid #667eea;
50
+ }
51
+ .stButton>button {
52
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
53
+ color: white;
54
+ font-weight: bold;
55
+ padding: 0.75rem 2rem;
56
+ border-radius: 25px;
57
+ border: none;
58
+ font-size: 1.1rem;
59
+ transition: all 0.3s ease;
60
+ }
61
+ .stButton>button:hover {
62
+ transform: translateY(-2px);
63
+ box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
64
+ }
65
+ .success-box {
66
+ background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
67
+ color: white;
68
+ padding: 1rem;
69
+ border-radius: 10px;
70
+ text-align: center;
71
+ }
72
+ .frame-preview {
73
+ border: 2px solid #667eea;
74
+ border-radius: 8px;
75
+ padding: 5px;
76
+ margin: 5px;
77
+ }
78
+ </style>
79
+ """, unsafe_allow_html=True)
80
+
81
+ # Header
82
+ st.markdown("""
83
+ <div class="main-header">
84
+ <h1>🎮 AI Sprite Frame Extractor</h1>
85
+ <p>استخرج وحسّن إطارات Sprite Sheets بذكاء اصطناعي</p>
86
+ </div>
87
+ """, unsafe_allow_html=True)
88
+
89
+ # Sidebar
90
+ with st.sidebar:
91
+ st.markdown("## ⚙️ الإعدادات")
92
+
93
+ st.markdown("### 🔧 خيارات المعالجة")
94
+
95
+ enhance_quality = st.checkbox("✨ تحسين الجودة (Upscale)", value=True,
96
+ help="رفع دقة الصورة وإزالة الضبابية")
97
+
98
+ if enhance_quality:
99
+ scale_factor = st.slider("📏 معامل التكبير", 2, 4, 4,
100
+ help="2x = ضعف الحجم، 4x = أربع أضعاف")
101
+ else:
102
+ scale_factor = 1
103
+
104
+ auto_detect = st.checkbox("🤖 اكتشاف تلقائي للإطارات", value=True,
105
+ help="تحديد الإطارات تلقائياً")
106
+
107
+ if not auto_detect:
108
+ manual_frames = st.number_input("عدد الإطارات", min_value=1, max_value=50, value=8)
109
+
110
+ smart_naming = st.checkbox("🏷️ تسمية ذكية", value=True,
111
+ help="تحديد نوع الحركة تلقائياً")
112
+
113
+ padding = st.slider("📐 الهوامش الداخلية", 0, 20, 2,
114
+ help="إضافة هوامش حول كل إطار")
115
+
116
+ st.markdown("---")
117
+ st.markdown("### 📊 معلومات")
118
+ st.info("💡 **نصيحة:** تأكد من أن الصورة بخلفية شفافة للحصول على أفضل نتائج")
119
+
120
+ # Main content
121
+ st.markdown("## 📤 رفع الصورة")
122
+
123
+ uploaded_file = st.file_uploader(
124
+ "اختر صورة Sprite Sheet",
125
+ type=['png', 'jpg', 'jpeg', 'webp'],
126
+ help="صورة تحتوي على إطارات متحركة متتالية"
127
+ )
128
+
129
+ if uploaded_file is not None:
130
+ # Read image
131
+ file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
132
+ original_image = cv2.imdecode(file_bytes, cv2.IMREAD_UNCHANGED)
133
+
134
+ # Display original
135
+ col1, col2 = st.columns(2)
136
+
137
+ with col1:
138
+ st.markdown("### 🖼️ الصورة الأصلية")
139
+
140
+ # Convert for display
141
+ if len(original_image.shape) == 3 and original_image.shape[2] == 4:
142
+ display_img = cv2.cvtColor(original_image, cv2.COLOR_BGRA2RGBA)
143
+ else:
144
+ display_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)
145
+
146
+ st.image(display_img, use_column_width=True)
147
+
148
+ st.markdown(f"""
149
+ **الأبعاد:** {original_image.shape[1]} × {original_image.shape[0]} px
150
+ **القنوات:** {original_image.shape[2] if len(original_image.shape) == 3 else 1}
151
+ """)
152
+
153
+ # Process button
154
+ st.markdown("---")
155
+
156
+ if st.button("🚀 بدء المعالجة", use_container_width=True):
157
+ with st.spinner("⏳ جاري المعالجة... قد يستغرق هذا ب��ع دقائق"):
158
+
159
+ # Initialize processors
160
+ progress_bar = st.progress(0)
161
+ status_text = st.empty()
162
+
163
+ # Step 1: Enhance quality
164
+ if enhance_quality:
165
+ status_text.text("✨ جاري تحسين جودة الصورة...")
166
+ processor = SpriteProcessor()
167
+ enhanced_image = processor.enhance_image(original_image, scale_factor)
168
+ progress_bar.progress(25)
169
+ else:
170
+ enhanced_image = original_image
171
+ progress_bar.progress(25)
172
+
173
+ # Step 2: Detect frames
174
+ status_text.text("🔍 جاري اكتشاف الإطارات...")
175
+ detector = FrameDetector()
176
+
177
+ if auto_detect:
178
+ frames, frame_boxes = detector.detect_frames_auto(enhanced_image, padding)
179
+ else:
180
+ frames, frame_boxes = detector.detect_frames_manual(enhanced_image, manual_frames, padding)
181
+
182
+ progress_bar.progress(60)
183
+
184
+ # Step 3: Smart naming
185
+ if smart_naming:
186
+ status_text.text("🏷️ جاري تحليل وتسمية الإطارات...")
187
+ namer = FrameNamer()
188
+ frame_names = namer.name_frames(frames)
189
+ else:
190
+ frame_names = [f"frame_{i:03d}" for i in range(len(frames))]
191
+
192
+ progress_bar.progress(80)
193
+
194
+ # Step 4: Create ZIP
195
+ status_text.text("📦 جاري إنشاء ملف ZIP...")
196
+ zip_buffer = io.BytesIO()
197
+
198
+ with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
199
+ for i, (frame, name) in enumerate(zip(frames, frame_names)):
200
+ # Convert frame to PNG bytes
201
+ if len(frame.shape) == 3 and frame.shape[2] == 4:
202
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGRA2RGBA)
203
+ else:
204
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
205
+
206
+ pil_img = Image.fromarray(frame_rgb)
207
+ img_buffer = io.BytesIO()
208
+ pil_img.save(img_buffer, format='PNG')
209
+ img_buffer.seek(0)
210
+
211
+ zip_file.writestr(f"{name}.png", img_buffer.getvalue())
212
+
213
+ # Add info file
214
+ info_content = f"""Sprite Frame Extractor - Export Report
215
+ Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
216
+ Total Frames: {len(frames)}
217
+ Original Size: {original_image.shape[1]}x{original_image.shape[0]}
218
+ Enhanced: {'Yes (' + str(scale_factor) + 'x)' if enhance_quality else 'No'}
219
+
220
+ Frame List:
221
+ """
222
+ for i, name in enumerate(frame_names):
223
+ info_content += f" {i+1}. {name}.png\n"
224
+
225
+ zip_file.writestr("info.txt", info_content)
226
+
227
+ zip_buffer.seek(0)
228
+ progress_bar.progress(100)
229
+ status_text.empty()
230
+
231
+ # Display results
232
+ with col2:
233
+ st.markdown("### ✅ النتيجة")
234
+
235
+ if enhance_quality:
236
+ st.markdown(f"**الأبعاد بعد التحسين:** {enhanced_image.shape[1]} × {enhanced_image.shape[0]} px")
237
+
238
+ st.markdown(f"**عدد الإطارات المكتشفة:** {len(frames)}")
239
+
240
+ # Show frame previews
241
+ st.markdown("### 👁️ معاينة الإطارات")
242
+
243
+ preview_cols = st.columns(min(4, len(frames)))
244
+ for i, (frame, name) in enumerate(zip(frames[:8], frame_names[:8])):
245
+ with preview_cols[i % 4]:
246
+ if len(frame.shape) == 3 and frame.shape[2] == 4:
247
+ display_frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2RGBA)
248
+ else:
249
+ display_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
250
+
251
+ st.image(display_frame, caption=name, use_column_width=True)
252
+
253
+ if len(frames) > 8:
254
+ st.info(f"... و {len(frames) - 8} إطارات أخرى")
255
+
256
+ # Download button
257
+ st.markdown("---")
258
+ st.markdown("### 📥 التحميل")
259
+
260
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
261
+
262
+ st.download_button(
263
+ label="⬇️ تحميل ملف ZIP",
264
+ data=zip_buffer,
265
+ file_name=f"sprite_frames_{timestamp}.zip",
266
+ mime="application/zip",
267
+ use_container_width=True
268
+ )
269
+
270
+ st.markdown("""
271
+ <div class="success-box">
272
+ <h3>🎉 تمت المعالجة بنج��ح!</h3>
273
+ <p>تم استخراج {} إطار وجاهزة للاستخدام</p>
274
+ </div>
275
+ """.format(len(frames)), unsafe_allow_html=True)
276
+
277
+ else:
278
+ # Show features when no image uploaded
279
+ st.markdown("---")
280
+ st.markdown("## ✨ مميزات الأداة")
281
+
282
+ col1, col2, col3 = st.columns(3)
283
+
284
+ with col1:
285
+ st.markdown("""
286
+ <div class="feature-card">
287
+ <h3>🔍 تحسين الجودة</h3>
288
+ <p>استخدام تقنية Real-ESRGAN لرفع دقة الصور وإزالة الضبابية مع الحفاظ على جودة البكسل</p>
289
+ </div>
290
+ """, unsafe_allow_html=True)
291
+
292
+ with col2:
293
+ st.markdown("""
294
+ <div class="feature-card">
295
+ <h3>🤖 اكتشاف ذكي</h3>
296
+ <p>اكتشاف الإطارات تلقائياً باستخدام خوارزميات متقدمة للرؤية الحاسوبية</p>
297
+ </div>
298
+ """, unsafe_allow_html=True)
299
+
300
+ with col3:
301
+ st.markdown("""
302
+ <div class="feature-card">
303
+ <h3>🏷️ تسمية ذكية</h3>
304
+ <p>تحديد نوع الحركة (Idle, Run, Attack...) تلقائياً باستخدام نماذج التعلم العميق</p>
305
+ </div>
306
+ """, unsafe_allow_html=True)
307
+
308
+ # Example section
309
+ st.markdown("---")
310
+ st.markdown("## 📋 كيفية الاستخدام")
311
+
312
+ st.markdown("""
313
+ 1. **📤 ارفع الصورة** - اختر ملف Sprite Sheet بخلفية شفافة
314
+ 2. **⚙️ اضبط الإعدادات** - فعّل خيارات التحسين والتسمية الذكية حسب الحاجة
315
+ 3. **🚀 ابدأ المعالجة** - اضغط على زر المعالجة وانتظر قليلاً
316
+ 4. **📥 حمل النتيجة** - احصل على ملف ZIP يحتوي على جميع الإطارات
317
+ """)
318
+
319
+ st.markdown("---")
320
+ st.info("💡 **ملاحظة:** للحصول على أفضل النتائج، تأكد من أن الصورة بخلفية شفافة (PNG مع قناة ألفا)")
main.py DELETED
@@ -1,233 +0,0 @@
1
- import discord
2
- from discord.ext import commands, tasks
3
- from discord import app_commands
4
- import io
5
- import aiohttp
6
- from aiohttp import web # أضفنا مكتبة الويب
7
- from PIL import Image, ImageDraw, ImageFont, ImageEnhance
8
- import datetime
9
- import random
10
- import traceback
11
- import os
12
-
13
- # ==========================================
14
- # 1. إعدادات البوت الأساسية والمعرفات
15
- # ==========================================
16
- SERVER_ID = 1485773565772173367
17
- ADMIN_ROLE_ID = 1488187501142216826
18
- WELCOME_CHANNEL_ID = 1485773566736597125
19
- LOGS_CHANNEL_ID = 1485773566736597129
20
- CONTROL_CHANNEL_ID = 1485773566736597127
21
-
22
- WELCOME_MESSAGES = [
23
- "مرحباً بك في مجتمعنا! نتمنى لك وقتاً ممتعاً.",
24
- "أهلاً بك في خادمنا، نورت المكان!",
25
- "سعداء بانضمامك إلينا، مرحباً بك!",
26
- "يا هلا ومرحب! خطوة عزيزة في سيرفرنا."
27
- ]
28
-
29
- POLYGON_COORDS = [
30
- (227, 307), (251, 299), (286, 291), (318, 297), (344, 297),
31
- (371, 297), (397, 297), (429, 299), (461, 302), (493, 299),
32
- (509, 321), (522, 355), (533, 387), (530, 427), (528, 475),
33
- (520, 517), (509, 546), (482, 562), (445, 581), (403, 594),
34
- (350, 602), (304, 597), (259, 578), (222, 546), (193, 504),
35
- (188, 459), (185, 411), (193, 374), (209, 334)
36
- ]
37
-
38
- daily_stats = {"joins": 0, "leaves": 0, "errors": 0}
39
-
40
- intents = discord.Intents.default()
41
- intents.members = True
42
- intents.message_content = True
43
- bot = commands.Bot(command_prefix="!", intents=intents)
44
-
45
- # ==========================================
46
- # 2. خادم الويب الوهمي لـ Hugging Face
47
- # ==========================================
48
- async def web_server():
49
- app = web.Application()
50
- app.router.add_get('/', lambda r: web.Response(text="Bot is running smoothly!"))
51
- runner = web.AppRunner(app)
52
- await runner.setup()
53
- site = web.TCPSite(runner, '0.0.0.0', 7860)
54
- await site.start()
55
- print("🌐 تم تشغيل خادم الويب الوهمي بنجاح على المنفذ 7860 (Hugging Face سيصبح Running الآن)")
56
-
57
- # ==========================================
58
- # 3. دوال مساعدة (معالجة الصور)
59
- # ==========================================
60
- async def generate_welcome_image(member: discord.Member):
61
- async with aiohttp.ClientSession() as session:
62
- bg_url = "https://i.ibb.co/fVzTX4sr/c24b17434824edeab1c3ce02bef9072f.jpg"
63
- async with session.get(bg_url) as resp:
64
- bg_bytes = await resp.read()
65
- bg_image = Image.open(io.BytesIO(bg_bytes)).convert("RGBA")
66
-
67
- avatar_url = member.display_avatar.with_format("png").with_size(512).url
68
- async with session.get(avatar_url) as resp:
69
- avatar_bytes = await resp.read()
70
- avatar_image = Image.open(io.BytesIO(avatar_bytes)).convert("RGBA")
71
-
72
- avatar_image = avatar_image.resize((360, 360))
73
-
74
- mask = Image.new("L", bg_image.size, 0)
75
- draw = ImageDraw.Draw(mask)
76
- draw.polygon(POLYGON_COORDS, fill=255)
77
-
78
- avatar_layer = Image.new("RGBA", bg_image.size, (0, 0, 0, 0))
79
- avatar_layer.paste(avatar_image, (185, 290))
80
-
81
- purple_filter = Image.new("RGBA", avatar_layer.size, (128, 0, 128, 60))
82
- avatar_layer = Image.alpha_composite(avatar_layer, purple_filter)
83
-
84
- final_image = Image.composite(avatar_layer, bg_image, mask)
85
-
86
- draw_final = ImageDraw.Draw(final_image)
87
- try:
88
- font = ImageFont.truetype("arial.ttf", 36)
89
- except:
90
- font = ImageFont.load_default()
91
-
92
- text = f"#{member.name}"
93
- draw_final.text((368, 630), text, fill=(100, 0, 150), font=font, anchor="mm")
94
-
95
- final_buffer = io.BytesIO()
96
- final_image.save(final_buffer, format="PNG")
97
- final_buffer.seek(0)
98
- return final_buffer
99
-
100
- # ==========================================
101
- # 4. أحداث البوت (Events)
102
- # ==========================================
103
- @bot.event
104
- async def setup_hook():
105
- # تشغيل خادم الويب في الخلفية مع بداية عمل البوت
106
- bot.loop.create_task(web_server())
107
-
108
- @bot.event
109
- async def on_ready():
110
- print(f"✅ تم تسجيل الدخول كـ {bot.user}")
111
- daily_stats_task.start()
112
- try:
113
- synced = await bot.tree.sync()
114
- print(f"🔄 تم مزامنة {len(synced)} أوامر سلاش.")
115
- except Exception as e:
116
- print(f"❌ خطأ في المزامنة: {e}")
117
-
118
- @bot.event
119
- async def on_member_join(member: discord.Member):
120
- if member.guild.id != SERVER_ID:
121
- return
122
-
123
- daily_stats["joins"] += 1
124
- channel = bot.get_channel(WELCOME_CHANNEL_ID)
125
-
126
- if channel:
127
- try:
128
- image_buffer = await generate_welcome_image(member)
129
- file = discord.File(fp=image_buffer, filename="welcome.png")
130
-
131
- embed = discord.Embed(
132
- title="🎉 عضو جديد انضم إلينا!",
133
- description=random.choice(WELCOME_MESSAGES),
134
- color=discord.Color.purple()
135
- )
136
- embed.add_field(name="👤 العضو", value=member.mention, inline=True)
137
- embed.add_field(name="📅 تاريخ الانضمام", value=f"<t:{int(datetime.datetime.now().timestamp())}:d>", inline=True)
138
- embed.add_field(name="📈 رقم العضو", value=f"أنت العضو رقم {member.guild.member_count}", inline=False)
139
- embed.set_image(url="attachment://welcome.png")
140
-
141
- msg = await channel.send(content=member.mention, embed=embed, file=file)
142
- await msg.add_reaction("👋")
143
-
144
- logs_channel = bot.get_channel(LOGS_CHANNEL_ID)
145
- if logs_channel:
146
- await logs_channel.send(f"✅ **دخول:** {member.mention} انضم للسيرفر.")
147
-
148
- except Exception as e:
149
- daily_stats["errors"] += 1
150
- logs_channel = bot.get_channel(LOGS_CHANNEL_ID)
151
- if logs_channel:
152
- await logs_channel.send(f"❌ **خطأ في الترحيب (تأكد من صلاحيات رفع الملفات للسيرفر):** `{e}`")
153
-
154
- @bot.event
155
- async def on_member_remove(member: discord.Member):
156
- if member.guild.id != SERVER_ID:
157
- return
158
- daily_stats["leaves"] += 1
159
- logs_channel = bot.get_channel(LOGS_CHANNEL_ID)
160
- if logs_channel:
161
- await logs_channel.send(f"🚪 **خروج:** {member.name} غادر السيرفر.")
162
-
163
- # ==========================================
164
- # 5. المهام المجدولة (Tasks)
165
- # ==========================================
166
- @tasks.loop(hours=24)
167
- async def daily_stats_task():
168
- logs_channel = bot.get_channel(LOGS_CHANNEL_ID)
169
- if logs_channel:
170
- joins = daily_stats["joins"]
171
- leaves = daily_stats["leaves"]
172
- growth = joins - leaves
173
-
174
- embed = discord.Embed(title="📊 إحصائيات الـ 24 ساعة الماضية", color=discord.Color.blue())
175
- embed.add_field(name="📥 الدخول", value=str(joins), inline=True)
176
- embed.add_field(name="📤 الخروج", value=str(leaves), inline=True)
177
- embed.add_field(name="📈 نسبة النمو", value=f"{growth} أعضاء", inline=False)
178
- embed.add_field(name="❌ الأخطاء", value=str(daily_stats["errors"]), inline=False)
179
-
180
- await logs_channel.send(embed=embed)
181
-
182
- daily_stats["joins"] = 0
183
- daily_stats["leaves"] = 0
184
- daily_stats["errors"] = 0
185
-
186
- @daily_stats_task.before_loop
187
- async def before_daily_stats():
188
- await bot.wait_until_ready()
189
-
190
- # ==========================================
191
- # 6. أوامر السلاش (Slash Commands)
192
- # ==========================================
193
- @bot.tree.command(name="تجربة_ترحيب", description="تجربة نظام الترحيب على عضو معين")
194
- @app_commands.describe(member="العضو الذي تريد تجربة الترحيب عليه")
195
- async def test_welcome(interaction: discord.Interaction, member: discord.Member):
196
- if interaction.channel_id != CONTROL_CHANNEL_ID:
197
- return await interaction.response.send_message("❌ لا يمكنك استخدام هذا الأمر هنا.", ephemeral=True)
198
-
199
- if not any(role.id == ADMIN_ROLE_ID for role in interaction.user.roles) and interaction.user.id != interaction.guild.owner_id:
200
- return await interaction.response.send_message("❌ لا تملك صلاحية استخدام هذا الأمر.", ephemeral=True)
201
-
202
- await interaction.response.defer(ephemeral=True)
203
-
204
- try:
205
- channel = bot.get_channel(WELCOME_CHANNEL_ID)
206
- image_buffer = await generate_welcome_image(member)
207
- file = discord.File(fp=image_buffer, filename="welcome.png")
208
-
209
- embed = discord.Embed(
210
- title="🎉 عضو جديد انضم إلينا! (تجربة)",
211
- description=random.choice(WELCOME_MESSAGES),
212
- color=discord.Color.purple()
213
- )
214
- embed.add_field(name="👤 العضو", value=member.mention, inline=True)
215
- embed.add_field(name="📅 تاريخ الانضمام", value=f"<t:{int(datetime.datetime.now().timestamp())}:d>", inline=True)
216
- embed.add_field(name="📈 رقم العضو", value=f"أنت العضو رقم {member.guild.member_count}", inline=False)
217
- embed.set_image(url="attachment://welcome.png")
218
-
219
- msg = await channel.send(content=member.mention, embed=embed, file=file)
220
- await msg.add_reaction("👋")
221
-
222
- await interaction.followup.send("✅ تم إرسال رسالة التجربة بنجاح في قناة الترحيب.")
223
- except Exception as e:
224
- await interaction.followup.send(f"❌ حدث خطأ أثناء التجربة: {e}\n(يرجى التأكد من أن البوت يمتلك صلاحية إرفاق الملفات في إعدادات السيرفر والقناة)")
225
-
226
- # ==========================================
227
- # 7. تشغيل البوت
228
- # ==========================================
229
- TOKEN = os.environ.get("BOT_TOKEN")
230
- if TOKEN:
231
- bot.run(TOKEN)
232
- else:
233
- print("❌ خطأ: ��م يتم العثور على التوكن. يرجى إضافة BOT_TOKEN إلى بيئة العمل.")