Spaces:
No application file
No application file
File size: 10,730 Bytes
ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b ad835d2 c1cc14b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | import discord
from discord import app_commands
from discord.ext import commands
import datetime
import random
import string
import io
import asyncio
import re
# --- الإعدادات الثابتة ---
OWNER_ID = 1429183440485486679
ERROR_LOG_CHANNEL_ID = 1488536752691085552
TICKETS_CHANNEL_ID = 1488536530019549344
LOG_CHANNEL_ID = 1488536921813680218
STAFF_ROLES_IDS = [
1488187501142216826, 1488187641424773140, 1488187816201687181,
1488188612313874733, 1488537308700344490, 1488537566910218260
]
PING_ROLES = "<@&1488187816201687181> <@&1488188612313874733> <@&1488537308700344490> <@&1488537566910218260>"
# --- نظام الحماية والقيود ---
active_tickets = {} # user_id: thread_id
cooldowns = {} # user_id: datetime
class MyBot(commands.Bot):
def __init__(self):
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
super().__init__(command_prefix="!", intents=intents)
async def setup_hook(self):
self.add_view(TicketPanelView())
self.add_view(TicketControls())
await self.tree.sync()
async def on_error(self, event, *args, **kwargs):
channel = self.get_channel(ERROR_LOG_CHANNEL_ID)
if channel:
await channel.send(f"⚠️ **Crash Detected / خطأ في النظام**\n`{event}`\n<@{OWNER_ID}>")
bot = MyBot()
# --- أدوات مساعدة ---
def is_staff(interaction: discord.Interaction):
return any(role.id in STAFF_ROLES_IDS for role in interaction.user.roles) or interaction.user.id == OWNER_ID
# --- نظام واجهة التذاكر ---
class TicketPanelView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
@discord.ui.select(
custom_id="ticket_select",
placeholder="Choose ticket type / اختر نوع التذكرة",
options=[
discord.SelectOption(label="Complaint against staff / شكوى ضد إداري", value="staff_complaint", emoji="⚖️"),
discord.SelectOption(label="Complaint against user / شكوى ضد لاعب", value="user_complaint", emoji="👥"),
discord.SelectOption(label="Bug report / بلاغ عن ثغرة", value="bug_report", emoji="🐛"),
discord.SelectOption(label="Technical support / دعم فني", value="tech_support", emoji="🛠️"),
]
)
async def select_callback(self, interaction: discord.Interaction, select: discord.ui.Select):
user_id = interaction.user.id
# تحقق من التذكرة المفتوحة
if user_id in active_tickets:
return await interaction.response.send_message("❌ You already have an open ticket! / لديك تذكرة مفتوحة بالفعل!", ephemeral=True)
# تحقق من الـ Cooldown
if user_id in cooldowns:
diff = (datetime.datetime.now() - cooldowns[user_id]).total_seconds()
if diff < 60:
return await interaction.response.send_message(f"⏳ Wait {int(60-diff)}s / انتظر {int(60-diff)} ثانية", ephemeral=True)
await interaction.response.defer(ephemeral=True)
# إنشاء Thread
channel = bot.get_channel(TICKETS_CHANNEL_ID)
ticket_id = ''.join(random.choices(string.ascii_lowercase + string.digits, k=4))
thread_name = f"ticket-{random.randint(1000,9999)}-{ticket_id}"
thread = await channel.create_thread(
name=thread_name,
type=discord.ChannelType.private_thread,
invitable=False
)
active_tickets[user_id] = thread.id
await thread.add_user(interaction.user)
await thread.edit(slowmode_delay=10)
# رسالة الترحيب
embed = discord.Embed(
title="Ticket Created / تم إنشاء التذكرة",
description=f"Welcome {interaction.user.mention}\n{PING_ROLES}\nYour ticket has been created, please wait...\n\nمرحباً بك، تم إنشاء تذكرتك، يرجى الانتظار...",
color=discord.Color.blue()
)
await thread.send(embed=embed, view=TicketControls())
# إرسال DM
try:
await interaction.user.send(f"✅ Your ticket has been created: {thread.jump_url}\nتم إنشاء تذكرتك بنجاح.")
except: pass
await interaction.followup.send(f"✅ Ticket Created: {thread.mention}", ephemeral=True)
class TicketControls(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
@discord.ui.button(label="Claim / استلام", style=discord.ButtonStyle.green, custom_id="claim_btn")
async def claim(self, interaction: discord.Interaction, button: discord.ui.Button):
if not is_staff(interaction):
return await interaction.response.send_message("❌ Staff only / للموظفين فقط", ephemeral=True)
button.disabled = True
await interaction.response.edit_message(view=self)
await interaction.followup.send(f"📌 Ticket claimed by / تم استلام التذكرة من قبل: {interaction.user.mention}")
# إرسال DM للمستخدم
thread_owner_id = next((k for k, v in active_tickets.items() if v == interaction.channel_id), None)
if thread_owner_id:
user = await bot.fetch_user(thread_owner_id)
try: await user.send(f"👋 Your ticket has been claimed by **{interaction.user.name}**\nتم استلام تذكرتك بواسطة الموظف.")
except: pass
@discord.ui.button(label="Close / إغلاق", style=discord.ButtonStyle.red, custom_id="close_btn")
async def close(self, interaction: discord.Interaction, button: discord.ui.Button):
if not is_staff(interaction):
return await interaction.response.send_message("❌ Staff only / للموظفين فقط", ephemeral=True)
await interaction.response.send_modal(CloseModal())
class CloseModal(discord.ui.Modal, title="Close Ticket / إغلاق التذكرة"):
reason = discord.ui.TextInput(label="Reason / السبب", placeholder="Enter closing reason...", min_length=5, required=True)
async def on_submit(self, interaction: discord.Interaction):
thread = interaction.channel
messages = [msg async for msg in thread.history(limit=None, oldest_first=True)]
# إنشاء ملف سجل
transcript = ""
for m in messages:
transcript += f"[{m.created_at.strftime('%Y-%m-%d %H:%M')}] {m.author}: {m.content}\n"
file = discord.File(io.BytesIO(transcript.encode()), filename=f"{thread.name}.txt")
# إرسال اللوق
log_channel = bot.get_channel(LOG_CHANNEL_ID)
user_id = next((k for k, v in active_tickets.items() if v == thread.id), "Unknown")
embed = discord.Embed(title="Ticket Closed / إغلاق تذكرة", color=discord.Color.red())
embed.add_field(name="User / المستخدم", value=f"<@{user_id}>")
embed.add_field(name="Staff / الموظف", value=interaction.user.mention)
embed.add_field(name="Reason / السبب", value=self.reason.value)
embed.add_field(name="Open Time / وقت الفتح", value=thread.created_at.strftime('%Y-%m-%d %H:%M'))
await log_channel.send(embed=embed, file=file)
# تنظيف البيانات
if user_id != "Unknown":
active_tickets.pop(int(user_id), None)
cooldowns[int(user_id)] = datetime.datetime.now()
await interaction.response.send_message("Closing... / جارِ الإغلاق...")
await thread.delete()
# --- الأوامر ---
@bot.tree.command(name="setup-ticket-panel", description="Setup the ticket panel (Owner Only)")
async def setup_ticket(interaction: discord.Interaction):
if interaction.user.id != OWNER_ID:
return await interaction.response.send_message("❌ Access Denied", ephemeral=True)
embed = discord.Embed(
title="Support System / نظام الدعم الفني",
description=(
"**Rules / القوانين:**\n"
"❌ No spamming tickets / يمنع فتح تذاكر عشوائية\n"
"✅ Use for complaints or support / استخدم التذاكر للشكاوى والدعم فقط\n\n"
"**Options / الخيارات:**\n"
"• Staff Complaint / شكوى إداري\n"
"• User Complaint / شكوى لاعب\n"
"• Bug Report / بلاغ ثغرة\n"
"• Technical Support / دعم فني"
),
color=discord.Color.green()
)
await interaction.response.send_message("Panel Sent!", ephemeral=True)
await interaction.channel.send(embed=embed, view=TicketPanelView())
@bot.tree.command(name="help", description="Show help information")
async def help_cmd(interaction: discord.Interaction):
await interaction.response.send_message(f"To open a ticket, go to <#{TICKETS_CHANNEL_ID}>\nلفتح تذكرة، توجه إلى القناة المخصصة.", ephemeral=True)
# --- نظام الحماية (Anti-Spam & Content Filter) ---
@bot.event
async def on_message(message):
if message.author.bot: return
if not isinstance(message.channel, discord.Thread): return
if message.channel.parent_id != TICKETS_CHANNEL_ID: return
# منع الروابط، الملفات، والبصمات الصوتية
if re.search(r'http[s]?://', message.content) or message.attachments or message.flags.voice:
# السماح فقط بالصور والفيديو
allowed = True
if message.attachments:
for att in message.attachments:
if not att.content_type or (not att.content_type.startswith('image/') and not att.content_type.startswith('video/')):
allowed = False
if not allowed or re.search(r'http[s]?://', message.content) or message.flags.voice:
await message.delete()
return await message.channel.send(f"{message.author.mention} ❌ Only text, images, and videos are allowed.\nمسموح فقط بالنصوص، الصور، والفيديو.", delete_after=5)
# منع السبام (أحرف عشوائية طويلة)
if len(message.content) > 50 and len(set(message.content)) < 10:
await message.delete()
return await message.channel.send("❌ Random characters/spam detected.", delete_after=5)
import os
from dotenv import load_dotenv
load_dotenv()
bot.run(os.getenv('TOKEN'))
|