File size: 10,354 Bytes
cbb05ec | 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 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | import discord
from discord.ext import commands
from discord import app_commands
from datetime import datetime
from database import Database
import random
CYBER_BLUE = discord.Color.from_rgb(52, 152, 219)
CYBER_GREEN = discord.Color.from_rgb(46, 204, 113)
CYBER_GOLD = discord.Color.from_rgb(241, 196, 15)
class Level(commands.Cog):
def __init__(self, bot):
self.bot = bot
# Cooldown: {user_id: last_msg_ts}
self._xp_cooldown = {}
self.COOLDOWN_SECONDS = 30
def _xp_for_level(self, level, difficulty=100):
return 5 * (level ** 2) + 50 * level + 100 - level * difficulty // 10
def _level_from_xp(self, xp, difficulty=100):
level = 0
while xp >= self._xp_for_level(level + 1, difficulty):
level += 1
xp -= self._xp_for_level(level, difficulty)
return level, xp
async def _add_xp(self, member: discord.Member, xp_add: int):
guild_id = member.guild.id
user_id = member.id
row = await Database.fetch_one(
"SELECT * FROM seviye WHERE guild_id = ? AND user_id = ?",
(guild_id, user_id)
)
if not row:
await Database.execute(
"INSERT INTO seviye (guild_id, user_id, xp, seviye) VALUES (?, ?, ?, ?)",
(guild_id, user_id, 0, 0)
)
row = await Database.fetch_one(
"SELECT * FROM seviye WHERE guild_id = ? AND user_id = ?",
(guild_id, user_id)
)
new_xp = row['xp'] + xp_add
settings = await Database.fetch_one("SELECT * FROM seviye_ayarlar WHERE guild_id = ?", (guild_id,))
difficulty = settings['zorluk'] if settings and settings.get('zorluk') else 100
old_level = row['seviye']
new_level = self._level_from_xp(new_xp, difficulty)[0]
await Database.execute(
"UPDATE seviye SET xp = ?, seviye = ? WHERE guild_id = ? AND user_id = ?",
(new_xp, new_level, guild_id, user_id)
)
if new_level > old_level:
# Level up bildirimi
kanal_id = settings['mesaj_kanal_id'] if settings and settings.get('mesaj_kanal_id') else 0
kanal = member.guild.get_channel(kanal_id) if kanal_id else None
embed = discord.Embed(
title="🎉 Seviye Atlandı!",
description=f"Tebrikler {member.mention}! **Seviye {new_level}**'e ulaştın! 🎊",
color=CYBER_GOLD,
timestamp=datetime.now()
)
if kanal:
try:
await kanal.send(embed=embed)
except:
pass
# Rol ödülü var mı kontrol et
odul = await Database.fetch_one(
"SELECT rol_id FROM seviye_oduller WHERE guild_id = ? AND seviye = ?",
(guild_id, new_level)
)
if odul:
rol = member.guild.get_role(odul['rol_id'])
if rol:
try:
await member.add_roles(rol, reason=f"Seviye {new_level} ödülü")
except:
pass
@commands.Cog.listener()
async def on_message(self, message: discord.Message):
if message.author.bot or not message.guild:
return
if not await Database.modul_aktif_mi(message.guild.id, "Level"):
return
settings = await Database.fetch_one("SELECT aktif FROM seviye_ayarlar WHERE guild_id = ?", (message.guild.id,))
if settings and settings.get('aktif') == 0:
return
# Cooldown kontrolü
import time
now = time.time()
last = self._xp_cooldown.get(message.author.id, 0)
if now - last < self.COOLDOWN_SECONDS:
return
self._xp_cooldown[message.author.id] = now
xp_gain = random.randint(15, 25)
await self._add_xp(message.author, xp_gain)
@commands.hybrid_command(name="seviye", description="Senin veya başka bir üyenin seviye kartını gösterir.")
@app_commands.describe(uye="Seviyesine bakılacak üye")
async def seviye(self, ctx: commands.Context, uye: discord.Member = None):
if ctx.interaction:
await ctx.defer()
target = uye or ctx.author
row = await Database.fetch_one(
"SELECT * FROM seviye WHERE guild_id = ? AND user_id = ?",
(ctx.guild.id, target.id)
)
if not row:
await ctx.send(f"ℹ️ {target.mention} henüz seviye verisine sahip değil.")
return
settings = await Database.fetch_one("SELECT * FROM seviye_ayarlar WHERE guild_id = ?", (ctx.guild.id,))
difficulty = settings['zorluk'] if settings and settings.get('zorluk') else 100
level = row['seviye']
xp = row['xp']
xp_for_current = self._xp_for_level(level, difficulty)
xp_for_next = self._xp_for_level(level + 1, difficulty)
xp_needed = xp_for_next - xp_for_current
xp_progress = xp - xp_for_current
progress_pct = int((xp_progress / max(xp_needed, 1)) * 100)
bar_size = 20
filled = int((xp_progress / max(xp_needed, 1)) * bar_size)
bar = "█" * filled + "░" * (bar_size - filled)
# Sıralama hesapla
all_users = await Database.fetch_all(
"SELECT user_id, xp FROM seviye WHERE guild_id = ? ORDER BY xp DESC",
(ctx.guild.id,)
)
rank = 1
for i, u in enumerate(all_users, 1):
if u['user_id'] == target.id:
rank = i
break
embed = discord.Embed(
title=f"🏆 Seviye Kartı - {target.display_name}",
color=CYBER_GOLD,
timestamp=datetime.now()
)
embed.set_thumbnail(url=target.display_avatar.url)
embed.add_field(name="Seviye", value=f"**{level}**", inline=True)
embed.add_field(name="Toplam XP", value=f"**{xp}**", inline=True)
embed.add_field(name="Sıralama", value=f"**#{rank}**", inline=True)
embed.add_field(
name=f"İlerleme ({progress_pct}%)",
value=f"`{bar}`\n{xp_progress}/{xp_needed} XP",
inline=False
)
await ctx.send(embed=embed)
@commands.hybrid_command(name="seviye-ayarla", description="Seviye sistemi ayarlarını yapar.")
@commands.has_permissions(administrator=True)
@app_commands.describe(
mesaj_kanali="Seviye atladığında bildirim gönderilecek kanal",
zorluk="Zorluk çarpanı (örn: 100 - ne kadar yüksek o kadar yavaş ilerleme)",
aktif="Seviye sistemi aktif mi? (1=Açık, 0=Kapalı)"
)
async def seviye_ayarla(self, ctx: commands.Context, mesaj_kanali: discord.TextChannel = None, zorluk: int = 100, aktif: int = 1):
if ctx.interaction:
await ctx.defer()
kanal_id = mesaj_kanali.id if mesaj_kanali else 0
await Database.execute(
"""INSERT OR REPLACE INTO seviye_ayarlar (guild_id, mesaj_kanal_id, aktif, zorluk)
VALUES (?, ?, ?, ?)""",
(ctx.guild.id, kanal_id, aktif, zorluk)
)
await ctx.send(f"✅ Seviye sistemi ayarlandı! Aktif: **{'Açık' if aktif else 'Kapalı'}**, Zorluk: **{zorluk}**")
@commands.hybrid_command(name="seviye-ödül-ekle", description="Belirli bir seviyeye ulaşınca verilecek rol ödülü ekler.")
@commands.has_permissions(administrator=True)
@app_commands.describe(seviye="Hedef seviye", rol="Verilecek rol")
async def seviye_odul_ekle(self, ctx: commands.Context, seviye: int, rol: discord.Role):
if ctx.interaction:
await ctx.defer()
await Database.execute(
"INSERT OR REPLACE INTO seviye_oduller (guild_id, seviye, rol_id) VALUES (?, ?, ?)",
(ctx.guild.id, seviye, rol.id)
)
await ctx.send(f"✅ Seviye **{seviye}**'e ulaşanlara **{rol.mention}** rolü verilecek.")
@commands.hybrid_command(name="seviye-ödül-sil", description="Bir seviye ödülünü siler.")
@commands.has_permissions(administrator=True)
@app_commands.describe(seviye="Ödül silinecek seviye")
async def seviye_odul_sil(self, ctx: commands.Context, seviye: int):
if ctx.interaction:
await ctx.defer()
await Database.execute(
"DELETE FROM seviye_oduller WHERE guild_id = ? AND seviye = ?",
(ctx.guild.id, seviye)
)
await ctx.send(f"✅ Seviye **{seviye}** ödülü silindi.")
@commands.hybrid_command(name="seviye-sıralama", description="Sunucudaki en yüksek seviyeli üyeleri gösterir.")
async def seviye_siralama(self, ctx: commands.Context):
if ctx.interaction:
await ctx.defer()
records = await Database.fetch_all(
"SELECT user_id, xp, seviye FROM seviye WHERE guild_id = ? ORDER BY xp DESC LIMIT 10",
(ctx.guild.id,)
)
if not records:
await ctx.send("ℹ️ Henüz seviye verisi bulunmamaktadır.")
return
embed = discord.Embed(title="🏆 Seviye Sıralaması", color=CYBER_GOLD, timestamp=datetime.now())
desc = ""
for i, r in enumerate(records, 1):
member = ctx.guild.get_member(r['user_id'])
name = member.mention if member else f"ID: {r['user_id']}"
emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉" if i == 3 else f"#{i}"
desc += f"{emoji} {name} — Seviye **{r['seviye']}** ({r['xp']} XP)\n"
embed.description = desc
await ctx.send(embed=embed)
@commands.hybrid_command(name="seviye-sıfırla", description="Bir üyenin seviyesini sıfırlar.")
@commands.has_permissions(administrator=True)
@app_commands.describe(uye="Seviyesi sıfırlanacak üye")
async def seviye_sifirla(self, ctx: commands.Context, uye: discord.Member):
if ctx.interaction:
await ctx.defer()
await Database.execute(
"UPDATE seviye SET xp = 0, seviye = 0 WHERE guild_id = ? AND user_id = ?",
(ctx.guild.id, uye.id)
)
await ctx.send(f"✅ {uye.mention} kullanıcısının seviyesi sıfırlandı.")
async def setup(bot):
await bot.add_cog(Level(bot))
|