| import discord |
| from discord.ext import commands |
| from discord import app_commands |
| from datetime import datetime, timezone |
| import time |
| from database import Database |
|
|
| |
| CYBER_BLUE = discord.Color.from_rgb(52, 152, 219) |
| CYBER_DARK = discord.Color.from_rgb(44, 62, 80) |
| CYBER_GREEN = discord.Color.from_rgb(46, 204, 113) |
|
|
| class Stats(commands.Cog): |
| def __init__(self, bot): |
| self.bot = bot |
| |
| self.voice_join_times = {} |
|
|
| def _get_today_str(self): |
| return datetime.now().date().isoformat() |
|
|
| def _format_duration(self, seconds: int) -> str: |
| if seconds <= 0: |
| return "0 saniye" |
| hours = seconds // 3600 |
| minutes = (seconds % 3600) // 60 |
| secs = seconds % 60 |
| parts = [] |
| if hours > 0: |
| parts.append(f"{hours} saat") |
| if minutes > 0: |
| parts.append(f"{minutes} dakika") |
| if secs > 0 or not parts: |
| parts.append(f"{secs} saniye") |
| return " ".join(parts) |
|
|
| def _generate_bar(self, value, max_val, size=10) -> str: |
| if max_val <= 0: |
| return "░" * size |
| filled = int((value / max_val) * size) |
| filled = min(filled, size) |
| return "█" * filled + "░" * (size - filled) |
|
|
| |
| @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, "Stats"): |
| return |
| today = self._get_today_str() |
| await Database.aktiflik_mesaj_arttir(message.guild.id, message.author.id, today) |
|
|
| |
| @commands.Cog.listener() |
| async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): |
| if member.bot or not member.guild: |
| return |
| if not await Database.modul_aktif_mi(member.guild.id, "Stats"): |
| return |
|
|
| user_id = member.id |
| guild_id = member.guild.id |
| today = self._get_today_str() |
| now = time.time() |
|
|
| |
| if before.channel is None and after.channel is not None: |
| self.voice_join_times[user_id] = now |
|
|
| |
| elif before.channel is not None and after.channel is None: |
| join_time = self.voice_join_times.pop(user_id, None) |
| if join_time: |
| duration = int(now - join_time) |
| if duration > 0: |
| await Database.aktiflik_ses_ekle(guild_id, user_id, today, duration) |
|
|
| |
| elif before.channel is not None and after.channel is not None and before.channel.id != after.channel.id: |
| join_time = self.voice_join_times.get(user_id, None) |
| if join_time: |
| duration = int(now - join_time) |
| if duration > 0: |
| await Database.aktiflik_ses_ekle(guild_id, user_id, today, duration) |
| |
| self.voice_join_times[user_id] = now |
|
|
| |
|
|
| @commands.hybrid_command(name="istatistik", description="Kendi aktiflik istatistiklerinizi veya başka bir üyeninkini görüntüler.") |
| @app_commands.describe(uye="İstatistiklerine bakılacak üye") |
| async def istatistik(self, ctx: commands.Context, uye: discord.Member = None): |
| if ctx.interaction: |
| await ctx.defer() |
| |
| target = uye or ctx.author |
| stats = await Database.aktiflik_getir(ctx.guild.id, target.id) |
| |
| |
| mesaj_detay = "" |
| toplam_7_gun_mesaj = 0 |
| max_7_gun_mesaj = 0 |
| for r in stats["son_7_gun_mesaj"]: |
| toplam_7_gun_mesaj += r["mesaj_sayisi"] |
| if r["mesaj_sayisi"] > max_7_gun_mesaj: |
| max_7_gun_mesaj = r["mesaj_sayisi"] |
| |
| |
| for r in reversed(stats["son_7_gun_mesaj"]): |
| bar = self._generate_bar(r["mesaj_sayisi"], max_7_gun_mesaj) |
| mesaj_detay += f"`{r['gun_tarih']}` {bar} `{r['mesaj_sayisi']} mesaj`\n" |
|
|
| |
| ses_detay = "" |
| toplam_7_gun_ses = 0 |
| max_7_gun_ses = 0 |
| for r in stats["son_7_gun_ses"]: |
| toplam_7_gun_ses += r["ses_suresi_sn"] |
| if r["ses_suresi_sn"] > max_7_gun_ses: |
| max_7_gun_ses = r["ses_suresi_sn"] |
|
|
| for r in reversed(stats["son_7_gun_ses"]): |
| bar = self._generate_bar(r["ses_suresi_sn"], max_7_gun_ses) |
| ses_detay += f"`{r['gun_tarih']}` {bar} `{self._format_duration(r['ses_suresi_sn'])}`\n" |
|
|
| embed = discord.Embed( |
| title=f"📊 Aktiflik İstatistikleri - {target.display_name}", |
| color=CYBER_BLUE, |
| timestamp=datetime.now() |
| ) |
| embed.set_thumbnail(url=target.display_avatar.url) |
| |
| |
| embed.add_field(name="✉️ Toplam Mesaj", value=f"`{stats['toplam_mesaj']}` adet", inline=True) |
| embed.add_field(name="🔊 Toplam Ses Süresi", value=f"`{self._format_duration(stats['toplam_ses'])}`", inline=True) |
| |
| |
| if mesaj_detay: |
| embed.add_field(name="📅 Son 7 Gün Mesaj İstatistiği", value=mesaj_detay, inline=False) |
| else: |
| embed.add_field(name="📅 Son 7 Gün Mesaj İstatistiği", value="*Son 7 günde kaydedilmiş mesaj yok.*", inline=False) |
| |
| if ses_detay: |
| embed.add_field(name="⏱️ Son 7 Gün Ses İstatistiği", value=ses_detay, inline=False) |
| else: |
| embed.add_field(name="⏱️ Son 7 Gün Ses İstatistiği", value="*Son 7 günde kaydedilmiş ses aktifliği yok.*", inline=False) |
|
|
| await ctx.send(embed=embed) |
|
|
| @commands.hybrid_command(name="top-aktiflik", description="Sunucudaki aktiflik sıralamasını (mesaj ve ses) gösterir.") |
| async def top_aktiflik(self, ctx: commands.Context): |
| if ctx.interaction: |
| await ctx.defer() |
| |
| top_mesaj = await Database.aktiflik_siralamasi_mesaj(ctx.guild.id, 10) |
| top_ses = await Database.aktiflik_siralamasi_ses(ctx.guild.id, 10) |
| |
| mesaj_list = [] |
| for i, row in enumerate(top_mesaj, 1): |
| member = ctx.guild.get_member(row['user_id']) |
| name = member.mention if member else f"ID: {row['user_id']}" |
| mesaj_list.append(f"**{i}.** {name} — `{row['toplam']} mesaj`") |
| |
| ses_list = [] |
| for i, row in enumerate(top_ses, 1): |
| member = ctx.guild.get_member(row['user_id']) |
| name = member.mention if member else f"ID: {row['user_id']}" |
| ses_list.append(f"**{i}.** {name} — `{self._format_duration(row['toplam'])}`") |
|
|
| embed = discord.Embed( |
| title=f"🏆 Sunucu Aktiflik Sıralaması", |
| color=CYBER_GREEN, |
| timestamp=datetime.now() |
| ) |
| |
| embed.add_field(name="✉️ En Çok Mesaj Atanlar", value="\n".join(mesaj_list) if mesaj_list else "*Veri yok.*", inline=False) |
| embed.add_field(name="🔊 En Çok Seste Kalanlar", value="\n".join(ses_list) if ses_list else "*Veri yok.*", inline=False) |
| |
| await ctx.send(embed=embed) |
|
|
| async def setup(bot): |
| await bot.add_cog(Stats(bot)) |
|
|