如何在 Discord 机器人中自动将用户添加到 JSON 文件以执行每日 streak 命令?

问题描述 投票:0回答:1

我正在使用 Python 和 Discord.py 库为我的 Discord 机器人创建每日 streak 命令。我使用的代码基于我在网上找到的示例,但我遇到了问题。

(代码取自 - Economy Bot Daily Streak

import datetime
from datetime import datetime, timedelta

@client.command()
async def daily(ctx):
  with open ("streak.json","r") as f:
    data = json.load(f)
  streak=data[f"{ctx.author.id}"]["streak"]
  last_claim_stamp=data[f"{ctx.author.id}"]["last_claim"]
  last_claim=datetime.fromtimestamp(float(last_claim_stamp))
  now  =datetime.now() 
  delta = now-last_claim 
  print(f"{streak}\n{last_claim_stamp}\n{last_claim}\n{now}\n{delta}") 
  if delta< timedelta(hours=24):
    await ctx.send('YOU ALREADY CLAIMED YOUR DAILY in 24 hours')
    return
  if delta > timedelta(hours=48):
    print('streak reset')
    streak = 1
  else:
    streak+=1   
  daily = 45+(streak*5) 
  data[f'{ctx.author.id}']["streak"]=streak
  data[f'{ctx.author.id}']["last_claim"]= str(now.timestamp())
  with open("streak.json","w") as f:
    json.dump(data,f,indent=2)
  embed = discord.Embed(title="Daily", colour=random.randint(0, 0xffffff), description=f"You've claimed your daily of **{daily}** \n Not credited")
  embed.set_footer(text=f"Your daily streak : {streak}")

  await ctx.send(embed=embed)

我的问题是:当用户第一次使用 daily streak 命令时,如何自动将用户添加到 JSON 文件中?我尝试创建一个函数来处理这个问题,但遇到了一个错误,它在执行命令之前添加了时间戳,导致机器人即使在第一次尝试时也会说“您已经声明了您的日常”。

  • 请解释如何正确地将用户添加到 JSON 文件中,以便机器人可以跟踪他们的个人连续记录。
  • 如果可以的话,能否提供一个代码示例来演示如何实现自动添加用户?
python discord.py
1个回答
0
投票
import json
import datetime
from datetime import datetime, timedelta

def initialize_json(filename):
    """
    Initializes the JSON file, creating it and adding default values for new users if it doesn't exist.

    Args:
        filename (str): The name of the JSON file.

    Returns:
        dict: The data dictionary loaded from the JSON file, or an empty dictionary if the file is new.
    """

    try:
        with open(filename, 'r') as f:
            data = json.load(f)
    except FileNotFoundError:  # File doesn't exist
        with open(filename, 'w') as f:
            data = {}  # Create an empty dictionary (JSON object)
    return data

def add_user_to_json(filename, user_id, streak=0, last_claim=None):
    """
    Adds a new user to the JSON file if they don't already exist, with the specified default values.

    Args:
        filename (str): The name of the JSON file.
        user_id (int/str): The user's unique identifier.
        streak (int, optional): The user's initial streak (default: 0).
        last_claim (datetime.datetime, optional): The user's last claim timestamp (default: None).
    """

    data = initialize_json(filename)
    if user_id not in data:
        data[user_id] = {'streak': streak, 'last_claim': last_claim}  # Add new user info
    with open(filename, 'w') as f:
        json.dump(data, f, indent=2)

@client.command()
async def daily(ctx):
    """
    The daily command for the Discord bot, handling user streaks.

    Args:
        ctx (discord.ext.commands.Context): The context object containing command information.
    """

    user_id = str(ctx.author.id)
    with open("streak.json", "r") as f:
        data = json.load(f)

    # Check if user exists in data, add them if not
    if user_id not in data:
        add_user_to_json("streak.json", user_id)
        data = initialize_json("streak.json")  # Re-read data after adding

    streak = data[user_id]["streak"]
    last_claim_stamp = data[user_id]["last_claim"]

    if last_claim_stamp is not None:
        last_claim = datetime.fromtimestamp(float(last_claim_stamp))
    else:
        # Handle initial claim when there's no last_claim timestamp
        last_claim = datetime.now() - timedelta(days=1)  # Adjust for daily reset

    now = datetime.now()
    delta = now - last_claim

    # Check if 24 hours have passed since the last claim
    if delta < timedelta(hours=24):
        await ctx.send('YOU ALREADY CLAIMED YOUR DAILY in 24 hours')
        return

    # Reset streak if more than 48 hours have passed since the last claim
    if delta > timedelta(hours=48):
        data[user_id]["streak"] = 1
        streak = 1
    else:
        data[user_id]["streak"] += 1
        streak += 1

    # Calculate daily reward based on streak
    daily = 45 + (streak * 5)

    # Update user data in the JSON file
    data[user_id]["last_claim"] = str(now.timestamp())
    with open("streak.json", "w") as f:
        json.dump(data, f, indent=2)

    # Create and send the embed message
    embed = discord.Embed(title="Daily", colour=random.randint(0, 0xffffff),
                          description=f"You've claimed your daily of **{daily}** \n Not credited")
    embed.set_footer(text=f"Your daily streak : {streak}")
    await ctx.send(embed=embed)

说明

数据存储:

  • 该代码使用名为
    streak.json
    JSON 格式的文件来存储用户信息。
  • 此文件充当数据库,以结构化且易于访问的方式保存数据。
  • 有两个函数管理这些数据:
    • initialize_json
      :检查文件是否存在。如果没有,它会创建一个新的。
    • add_user_to_json
      :将新用户添加到文件中,并使用其连续记录和最后声明时间戳的默认值(可选)。

日常命令(

daily
):

  • 此命令处理用户领取每日奖励。
  • 它检索用户的 ID 并从
    streak.json
    文件中检索用户数据。
  • 如果用户是新用户(在数据中未找到),则会使用
    add_user_to_json
    添加默认值。
  • 代码从数据中检索用户的当前连续记录和上次索赔时间戳。
  • 它计算当前时间与上次索赔之间的时间差。

每日奖励资格:

  • 代码检查自上次索赔以来是否已过去 24 小时。
    • 如果不到 24 小时,则会通知用户尚不能领取。
  • 然后,它会检查自上次索赔以来是否已过去 48 小时以上。
    • 如果是这样,它会将用户的连胜重置为 1,表示连胜中断。

奖励计算及数据更新:

  • 如果符合条件,每日奖励将根据用户当前的连胜数计算。
  • 用户的最后索赔时间戳将更新为数据中的当前时间。
  • 更新后的数据将保存回
    streak.json
    文件。

回复消息并嵌入:

  • 创建了一个
    embed
    对象来使用
    discord.Embed
    显示每日奖励信息。
  • 其中包括已领取的奖励和用户当前的连胜记录等详细信息。
  • 机器人将嵌入消息发送给 Discord 频道中的用户。
© www.soinside.com 2019 - 2024. All rights reserved.