Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -3,6 +3,7 @@ from discord.ext import commands, tasks
|
|
| 3 |
from discord import app_commands
|
| 4 |
import io
|
| 5 |
import aiohttp
|
|
|
|
| 6 |
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
|
| 7 |
import datetime
|
| 8 |
import random
|
|
@@ -18,7 +19,6 @@ WELCOME_CHANNEL_ID = 1492284129792888986
|
|
| 18 |
LOGS_CHANNEL_ID = 1492544227505213490
|
| 19 |
CONTROL_CHANNEL_ID = 1492544049255678085
|
| 20 |
|
| 21 |
-
# قائمة رسائل الترحيب العشوائية
|
| 22 |
WELCOME_MESSAGES = [
|
| 23 |
"مرحباً بك في مجتمعنا! نتمنى لك وقتاً ممتعاً.",
|
| 24 |
"أهلاً بك في خادمنا، نورت المكان!",
|
|
@@ -26,7 +26,6 @@ WELCOME_MESSAGES = [
|
|
| 26 |
"يا هلا ومرحب! خطوة عزيزة في سيرفرنا."
|
| 27 |
]
|
| 28 |
|
| 29 |
-
# الإحداثيات التي قمت بتحديدها لقص صورة العضو (من 1 إلى 29)
|
| 30 |
POLYGON_COORDS = [
|
| 31 |
(227, 307), (251, 299), (286, 291), (318, 297), (344, 297),
|
| 32 |
(371, 297), (397, 297), (429, 299), (461, 302), (493, 299),
|
|
@@ -36,87 +35,88 @@ POLYGON_COORDS = [
|
|
| 36 |
(188, 459), (185, 411), (193, 374), (209, 334)
|
| 37 |
]
|
| 38 |
|
| 39 |
-
# متغيرات الإحصائيات اليومية
|
| 40 |
daily_stats = {"joins": 0, "leaves": 0, "errors": 0}
|
| 41 |
|
| 42 |
-
# إعداد الصلاحيات (Intents) المطلوبة لعمل البوت
|
| 43 |
intents = discord.Intents.default()
|
| 44 |
intents.members = True
|
| 45 |
intents.message_content = True
|
| 46 |
bot = commands.Bot(command_prefix="!", intents=intents)
|
| 47 |
|
| 48 |
# ==========================================
|
| 49 |
-
# 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
# ==========================================
|
| 51 |
async def generate_welcome_image(member: discord.Member):
|
| 52 |
async with aiohttp.ClientSession() as session:
|
| 53 |
-
# تحميل الخلفية الأصلية
|
| 54 |
bg_url = "https://i.ibb.co/fVzTX4sr/c24b17434824edeab1c3ce02bef9072f.jpg"
|
| 55 |
async with session.get(bg_url) as resp:
|
| 56 |
bg_bytes = await resp.read()
|
| 57 |
bg_image = Image.open(io.BytesIO(bg_bytes)).convert("RGBA")
|
| 58 |
|
| 59 |
-
# تحميل صورة العضو الشخصية
|
| 60 |
avatar_url = member.display_avatar.with_format("png").with_size(512).url
|
| 61 |
async with session.get(avatar_url) as resp:
|
| 62 |
avatar_bytes = await resp.read()
|
| 63 |
avatar_image = Image.open(io.BytesIO(avatar_bytes)).convert("RGBA")
|
| 64 |
|
| 65 |
-
# تحديد حجم صورة العضو لتغطي مساحة الإحداثيات تقريباً (من 180 إلى 540)
|
| 66 |
avatar_image = avatar_image.resize((360, 360))
|
| 67 |
|
| 68 |
-
# إنشاء قناع (Mask) بنفس حجم الخلفية (736x736)
|
| 69 |
mask = Image.new("L", bg_image.size, 0)
|
| 70 |
draw = ImageDraw.Draw(mask)
|
| 71 |
-
draw.polygon(POLYGON_COORDS, fill=255)
|
| 72 |
|
| 73 |
-
# إنشاء طبقة فارغة لوضع صورة العضو فيها بناءً على موقع الإحداثيات
|
| 74 |
avatar_layer = Image.new("RGBA", bg_image.size, (0, 0, 0, 0))
|
| 75 |
-
# نضع صورة العضو في منتصف الإحداثيات (حساب تقريبي بناءً على الإحداثيات)
|
| 76 |
avatar_layer.paste(avatar_image, (185, 290))
|
| 77 |
|
| 78 |
-
|
| 79 |
-
purple_filter = Image.new("RGBA", avatar_layer.size, (128, 0, 128, 60)) # بنفسجي شفاف
|
| 80 |
avatar_layer = Image.alpha_composite(avatar_layer, purple_filter)
|
| 81 |
|
| 82 |
-
# دمج صورة العضو مع الخلفية باستخدام القناع
|
| 83 |
final_image = Image.composite(avatar_layer, bg_image, mask)
|
| 84 |
|
| 85 |
-
# إضافة نص (اسم المستخدم) تحت الصورة
|
| 86 |
draw_final = ImageDraw.Draw(final_image)
|
| 87 |
try:
|
| 88 |
-
# إذا كان لديك خط، قم برفعه وتغيير الاسم هنا. حالياً نستخدم الافتراضي.
|
| 89 |
font = ImageFont.truetype("arial.ttf", 36)
|
| 90 |
except:
|
| 91 |
font = ImageFont.load_default()
|
| 92 |
|
| 93 |
text = f"#{member.name}"
|
| 94 |
-
|
| 95 |
-
draw_final.text((368, 630), text, fill=(100, 0, 150), font=font, anchor="mm") # لون بنفسجي غامق/أسود
|
| 96 |
|
| 97 |
-
# تحويل الصورة إلى بايتات لإرسالها
|
| 98 |
final_buffer = io.BytesIO()
|
| 99 |
final_image.save(final_buffer, format="PNG")
|
| 100 |
final_buffer.seek(0)
|
| 101 |
return final_buffer
|
| 102 |
|
| 103 |
# ==========================================
|
| 104 |
-
#
|
| 105 |
# ==========================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
@bot.event
|
| 107 |
async def on_ready():
|
| 108 |
print(f"✅ تم تسجيل الدخول كـ {bot.user}")
|
| 109 |
-
# تفعيل حلقة الإحصائيات
|
| 110 |
daily_stats_task.start()
|
| 111 |
try:
|
| 112 |
synced = await bot.tree.sync()
|
| 113 |
-
print(f"🔄 تم مزامنة {len(synced)} أوامر سلاش
|
| 114 |
except Exception as e:
|
| 115 |
print(f"❌ خطأ في المزامنة: {e}")
|
| 116 |
|
| 117 |
@bot.event
|
| 118 |
async def on_member_join(member: discord.Member):
|
| 119 |
-
# التأكد من أن الحدث في السيرفر المطلوب فقط
|
| 120 |
if member.guild.id != SERVER_ID:
|
| 121 |
return
|
| 122 |
|
|
@@ -125,11 +125,9 @@ async def on_member_join(member: discord.Member):
|
|
| 125 |
|
| 126 |
if channel:
|
| 127 |
try:
|
| 128 |
-
# إنشاء الصورة
|
| 129 |
image_buffer = await generate_welcome_image(member)
|
| 130 |
file = discord.File(fp=image_buffer, filename="welcome.png")
|
| 131 |
|
| 132 |
-
# إنشاء الإيمباد (Embed)
|
| 133 |
embed = discord.Embed(
|
| 134 |
title="🎉 عضو جديد انضم إلينا!",
|
| 135 |
description=random.choice(WELCOME_MESSAGES),
|
|
@@ -140,11 +138,9 @@ async def on_member_join(member: discord.Member):
|
|
| 140 |
embed.add_field(name="📈 رقم العضو", value=f"أنت العضو رقم {member.guild.member_count}", inline=False)
|
| 141 |
embed.set_image(url="attachment://welcome.png")
|
| 142 |
|
| 143 |
-
# إرسال الرسالة وإضافة التفاعل
|
| 144 |
msg = await channel.send(content=member.mention, embed=embed, file=file)
|
| 145 |
await msg.add_reaction("👋")
|
| 146 |
|
| 147 |
-
# إرسال سجل للدخول
|
| 148 |
logs_channel = bot.get_channel(LOGS_CHANNEL_ID)
|
| 149 |
if logs_channel:
|
| 150 |
await logs_channel.send(f"✅ **دخول:** {member.mention} انضم للسيرفر.")
|
|
@@ -153,7 +149,7 @@ async def on_member_join(member: discord.Member):
|
|
| 153 |
daily_stats["errors"] += 1
|
| 154 |
logs_channel = bot.get_channel(LOGS_CHANNEL_ID)
|
| 155 |
if logs_channel:
|
| 156 |
-
await logs_channel.send(f"❌ **خطأ في الترحيب:** `{e}`")
|
| 157 |
|
| 158 |
@bot.event
|
| 159 |
async def on_member_remove(member: discord.Member):
|
|
@@ -165,7 +161,7 @@ async def on_member_remove(member: discord.Member):
|
|
| 165 |
await logs_channel.send(f"🚪 **خروج:** {member.name} غادر السيرفر.")
|
| 166 |
|
| 167 |
# ==========================================
|
| 168 |
-
#
|
| 169 |
# ==========================================
|
| 170 |
@tasks.loop(hours=24)
|
| 171 |
async def daily_stats_task():
|
|
@@ -183,7 +179,6 @@ async def daily_stats_task():
|
|
| 183 |
|
| 184 |
await logs_channel.send(embed=embed)
|
| 185 |
|
| 186 |
-
# تصفير الإحصائيات لليوم الجديد
|
| 187 |
daily_stats["joins"] = 0
|
| 188 |
daily_stats["leaves"] = 0
|
| 189 |
daily_stats["errors"] = 0
|
|
@@ -193,22 +188,20 @@ async def before_daily_stats():
|
|
| 193 |
await bot.wait_until_ready()
|
| 194 |
|
| 195 |
# ==========================================
|
| 196 |
-
#
|
| 197 |
# ==========================================
|
| 198 |
@bot.tree.command(name="تجربة_ترحيب", description="تجربة نظام الترحيب على عضو معين")
|
| 199 |
@app_commands.describe(member="العضو الذي تريد تجربة الترحيب عليه")
|
| 200 |
async def test_welcome(interaction: discord.Interaction, member: discord.Member):
|
| 201 |
-
# حماية: يعمل فقط في قناة التحكم وللرتبة المحددة
|
| 202 |
if interaction.channel_id != CONTROL_CHANNEL_ID:
|
| 203 |
return await interaction.response.send_message("❌ لا يمكنك استخدام هذا الأمر هنا.", ephemeral=True)
|
| 204 |
|
| 205 |
if not any(role.id == ADMIN_ROLE_ID for role in interaction.user.roles) and interaction.user.id != interaction.guild.owner_id:
|
| 206 |
return await interaction.response.send_message("❌ لا تملك صلاحية استخدام هذا الأمر.", ephemeral=True)
|
| 207 |
|
| 208 |
-
await interaction.response.defer(ephemeral=True)
|
| 209 |
|
| 210 |
try:
|
| 211 |
-
# محاكاة الترحيب
|
| 212 |
channel = bot.get_channel(WELCOME_CHANNEL_ID)
|
| 213 |
image_buffer = await generate_welcome_image(member)
|
| 214 |
file = discord.File(fp=image_buffer, filename="welcome.png")
|
|
@@ -228,12 +221,11 @@ async def test_welcome(interaction: discord.Interaction, member: discord.Member)
|
|
| 228 |
|
| 229 |
await interaction.followup.send("✅ تم إرسال رسالة التجربة بنجاح في قناة الترحيب.")
|
| 230 |
except Exception as e:
|
| 231 |
-
await interaction.followup.send(f"❌ حدث خطأ أثناء التجربة: {e}")
|
| 232 |
|
| 233 |
# ==========================================
|
| 234 |
-
#
|
| 235 |
# ==========================================
|
| 236 |
-
# يجب وضع توكن البوت في متغيرات البيئة في Hugging Face باسم BOT_TOKEN
|
| 237 |
TOKEN = os.environ.get("BOT_TOKEN")
|
| 238 |
if TOKEN:
|
| 239 |
bot.run(TOKEN)
|
|
|
|
| 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
|
|
|
|
| 19 |
LOGS_CHANNEL_ID = 1492544227505213490
|
| 20 |
CONTROL_CHANNEL_ID = 1492544049255678085
|
| 21 |
|
|
|
|
| 22 |
WELCOME_MESSAGES = [
|
| 23 |
"مرحباً بك في مجتمعنا! نتمنى لك وقتاً ممتعاً.",
|
| 24 |
"أهلاً بك في خادمنا، نورت المكان!",
|
|
|
|
| 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),
|
|
|
|
| 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 |
|
|
|
|
| 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),
|
|
|
|
| 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} انضم للسيرفر.")
|
|
|
|
| 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):
|
|
|
|
| 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():
|
|
|
|
| 179 |
|
| 180 |
await logs_channel.send(embed=embed)
|
| 181 |
|
|
|
|
| 182 |
daily_stats["joins"] = 0
|
| 183 |
daily_stats["leaves"] = 0
|
| 184 |
daily_stats["errors"] = 0
|
|
|
|
| 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")
|
|
|
|
| 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)
|