Migration de Kuby vers disnake
This commit is contained in:
parent
dc6e235f27
commit
c8c579eefe
36 changed files with 1205 additions and 1253 deletions
|
|
@ -7,9 +7,8 @@ import asyncio
|
|||
from datetime import datetime
|
||||
from typing import Dict, Any, List
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord import app_commands
|
||||
import disnake
|
||||
from disnake.ext import commands
|
||||
|
||||
BACKUPS_ROOT = "data/security_backups" # dossier de sortie des sauvegardes
|
||||
|
||||
|
|
@ -46,10 +45,10 @@ def estimate_duration_seconds(
|
|||
return int(meta_cost + msg_cost + base_overhead)
|
||||
|
||||
|
||||
def serialize_overwrites(channel: discord.abc.GuildChannel) -> List[Dict[str, Any]]:
|
||||
def serialize_overwrites(channel: disnake.abc.GuildChannel) -> List[Dict[str, Any]]:
|
||||
serialized: List[Dict[str, Any]] = []
|
||||
for target, perms in channel.overwrites.items():
|
||||
target_type = "role" if isinstance(target, discord.Role) else "member"
|
||||
target_type = "role" if isinstance(target, disnake.Role) else "member"
|
||||
serialized.append({
|
||||
"target_type": target_type,
|
||||
"target_id": target.id,
|
||||
|
|
@ -64,20 +63,17 @@ class Backup(commands.Cog):
|
|||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
backup_group = app_commands.Group(name="backup", description="Outils de sauvegarde du serveur")
|
||||
@commands.slash_command(name="backup", description="Outils de sauvegarde du serveur")
|
||||
async def backup_group(self, interaction: disnake.ApplicationCommandInteraction):
|
||||
pass
|
||||
|
||||
@backup_group.command(name="create", description="Créer une sauvegarde du serveur")
|
||||
@app_commands.describe(
|
||||
save_messages="Inclure l'export des messages",
|
||||
privacy_notice="Afficher un avertissement public si messages sauvegardés",
|
||||
message_limit_per_channel="Nombre max de messages à exporter par salon (0 = tous)"
|
||||
)
|
||||
@backup_group.sub_command(name="create", description="Créer une sauvegarde du serveur")
|
||||
async def backup_create(
|
||||
self,
|
||||
interaction: discord.Interaction,
|
||||
save_messages: bool = True,
|
||||
privacy_notice: bool = True,
|
||||
message_limit_per_channel: int = 10000
|
||||
interaction: disnake.ApplicationCommandInteraction,
|
||||
save_messages: bool = commands.Param(True, description="Inclure l'export des messages"),
|
||||
privacy_notice: bool = commands.Param(True, description="Afficher un avertissement public si messages sauvegardés"),
|
||||
message_limit_per_channel: int = commands.Param(10000, description="Nombre max de messages à exporter par salon (0 = tous)")
|
||||
):
|
||||
guild = interaction.guild
|
||||
assert guild is not None, "Cette commande doit être utilisée dans un serveur."
|
||||
|
|
@ -93,20 +89,20 @@ class Backup(commands.Cog):
|
|||
)
|
||||
return
|
||||
|
||||
# Déferre l'interaction
|
||||
await interaction.response.defer(ephemeral=True, thinking=True)
|
||||
# Deferre l'interaction
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
# Avertissement de confidentialité
|
||||
if privacy_notice and save_messages:
|
||||
try:
|
||||
await interaction.channel.send(
|
||||
embed=discord.Embed(
|
||||
embed=disnake.Embed(
|
||||
title="📢 Information de confidentialité (transparence)",
|
||||
description=(
|
||||
"Une **sauvegarde du serveur** est en cours et **inclus les messages**.\n"
|
||||
"Vous êtes dans l'obligation de prévenir les membres."
|
||||
),
|
||||
color=discord.Color.orange()
|
||||
color=disnake.Color.orange()
|
||||
)
|
||||
)
|
||||
except Exception:
|
||||
|
|
@ -132,14 +128,14 @@ class Backup(commands.Cog):
|
|||
message_limit_per_channel if message_limit_per_channel else 100000
|
||||
)
|
||||
|
||||
prog_embed = discord.Embed(
|
||||
prog_embed = disnake.Embed(
|
||||
title="🗄️ Sauvegarde en cours",
|
||||
description=(
|
||||
f"**Serveur :** {guild.name} (`{guild.id}`)\n"
|
||||
f"**Estimation :** ~{estimation_s} secondes\n"
|
||||
f"**Options** : messages={'oui' if save_messages else 'non'} • limite/chan={message_limit_per_channel or 'tous'}"
|
||||
),
|
||||
color=discord.Color.blurple()
|
||||
color=disnake.Color.blurple()
|
||||
)
|
||||
prog_embed.add_field(name="Progression", value=progress_bar(0.0), inline=False)
|
||||
progress_msg = await interaction.followup.send(embed=prog_embed, ephemeral=False)
|
||||
|
|
@ -173,11 +169,11 @@ class Backup(commands.Cog):
|
|||
chans_dump=[]
|
||||
for ch in guild.channels:
|
||||
base={"id":ch.id,"name":ch.name,"type":str(ch.type),"position":ch.position,"category_id":ch.category.id if getattr(ch,"category",None) else None,"overwrites":serialize_overwrites(ch)}
|
||||
if isinstance(ch,discord.TextChannel):
|
||||
if isinstance(ch,disnake.TextChannel):
|
||||
base.update({"topic":ch.topic,"nsfw":ch.nsfw,"slowmode_delay":ch.slowmode_delay,"default_auto_archive_duration":ch.default_auto_archive_duration})
|
||||
elif isinstance(ch,discord.VoiceChannel):
|
||||
elif isinstance(ch,disnake.VoiceChannel):
|
||||
base.update({"bitrate":ch.bitrate,"user_limit":ch.user_limit,"rtc_region":str(ch.rtc_region) if ch.rtc_region else None})
|
||||
elif isinstance(ch,discord.ForumChannel):
|
||||
elif isinstance(ch,disnake.ForumChannel):
|
||||
base.update({"nsfw":ch.nsfw,"default_auto_archive_duration":ch.default_auto_archive_duration})
|
||||
chans_dump.append(base)
|
||||
with open(os.path.join(base_dir,"channels.json"),"w",encoding="utf-8") as f:
|
||||
|
|
@ -208,7 +204,7 @@ class Backup(commands.Cog):
|
|||
data={"id":msg.id,"channel_id":msg.channel.id,"author_id":msg.author.id,"author_bot":msg.author.bot,"created_at":msg.created_at.isoformat(),"content":msg.content,"attachments":[a.url for a in msg.attachments],"embeds":[e.to_dict() for e in msg.embeds],"reference":{"message_id":getattr(msg.reference,"message_id",None),"channel_id":getattr(msg.reference,"channel_id",None)} if msg.reference else None}
|
||||
f.write(json.dumps(data,ensure_ascii=False)+"\n")
|
||||
count+=1
|
||||
except discord.Forbidden: pass
|
||||
except disnake.Forbidden: pass
|
||||
except Exception: pass
|
||||
exported_total+=count
|
||||
done+=per_chan_weight
|
||||
|
|
@ -226,7 +222,7 @@ class Backup(commands.Cog):
|
|||
rel=os.path.relpath(full,base_dir)
|
||||
zf.write(full,rel)
|
||||
except Exception as exc:
|
||||
prog_embed.color=discord.Color.red()
|
||||
prog_embed.color=disnake.Color.red()
|
||||
prog_embed.set_field_at(0,name="Progression",value=progress_bar(1.0),inline=False)
|
||||
prog_embed.set_footer(text=f"Erreur lors de la création du ZIP : {exc}")
|
||||
await progress_msg.edit(embed=prog_embed)
|
||||
|
|
@ -234,15 +230,15 @@ class Backup(commands.Cog):
|
|||
return
|
||||
|
||||
# Finalisation
|
||||
prog_embed.color=discord.Color.green()
|
||||
prog_embed.color=disnake.Color.green()
|
||||
prog_embed.set_field_at(0,name="Progression",value=progress_bar(1.0),inline=False)
|
||||
prog_embed.add_field(name="Archive",value=f"`{zip_path}`",inline=False)
|
||||
prog_embed.set_footer(text="Sauvegarde terminée ✅")
|
||||
await progress_msg.edit(embed=prog_embed)
|
||||
await interaction.followup.send("🎉 Sauvegarde terminée. Un message de progression avec le chemin de l’archive a été publié.", ephemeral=True)
|
||||
|
||||
@backup_group.command(name="list", description="Lister les archives de sauvegarde disponibles")
|
||||
async def backup_list(self, interaction: discord.Interaction):
|
||||
@backup_group.sub_command(name="list", description="Lister les archives de sauvegarde disponibles")
|
||||
async def backup_list(self, interaction: disnake.ApplicationCommandInteraction):
|
||||
guild = interaction.guild
|
||||
assert guild is not None, "Cette commande doit être utilisée dans un serveur."
|
||||
|
||||
|
|
@ -256,7 +252,7 @@ class Backup(commands.Cog):
|
|||
)
|
||||
return
|
||||
|
||||
await interaction.response.defer(ephemeral=True, thinking=True)
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
ensure_dir(BACKUPS_ROOT)
|
||||
files = [f for f in os.listdir(BACKUPS_ROOT) if f.endswith(".zip")]
|
||||
files.sort(reverse=True)
|
||||
|
|
@ -266,7 +262,7 @@ class Backup(commands.Cog):
|
|||
return
|
||||
|
||||
desc="\n".join(f"• `{name}`" for name in files[:20])
|
||||
embed=discord.Embed(title="📦 Archives disponibles",description=desc,color=discord.Color.blurple())
|
||||
embed=disnake.Embed(title="📦 Archives disponibles",description=desc,color=disnake.Color.blurple())
|
||||
if len(files)>20:
|
||||
embed.set_footer(text=f"... et {len(files)-20} de plus")
|
||||
await interaction.followup.send(embed=embed,ephemeral=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue