I am building a bot that should store each member and the corresponding guild in a JSON. This works in the code without problems, but I just can not get one thing right.
Here is the code at first:
async def on_member_join(self, member):
with open("src/member.json", "r", encoding='utf-8') as f:
mlist = json.load(f)
guild = str(member.id)
#try:
#mlist[str(member.guild.id)] = guild
#except KeyError:
#print("KEY ERROR")
#mlist[str(member.guild.id)] = guild
if guild in mlist:
return print("IN LIST")
else:
mlist[str(member.guild.id)] = guild
print("NOT IN LIST")
with open('src/member.json', 'w', encoding='utf-8') as f:
json.dump(mlist, f, indent=2)
When I enter the server with my account the entry is created, but when I then re-enter the server my print("NOT IN LIST") still comes up.
This is how my JSON looks like:
{
"731855252277690XXX": "704712637988077XXX" # GuildID : UserID
}
Does anyone here see my error?
I have already tried the following:
Reverse search: if guild not in raidlist
try and except statements included
removed str and converted member.id or guild.id to something else
What you're doing right now is storing each guild and user as a single key-value pair. In other words each guild can only store one member. What we can do is to use lists:
async def on_member_join(self, member):
with open("src/member.json", "r", encoding='utf-8') as f:
mlist = json.load(f)
# changed to member id so it's less confusing
memberid = str(member.id)
guildid = str(member.guild.id)
if guildid in mlist:
if memberid in mlist[guildid]: # the member has already been recorded
return
mlist[guildid].append(memberid) # add the member to that guild's list
else:
mlist[guildid] = [memberid] # making a list with 1 element
with open('src/member.json', 'w', encoding='utf-8') as f:
json.dump(mlist, f, indent=2)
You should clear the JSON before running this code because it's incompatible with the format you had before.
This way the json will look like:
{
'GUILDID': ['MEMBERID1', 'MEMBERID2]
}
Related
What i'm trying to achive is to make three simple commands:
!add nick
!delete nick
!list (of nicknames)
This is my not-so-well-working script:
import json
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
def add(name):
list.append( name )
#bot.command()
async def dele(ctx, *args):
with open('list.json', 'r') as f:
lines = json.loads(f.read())
for name in args:
lines.remove(name)
with open('list.json', 'w') as f:
f.write(json.dumps(lines))
#bot.command()
async def add(ctx, *args):
with open('list.json', 'r') as f:
lines = json.loads(f.read())
for name in args:
lines.append(name)
with open('list.json', 'w') as f:
f.write(json.dumps(lines))
#bot.command()
async def list(ctx):
with open('list.json', 'r') as f:
list = json.loads(f.read())
await ctx.channel.send(f"List {list}")
bot.run("MY TOKEN HERE")
Command !list output:
list.json
["test1", "test2", "test3", "test", "4", "test4", "name", "name", "test", "5", "test", "6"]
So... adding and deleting nicknames works fine (except that when i'm trying to add nickname with spaces its adding two separate keys).
But the biggest problem i got with the list command. Don't know how to format this to some kind of list with \n nicknames showing one by one or even with discord embed thing.
Please help.
Spaces
(except that when i'm trying to add nickname with spaces its adding two separate keys)
Remember that when you write two words separated by space, the commands.command takes them as two arguments. You must write them without spaces.
One parameter function
You can solve your problem editing your functions like this:
#Bot.command()
async def add(ctx, member: str):
with open('list.json', 'r') as f:
lines = json.loads(f.read())
lines.append(member)
with open('list.json', 'w') as f:
f.write(json.dumps(lines))
Embed
You can do something like this:
description = ""
for i in list:
description += f'{i}\n'
Or
description = '\n'.join (list)
Then,
emb = discord.Embed(title="List", description=description, color=discord.Color.random())
await ctx.send(embed=emb)
My code:
reps = {}
with open("reps.json", "r") as f:
reps = json.load(f)
#client.command()
async def rep (ctx, member: discord.Member):
try:
count = reps[f'{ctx.guild.id}'][f'{member.id}']
reps[f'{ctx.guild.id}'][f'{member.id}'] = count + 1
with open('reps.json', 'w') as f:
json.dump(reps, f)
await ctx.message.add_reaction('<a:check12:810961073746345985>')
except:
reps[f'{ctx.guild.id}'] = {}
reps[f'{ctx.guild.id}'][f'{member.id}'] = 1
with open('reps.json', 'w') as f:
json.dump(reps, f)
await ctx.message.add_reaction('<a:check12:810961073746345985>')
The problem is that when I use this command my json file looks like:
{"GUILD_ID": {"MEMBER_ID": 1}}
It looks fine but when I try to use this command on a other member json file does not add another dictionary it just changes the name of a dict to a another member id so the file looks like this:
{"GUILD_ID": {"ANOTHER_MEMBER_ID": 1}}
And what I expect is:
{"GUILD_ID": {"MEMBER_ID": 1}}
And after using command on another member:
{"GUILD_ID": {"MEMBER_ID": 1, "ANOTHER_MEMBER_ID": 1}}
This is my code, and the current problem is that it only saves the latest change to my users.json file.
#commands.command()
async def command(self, ctx):
userid = ctx.message.author.id
with open('users.json', "r", encoding="utf8") as f:
userdata = json.load(f)
try:
with open('users.json', "w", encoding="utf8") as f:
userdata[str(userid)]["coins"] = userdata[str(userid)]["coins"] + 1
json.dump(userdata, f, sort_keys=True, indent=4, ensure_ascii=False)
except:
with open('users.json', "w", encoding="utf8") as f:
userdata = {}
userdata[str(userid)] = {}
userdata[str(userid)]["coins"] = 0
json.dump(userdata, f, sort_keys=True, indent=4, ensure_ascii=False)
Example: I use the command and this is what is stored in the file:
{
"idnumber": {
"coins": 0
}
}
But if someone else does it my variable coins is replaced by theirs leaving just:
{
"theiridnumber": {
"coins": 0
}
}
Any fix?
From your code it appears that you have used try-except just to see if a key is not present etc. This kind of usage is quite unnecessary (and needlessly complex too) considering you can do the same quite simply with various dictionary methods get, setdefault etc.
Try this:
#commands.command()
async def command(self, ctx):
userid = str(ctx.message.author.id)
with open('users.json', "r", encoding="utf8") as f:
userdata = json.load(f)
userdata.setdefault(userid, {}) # if key exists do nothing else set as dictionary, also returns value for key
# dict.get(key, alternate) either gets the value for key or returns the alternate given
userdata[userid]["coins"] = userdata[userid].get("coins", -1) + 1
with open('users.json', "w", encoding="utf8") as f:
json.dump(userdata, f, sort_keys=True, indent=4, ensure_ascii=False)
I'm currently in the process of making a kind of ticket system. I want to do that through a reaction.
When a user clicks on the reaction, a message is sent to a specific channel. This message ID is saved in a JSON file and should be assigned to the user who clicked on the reaction. But if I save the user and the message individually in the JSON file, I don't know which user the message belongs to. How can I assign the message ID to a user?
My Code:
#client.event
async def on_raw_reaction_add(reaction):
ticketmess = 716263100638035969
ticketlog = client.get_channel(716265124771397662)
user = client.get_user(reaction.user_id)
if reaction.message_id == ticketmess and reaction.emoji.id == 680827797165572117:
with open(r'./tickets.json', 'r')as f:
ticketchannels = json.load(f)
if not f"{reaction.user_id}" in ticketchannels:
ticketmess = await ticketlog.send('Ein User braucht Hilfe!')
with open(r'./tickets.json', 'r')as f:
ticketmessages = json.load(f)
ticketmessages[f"{reaction.user_id}"] = f'{user} in {ticketmess.id}'
with open(r'./tickets.json', 'w') as f:
json.dump(ticketmessages, f, indent=4)
The code would look something like:
#client.event
async def on_raw_reaction_add(reaction):
ticketmsg = 716263100638035969
ticketlog = client.get_channel(716265124771397662)
user = client.get_user(reaction.user_id)
if reaction.message_id == ticketmsg and reaction.emoji.id == 680827797165572117:
# you already have loaded it in once, you don't need to read it again
with open("tickets.json", "r") as fp:
data = json.load(fp)
if f"{reaction.user_id}" not in data.keys():
ticketmsg = await ticketlog.send("Ein User braucht Hilfe!")
# you can just assign the message id to the user, no need for a string
data[f"{reaction.user_id}"] = ticketmsg.id
with open("tickets.json", "w+") as fp:
json.dump(data, fp, sort_keys=True, indent=4) # kwargs are for beautification
You don't need the f"{user} in {ticketmsg.id}" because you can get the user from the key. Besides, usernames can change, so putting it in the file would prove to be not very useful.
If you wish to get the user's name, just load in the keys from the json and use client.get_user(ID_HERE).
If you want to search for a user based off of a specific message ID, you can iterate through a dictionary like so:
my_dict = {"key": "value", "foo": "bar"}
for k, v in my_dict.items():
if v == "bar":
print(k) # selecting the key based off of its value
# output:
# foo
I'm hoping I understood your question correctly, if not, I'll be happy to edit my answer after some clarification.
each time i use .register it will keep just making the account and not checking the id exist and if it does it will say the account is already made.
i've tryed if ctx.author.id not in jsonfile
and geting it from the file with other code too
just too much too add
#bot.command()
#commands.has_permissions(manage_guild=True)
async def register(ctx):
with open('Configs/amounts.json') as f:
usersidlel = json.loads(f.read())
if ctx.message.author.id not in usersidlel:
with open('Configs/amounts.json') as f:
data = json.loads(f.read())
data[str(ctx.author.id)] = {}
data[str(ctx.author.id)]['cash'] = 100
data[str(ctx.author.id)]['bank'] = 100
data = json.dumps(data, indent=4, sort_keys=True)
with open('Configs/amounts.json', 'w') as f:
f.write(data)
await ctx.send(f"```Account Registered!```")
else:
await ctx.send(f"Hey {ctx.author.name} you already got an account you silly person!")
No error messages just not sure how to check if the id exist or not.
You're testing a different variable than you're adding. Also, if ctx.author.id is an integer, you need to convert it to a string before testing.
There's also no need to load the JSON twice, just use the data returned by the first load.
async def register(ctx):
with open('Configs/amounts.json') as f:
usersidlel = json.load(f)
if str(ctx.author.id) not in usersidlel:
usersidlel[str(ctx.author.id)] = {'cash': 100, 'bank': 100}
with open('Configs/amounts.json', 'w') as f:
json.dump(usersidlel, f, indent=4, sort_keys=True)
await ctx.send(f"```Account Registered!```")
else:
await ctx.send(f"Hey {ctx.author.name} you already got an account you silly person!")