Добавить отключенных пользователей в базу данных? Когда они воссоединяются, они снова получают эту роль

#discord #discord.py

Вопрос:

 @commands.command()
    @commands.has_permissions(manage_roles=True)
    async def mute(self, ctx, member:discord.Member, *, time: TimeConverter = None):
        role = discord.utils.get(ctx.guild.roles, name="Muted by ez")
        if not role:
            role = await ctx.guild.create_role(name="Muted by ez")

            for channel in ctx.guild.channels:
                await channel.set_permissions(role, speak=False, send_messages=False, read_message_history=True,
                                              read_messages=False)
            await member.add_roles(role)
            await asyncio.sleep(time)
            await member.remove_roles(role)
            await ctx.send(f"Muted {member.mention} for {time}s")
        else:
            await member.add_roles(role)
            await ctx.send(f"Muted {member.mention} for {time}s")
            await asyncio.sleep(time)
            await member.remove_roles(role)
            await ctx.send(f'Unmuted {member.mention}')


    @commands.command()
    @commands.has_permissions(manage_roles=True)
    async def unmute(self, ctx, member: discord.Member):
        role = discord.utils.get(ctx.guild.roles, name="Muted by ez")
        await member.remove_roles(role)
        await ctx.send(f'Unmuted {member.mention}')
 

этот мой код до сих пор отлично работает, но я так долго занимаюсь этим и спрашиваю себя, как добавить пользователей в базу данных json, чтобы, когда они присоединятся, у них все еще была роль.

Обновите лучший код, который у меня теперь есть все, но не эти, с дополнительными данными: я хочу добавить идентификатор гильдии, продолжительность отключения звука и идентификатор автора

поэтому я попытался сохранить все это, но у меня было много ошибок, поэтому я надеюсь, что вы снова сможете помочь мне с этим моим кодом до сих пор

 import re

import asyncio
import discord
from discord.ext import commands
import cogs._json
time_regex = re.compile("(?:(d{1,5})(h|s|m|d)) ?")
time_dict = {"h": 3600, "s": 1, "m": 60, "d": 86400}



class TimeConverter(commands.Converter):
    async def convert(self, ctx, argument):
        args = argument.lower()
        matches = re.findall(time_regex, args)
        time = 0
        for key, value in matches:
            try:
                time  = time_dict[value] * float(key)
            except KeyError:
                raise commands.BadArgument(
                    f"{value} is an invalid time key! h|m|s|d are valid arguments"
                )
            except ValueError:
                raise commands.BadArgument(f"{key} is not a number!")
        return round(time)


class Moderation(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(
        name='mute',
        description="Mutes a given user for x time!",
        ussage='<user> [time]'
    )
    @commands.has_permissions(manage_roles=True)
    async def mute(self, ctx, member: discord.Member, *, time: TimeConverter= None):
        role = discord.utils.get(ctx.guild.roles, name="Muted by ez")
        if not role:
            role = await ctx.guild.create_role(name="Muted by ez", colour=0x171717)

            for channel in ctx.guild.channels:
                await channel.set_permissions(role, speak=False, send_messages=False, read_message_history=True,
                                              read_messages=False, add_reactions=False)
            pass

        try:

                data = cogs._json.read_json("muted_users")
                if member.id in data['muted_users']:
                    remsg = await ctx.send("reloading the mute")
                    await member.remove_roles(role)
                    data = cogs._json.read_json("muted_users")
                    data["muted_users"].remove(member.id)
                    cogs._json.write_json(data, "muted_users")
                    await asyncio.sleep(2)
                    await remsg.edit(content=f"Unmuted `{member}`")
                    data = cogs._json.read_json("muted_users")
                    data["muted_users"].append(member.id)
                    cogs._json.write_json(data, "muted_users")
                    await member.add_roles(role)
                    if not time:
                        await asyncio.sleep(2)
                        await remsg.edit(content=f"Muted `{member}`")
                    else:
                        await asyncio.sleep(2)
                        await remsg.edit(content=f"Muted `{member}` for `{time}s`")

                        await asyncio.sleep(time)
                        await member.remove_roles(role)
                        data = cogs._json.read_json("muted_users")
                        data["muted_users"].remove(member.id)
                        cogs._json.write_json(data, "muted_users")
                        await ctx.send(content=f"Unmuted `{member}`")


                    return
        except KeyError:
            pass
        data = cogs._json.read_json("muted_users")
        data["muted_users"].append(member.id)
        cogs._json.write_json(data, "muted_users")
        await member.add_roles(role)

        if not time:
            await ctx.send(f"Muted `{member}`")
        else:
            await ctx.send(f"Muted `{member}`for `{time}s`")
            await asyncio.sleep(time)
            print(time)
            if role in member.roles:
                await member.remove_roles(role)
                data = cogs._json.read_json("muted_users")
                data["muted_users"].remove(member.id)
                cogs._json.write_json(data, "muted_users")
                await ctx.send(f"Unmuted `{member}`")
            else:
                data = cogs._json.read_json("muted_users")
                data["muted_users"].remove(member.id)
                cogs._json.write_json(data, "muted_users")

    @commands.command(
        name='unmute',
        description="Unmuted a member!",
        usage='<user>'
    )
    @commands.has_permissions(manage_roles=True)
    async def unmute(self, ctx, member: discord.Member):
        role = discord.utils.get(ctx.guild.roles, name="Muted by ez")
        if not role:
            role = await ctx.guild.create_role(name="Muted by ez", color=0x171717)

            for channel in ctx.guild.channels:
                await channel.set_permissions(role, speak=False, send_messages=False, read_message_history=True,
                                              read_messages=False, add_reactions=False)
            return

        if role not in member.roles:
            await ctx.send("This member is not muted.")
            data = cogs._json.read_json("muted_users")
            data["muted_users"].remove(member.id)
            cogs._json.write_json(data, "muted_users")





        await member.remove_roles(role)
        data = cogs._json.read_json("muted_users")
        data["muted_users"].remove(member.id)
        cogs._json.write_json(data, "muted_users")
        await ctx.send(f"Unmuted `{member}`")
def setup(bot):
    bot.add_cog(Moderation(bot))
 

that is the cog

 import json
from pathlib import Path

def get_path():
    """
    A function to get the current path to bot.py

    Returns:
     - cwd (string) : Path to bot.py directory
    """
    cwd = Path(__file__).parents[1]
    cwd = str(cwd)
    return cwd

def read_json(filename):
    """
    A function to read a json file and return the data.

    Params:
     - filename (string) : The name of the file to open

    Returns:
     - data (dict) : A dict of the data in the file
    """
    cwd = get_path()
    with open(cwd '/bot_config/' filename '.json', 'r') as file:
        data = json.load(file)
    return data

def write_json(data, filename):
    """
    A function used to write data to a json file

    Params:
     - data (dict) : The data to write to the file
     - filename (string) : The name of the file to write to
    """
    cwd = get_path()
    with open(cwd '/bot_config/' filename '.json', 'w') as file:
        json.dump(data, file, indent=4)
 

мой «файл преобразования»

 {
    "muted_users": []
}
 

мой файл хранилища json

 @commands.Cog.listener()
    async def on_member_join(self, member):
        print(member)
        await member.send("hello")
        role = discord.utils.get(member.guild.roles, name="Muted by ez")
        data = cogs._json.read_json("muted_users")
        if member.id in data['muted_users']:
            await member.add_roles(role)
 

и мой модуль on_member_join.
Этот код полностью работает, но я хочу сделать его лучше, bcs, как в модуле объединения участников, может быть одним участником, поэтому один и тот же ребенок отключается на одном сервере, а не на другом, но отключается на обоих. вот почему мне нужен идентификатор гильдии.
и как я могу удалить все эти данные, когда я снова включу участника?
я этого не понял, так что не могли бы вы мне еще раз помочь?

Ответ №1:

Этапы рабочего процесса будут следующими

  1. Когда используется команда, соберите пользовательские данные
  2. сохраните его в файле json, предпочтительно используя уникальный идентификатор пользователя в качестве ключа.
  3. Когда присоединяется новый участник, проверьте идентификатор пользователя в разделе данные json
  4. Если идентификатор существует в данных json, назначьте им отключенную роль, в противном случае передайте.

Полезные ресурсы


Пример хранения данных

 import json
...

class Moderation(commands.Cog):
    ...

    @commands.command()
    async def mute(self, ctx, member:discord.Member):
        ...
        # add the muted role
        await member.add_roles(role)

        # open the json file and add the data
        with open('users.json', 'w') as fp:
            data = json.load(fp)
            if member.id not in data['muted']:
                data['muted'].append(member.id)
                json.dump(data, fp)
        ... 
 

создайте файл JSON users.json со следующими данными:

 {
    "muted": []
}
 

в этом простом примере отключенные пользователи хранятся как в списке. Сгенерированный файл JSON будет выглядеть следующим образом:

 {
    "muted": [123123123, 1231231231, 23423423423]
}
 

Пример проверки того, что пользователь находится в списке

 import json
...

@client.event
async def on_member_join(member):
    ...
    with open('users.json', 'r') as fp:
        data = json.load(fp)
        if member.id in data['muted']:
            await member.add_roles(role)

...
 

Изменить: Хранение Дополнительных Данных

Это редактирование предназначено для ответа на часть вопроса, полученного в комментариях

Чтобы собрать больше данных, вы можете использовать словари вместо одного списка. Возможность структуры данных JSON, которую вы ищете, может быть следующей

 {
    "guild_1_id": {
        "user_1_id": {
            "channel": "12345678",
            "moderator": "12345678"
        },
        "user_2_id": {
            "channel": "12345678",
            "moderator": "12345678"
        },
        ...
    },
    "guild_2_id": {
        "user_1_id": {
            "channel": "12345678",
            "moderator": "12345678"
        }
    }
    ...
}
 

Во-первых, соберите все необходимые данные, сохраните их в словаре под идентификатором участника

 newdata = {
    member.id: {
        "channel": ctx.channel.id,
        "moderator": ctx.author.id
    }
}
 

При обновлении данных JSON проверьте, существует ли в нем идентификатор гильдии, если да, то обновите данные сервера, чтобы включить данные нового участника, в противном случае создайте новый ключ с идентификатором гильдии и назначьте ему данные нового участника.

Измененная версия выглядит следующим образом

 # open the json file and add the data
with open('users.json', 'w') as fp:
    data = json.load(fp)
    if ctx.guild.id not in data.keys():
        data[ctx.guild.id] = newdata
    else:
        data[ctx.guild.id].update(newdata)
    json.dump(data, fp)
 

Объединив их, вы получите это

 import json
...

class Moderation(commands.Cog):
    ...

    @commands.command()
    async def mute(self, ctx, member:discord.Member):
        ...
        await member.add_roles(role)

        newdata = {
            member.id: {
                "channel": ctx.channel.id,
                "moderator": ctx.author.id
            }
        }

        # open the json file and add the data
        with open('users.json', 'w') as fp:
            data = json.load(fp)
            if ctx.guild.id not in data.keys():
                data[ctx.guild.id] = newdata
            else:
                data[ctx.guild.id].update(newdata)
            json.dump(data, fp)
        ... 
 

Теперь измените свои данные участника on_member_join , зарегистрировавшись в

 @client.event
async def on_member_join(member):
    ...
    with open('users.json', 'r') as fp:
        data = json.load(fp)
        if member.id in data[member.guild.id].keys():
            await member.add_roles(role)

            # further data can be accessed as following
            user_data = data[member.guild.id][member.id]
            
            channel = user_data['channel']
            moderator = user_data['moderator']
...
 

Также проверьте

Комментарии:

1. прежде всего, так много, я сохранил его сейчас, но как я должен это сделать, когда я хотел бы сохранить больше данных, таких как идентификатор канала, идентификатор гильдии или идентификатор автора, есть ли у меня больше возможностей для данных или как это работает?

2. @Socsz Я обновил свой ответ, чтобы включить более подробную информацию о том, как вы можете хранить больше данных, пожалуйста, проверьте еще раз 🙂

3. братан, большое тебе спасибо за твою помощь, но я не совсем правильно понял, я добавил еще несколько деталей к своему вопросу, так что я надеюсь, что ты сможешь помочь