Discord money bot 将用户 ID 保存在 json 文件中。当 Not 重新启动时,它会为每个人创建一个新的(但相同的)ID

Posted

技术标签:

【中文标题】Discord money bot 将用户 ID 保存在 json 文件中。当 Not 重新启动时,它会为每个人创建一个新的(但相同的)ID【英文标题】:Discord money bot keeping user ID's in json file. When Bot restarts it creats a new (but same) ID for everyone 【发布时间】:2019-08-24 10:35:47 【问题描述】:

当这段代码运行时,它可以从 discord 中获取用户 ID,并将他们有 100 钱放入 json,但是一旦你重新启动机器人,你必须再次注册,它会在 json 文件中写入相同的用户 ID,认为这是一个如果不是新用户。

from discord.ext import commands
import discord
import json

bot = commands.Bot('!')

amounts = 

@bot.event
async def on_ready():
    global amounts
    try:
        with open('amounts.json') as f:
            amounts = json.load(f)
    except FileNotFoundError:
        print("Could not load amounts.json")
        amounts = 

@bot.command(pass_context=True)
async def balance(ctx):
    id = ctx.message.author.id
    if id in amounts:
        await ctx.send("You have  in the bank".format(amounts[id]))
    else:
        await ctx.send("You do not have an account")

@bot.command(pass_context=True)
async def register(ctx):
    id = ctx.message.author.id
    if id not in amounts:
        amounts[id] = 100
        await ctx.send("You are now registered")
        _save()
    else:
        await ctx.send("You already have an account")

@bot.command(pass_context=True)
async def transfer(ctx, amount: int, other: discord.Member):
    primary_id = ctx.message.author.id
    other_id = other.id
    if primary_id not in amounts:
        await ctx.send("You do not have an account")
    elif other_id not in amounts:
        await ctx.send("The other party does not have an account")
    elif amounts[primary_id] < amount:
        await ctx.send("You cannot afford this transaction")
    else:
        amounts[primary_id] -= amount
        amounts[other_id] += amount
        await ctx.send("Transaction complete")
    _save()

def _save():
    with open('amounts.json', 'w+') as f:
        json.dump(amounts, f)

@bot.command()
async def save():
    _save()

bot.run("Token")

机器人关闭并重新打开并注册两次后的 JSON(假用户 ID):

"56789045678956789": 100, "56789045678956789": 100

即使在机器人关闭并重新打开后也需要它能够识别用户 ID。

【问题讨论】:

字典中不能有重复的键,并且字典的键应该显示为整数,因为您使用的是重写分支。您能否仔细检查并确认您看到这些重复的字符串键? 是的,它们是 100% 相同的键。 PyCharm 警告我这两个键是重复的。为了澄清这一点,当机器人打开时,用户执行“!注册”,然后机器人停止并重新启动,用户再次执行“!注册”。用户必须重新注册一次,因为它认为它还没有注册用户还导致重复键。 【参考方案1】:

您只需要加载您在程序启动时创建的 .json 文件。而不是amounts = 试试这个:

import os

if os.path.exists('amounts.json'):
    with open('amounts.json', 'r') as file:
        amounts = json.load(file)
else:
    amounts =  # default to not loading if file not found

更新

我相信在阅读您的评论并查看您的代码后,问题出在您的register() 代码中。

你有:

if id not in amounts:

但应该是:

if id not in amounts.keys():

【讨论】:

@PatrickHaugh 你说得对,基本上是一样的。我不知道每次加载机器人时还有什么会导致它重置。我认为值得一试,也许 on_ready 事件没有被调用或其他什么,这将有助于诊断它是否修复了它。 在尝试此操作后,它会执行与在 JSON 文件中创建重复键之前相同的操作 关于您的编辑,字典上的成员资格测试只查看它们的键。 @PatrickHaugh 你能详细说明你的意思吗?我一直使用.keys() 来生成用于比较的键列表。你是说没有必要并且是隐式完成的吗? if item in dictionary 测试item 是否是字典中的键,当您遍历字典时,您会遍历它们的键。【参考方案2】:

发生这种情况是因为 JSON 对象总是有“键”的字符串。所以json.dump 将整数键转换为字符串。您可以通过在使用用户 ID 之前将其转换为字符串来执行相同的操作。

from discord.ext import commands
import discord
import json

bot = commands.Bot('!')

amounts = 

@bot.event
async def on_ready():
    global amounts
    try:
        with open('amounts.json') as f:
            amounts = json.load(f)
    except FileNotFoundError:
        print("Could not load amounts.json")
        amounts = 

@bot.command(pass_context=True)
async def balance(ctx):
    id = str(ctx.message.author.id)
    if id in amounts:
        await ctx.send("You have  in the bank".format(amounts[id]))
    else:
        await ctx.send("You do not have an account")

@bot.command(pass_context=True)
async def register(ctx):
    id = str(ctx.message.author.id)
    if id not in amounts:
        amounts[id] = 100
        await ctx.send("You are now registered")
        _save()
    else:
        await ctx.send("You already have an account")

@bot.command(pass_context=True)
async def transfer(ctx, amount: int, other: discord.Member):
    primary_id = str(ctx.message.author.id)
    other_id = str(other.id)
    if primary_id not in amounts:
        await ctx.send("You do not have an account")
    elif other_id not in amounts:
        await ctx.send("The other party does not have an account")
    elif amounts[primary_id] < amount:
        await ctx.send("You cannot afford this transaction")
    else:
        amounts[primary_id] -= amount
        amounts[other_id] += amount
        await ctx.send("Transaction complete")
    _save()

def _save():
    with open('amounts.json', 'w+') as f:
        json.dump(amounts, f)

@bot.command()
async def save():
    _save()

bot.run("Token")

【讨论】:

【参考方案3】:

我发现了问题并自己测试了它,所以它不是 .keys() 或 os 的东西,而是在 _save() 函数中。我首先使用 _save 函数进行了测试,没有使用它,而不是使用调用的函数,而是在我手动执行时工作。像这样

(P.S 我是在一个 cog 中完成的,唯一的区别是名称 @commands.command,即 @bot.command,您需要添加“self”)

@commands.command(pass_context=True)
async def register(self, ctx):
    id = str(ctx.message.author.id)
    with open("smth.json") as json_file:
        amounts = json.load(json_file)
    if id not in amounts:
        amounts[id] = 0
        await ctx.send("You are now registered")
    else:
        await ctx.send("You already have an account!")
    with open("smth.json", "w") as outfile:
        json.dump(amounts, outfile)

还有非常重要的注意事项,请确保在创建 json 文件时,它的名称以“.json”结尾,并且其中的所有内容都是




【讨论】:

以上是关于Discord money bot 将用户 ID 保存在 json 文件中。当 Not 重新启动时,它会为每个人创建一个新的(但相同的)ID的主要内容,如果未能解决你的问题,请参考以下文章

Discord.js Bot 上的 DM 特定用户 ID

Discord BOT python,如何在特定用户编写命令时发送消息

discord.py bot 看不到成员

从用户名 Discord.py 获取用户 ID

如何使用 discord.js 从 discord bot 向特定用户发送消息

Discord Bot 选择角色不会将角色授予用户