Я работаю над ботом для прокачки. Я обнаружил серьезную проблему с получением опыта, и ею можно чрезвычайно злоупотреблять. Я хочу, чтобы у него было время восстановления после того, как пользователь отправляет сообщение, поэтому, когда пользователь спамит в канале для фарма XP, у него есть время восстановления 0,5 секунды для каждого сообщения, чтобы предотвратить спам. Если вы рассылаете много спама, вы легко можете попасть на первое место, а я не хочу, чтобы это произошло. С ним работает все: получение опыта, таблица лидеров и сообщение о повышении уровня. Я искал в Интернете ответ на этот вопрос, и ни один из них не помог. Кто-нибудь знает? Пожалуйста и спасибо вам!!! :)

Код:

@bot.event
async def on_message(message):
    if not message.author.bot:
        # specify the encoding as utf-8 when opening the file
        with open('level.json','r', encoding='utf-8') as f:
            users = json.load(f)
        await update_data(users, message.author,message.guild)
        await add_experience(users, message.author, 4, message.guild)
        await level_up(users, message.author,message.channel, message.guild)

        # specify the encoding as utf-8 when writing the file
        with open('level.json','w', encoding='utf-8') as f:
            json.dump(users, f)
    await bot.process_commands(message)




async def update_data(users, user,server):
    if not str(server.id) in users:
        users[str(server.id)] = {}
        if not str(user.id) in users[str(server.id)]:
            users[str(server.id)][str(user.id)] = {}
            users[str(server.id)][str(user.id)]['experience'] = 0
            users[str(server.id)][str(user.id)]['level'] = 1
    elif not str(user.id) in users[str(server.id)]:
            users[str(server.id)][str(user.id)] = {}
            users[str(server.id)][str(user.id)]['experience'] = 0
            users[str(server.id)][str(user.id)]['level'] = 1

async def add_experience(users, user, exp, server):
  users[str(user.guild.id)][str(user.id)]['experience'] += exp

async def level_up(users, user, channel, server):
  experience = users[str(user.guild.id)][str(user.id)]['experience']
  lvl_start = users[str(user.guild.id)][str(user.id)]['level']
  lvl_end = int(experience ** (1/4))
  if str(user.guild.id) != '757383943116030074':
    if lvl_start < lvl_end:
      await channel.send(':fire: {} has leveled up to **Level {}!**'.format(user.mention, lvl_end))
      users[str(user.guild.id)][str(user.id)]['level'] = lvl_end
      embed=discord.Embed(title=':fire: {} has leveled up to **Level {}!**'.format(user.mention, lvl_end), color=0x38ff6a)
      await bot.get_channel(log_channel_id).send(embed=embed)

@bot.command(aliases = ['rank','lvl'])
async def level(ctx,member: discord.Member = None):
    if not member:
        user = ctx.message.author
        # specify the encoding as utf-8 when opening the file
        with open('level.json','r', encoding='utf-8') as f:
            users = json.load(f)
        lvl = users[str(ctx.guild.id)][str(user.id)]['level']
        exp = users[str(ctx.guild.id)][str(user.id)]['experience']

        embed = discord.Embed(title = 'Level {}'.format(lvl), description = f"{exp} XP " ,color = discord.Color.green())
        embed.set_author(name = ctx.author, icon_url = ctx.author.avatar.url)
        await ctx.send(embed = embed)
    else:
      # specify the encoding as utf-8 when opening the file
      with open('level.json','r', encoding='utf-8') as f:
          users = json.load(f)
      lvl = users[str(ctx.guild.id)][str(member.id)]['level']
      exp = users[str(ctx.guild.id)][str(member.id)]['experience']
      embed = discord.Embed(title = 'Level {}'.format(lvl), description = f"{exp} XP" ,color = discord.Color.green())
      embed.set_author(name = member, icon_url = member.avatar.url)

      await ctx.send(embed = embed)

Пример файла JSON:

{
  "757383943116030074": {
    "123456789012345678": {
      "experience": 0,
      "level": 1
    }
  }
}
1
As2Bax 30 Окт 2023 в 06:02

2 ответа

Лучший ответ

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

# Create a dictionary to keep track of last message times
message_cooldown = {}

@bot.event
async def on_message(message):
    if not message.author.bot:
        # Check if the user is in the cooldown dictionary
        if message.author.id in message_cooldown:
            current_time = time.time()
            last_message_time = message_cooldown[message.author.id]

            # Check if the user's cooldown has expired (0.5 seconds cooldown)
            if current_time - last_message_time < 0.5:
                return

        with open('level.json', 'r', encoding='utf-8') as f:
            users = json.load(f)
        await update_data(users, message.author, message.guild)
        await add_experience(users, message.author, 4, message.guild)
        await level_up(users, message.author, message.channel, message.guild)

        # Update the last message time for the user
        message_cooldown[message.author.id] = time.time()

        with open('level.json', 'w', encoding='utf-8') as f:
            json.dump(users, f)
    await bot.process_commands(message)

Здесь мы используем модуль времени для расчета времени, прошедшего между сообщениями для каждого пользователя, и устанавливаем время восстановления в 0,5 секунды. Словарь message_cooldown хранит время последнего сообщения для каждого пользователя. Если время восстановления не истекло, сообщение игнорируется.

2
xapi 30 Окт 2023 в 06:46

У меня нет опыта работы с ботами Discord, поэтому, возможно, есть лучший способ сделать это, но, посмотрев на ваш код и файл Ссылка на API, вот как я мог бы это сделать. Переданный объект сообщения содержит время created_at, которое можно использовать для отслеживания времени восстановления.

Псевдокод будет примерно таким:

async def on_message(message):
    # open json file
    if message.created_at > users[...][...]['cooldown_end']:
        # add xp
        users[...][...]['cooldown_end'] = message.created_at + 0.5 seconds

Таким образом, пользователь может получать XP не чаще одного раза в 0,5 секунды.

0
gommb 30 Окт 2023 в 06:28