I've looked at several questions and I could not get it working! The thing I'm trying to edit JSON file when my bot (discord bot) is being joined to new guild or is leaving guild!
My default JSON file look like this:
{
"guilds": {
}
}
What I'm trying to do is add another array where will be listed guild-id and another config for specific servers. I tried this and it did not worked!
#client.event
async def on_guild_join(guild):
with open('data.json') as f:
data = json.load(f);
data["guilds"][guild.id] = {
"join-message": "Welcome {member} to {server-name}! We hope you enjoy!"
}
with open('data.json','w') as f:
json.dump(f,data);
So I want the JSON file looks like this when new guilds are being added:
{
"guilds": {
{
"guild-id": 418718584455,
"join-message": "Welcome to blablabla"
},
}
}
and I want this happen always when bot is being joined when bot is leaving I will loop trough list of guilds and find the right and then delete it!
This seem to be not working, I get no error from it and file isnt being edited!
If anyone know how could achieve that please reply!
#client.event
async def on_guild_join(guild):
with open('data.json') as f:
data = json.load(f)
data["guilds"].append(({"guild-id": guild.id,
"join-message": "Welcome {member} to {server-name}! We hope
you enjoy!"
}))
with open('data.json','w') as f:
json.dump(data ,f);
Should it be this in the final line?
import json
with open('data.json','w') as f:
json.dump(data, f) # <<--- this one is inverted
Related
I have this cog blocker that puts a guild id and the command blocked in a .json file. When the command is used, it will check to see if this information is in the .json file, if it is, it will not run the command. Although, I do not know how to make it so it takes out the command or guild id so the command can be used again. Please help!
#commands.command()
#has_permissions(administrator=True)
async def block(self, ctx, cmd: str):
with open(os.path.dirname(__file__) + f'/json/data.json','r+') as f:
data=json.load(f)
if not str(ctx.message.guild.id) in data:
data.update({str(ctx.message.guild.id): []})
data[str(ctx.message.guild.id)].append(cmd)
else:
if cmd not in data[str(ctx.message.guild.id)]:
data[str(ctx.message.guild.id)].append(cmd)
await ctx.send(embed=discord.Embed(description=f'{ctx.author.mention} has banned the command **{cmd}**',color=65535))
else:
await ctx.send(embed=discord.Embed(description=f'{ctx.author.mention} **{cmd}** is already banned', color=65535))
self.write("data", data)
If you can give me the code, that would be greatly appreciated.
Ok so you can remove the guild id simply by
# Do a if id in data.keys() b4 to make sure there wont be a KeyError
with open('json/data.json','r+') as f: # u don't need the f"" or __file__
data = json.load(f)
del data[str(ctx.guild.id)]
# save json do bomb stuff
Now deleting a specific command
#Load json like the previous snippet
if cmd in data[str(ctx.guild.id)]:
del data[str(ctx.guild.id)][data[str(ctx.guild.id)].index(cmd)]
#save json
and its also advisable to use a db instead of json(its very useful for seldom changed data) but if its a small project json would do fine
I have a function that gets the top 10 cryptocurrencies by market cap
import os
import json
from requests import Session
def get_top10():
CMC_API_KEY=os.environ.get('CMC')
parameters={
'start':1,
'limit':5000
}
headers={
'Accepts':'application/json',
'X-CMC_PRO_API_KEY':CMC_API_KEY
}
session=Session()
session.headers.update(headers)
url='https://pro-api.coinmarketcap.com/v1/cryptocurrency/map'
response=session.get(url,params=parameters)
json_file=json.loads(response.text)['data']
top10_rank_to_slug = {d['rank']: d['slug'] for d in json_file}
top_10 = sorted(top10_rank_to_slug.items())[:10]
for rank,name in top_10:
print(rank,name)
but in order to pass it to my discord bot the function has to return a value not print it how can I do that (I want the bot to loop through the list then return the items one by one I dont want the bot to just return the list )
#client.command()
#commands.check(check_channel)
async def top10(ctx):
await ctx.send(get_top10())
client.run(token)
how do you suggest I do that??
The first thing that comes to mind for me is to return the dictionary, then loop through the dictionary when sending the messages.
import os
import json
from requests import Session
def get_top10():
CMC_API_KEY=os.environ.get('CMC')
parameters={'start':1,
'limit':5000
}
headers={'Accepts':'application/json',
'X-CMC_PRO_API_KEY':CMC_API_KEY
}
session=Session()
session.headers.update(headers)
url='https://pro-api.coinmarketcap.com/v1/cryptocurrency/map'
response=session.get(url,params=parameters)
json_file=json.loads(response.text)['data']
top10_rank_to_slug = {d['rank']: d['slug'] for d in json_file}
top_10 = sorted(top10_rank_to_slug.items())[:10]
return top_10
Then you can await ctx.send the dictionary by each key:value pair:
#client.command()
#commands.check(check_channel)
async def top10(ctx):
top_10 = get_top_10()
for key in top_10:
await ctx.send(f"{key} is the key and {top_10[key]} is the value.")
client.run(token)
There are MANY other solutions and ways to do this, but this is frankly the least intrusive to your code and one of the easier to understand ones.
I want the bot to loop through the list then return the items one by one I dont want the bot to just return the list
I do not necessarily know why you want the above specifically, but if you share that, I may be able to help in a more suitable manner. Another simple solution is to turn the dictionary into a string in the function, then return the string already preformatted for the bot to send.
Basically I have a discord bot that auto leaves servers unless its in a database. I was wondering how I could make a command to add to that database and remove? Heres my current code
server=[878537556332015626,
884958773913985054,
869615568838357052]
#client.event
async def on_guild_join(guild):
if guild.id in server:
pass
elif guild.id not in server:
await guild.leave()
So where it says "server=[stuff here]" how could i make a command to add servers ids to that database? Maybe like ';addserver server-id' and it'd add it to that database, and also a remove command. Like ';removeserver server-id' ive attempted multiple times but it didnt work, neither did it show an error.
Or help me make this into a json file!
If your goal is to make a command for your bot such as ;addserver server-id, it would be quite simple. Here's an example for checking the validity of the ID and writing it to a servers.json file if it's valid:
#client.command()
async def addserver(ctx, message = None):
if client.get_guild(int(message)): # If the bot is in a guild with this ID, returns True
serverFile = json.loads(open('servers.json', 'r').read()) # Reading Json file to a dict
serverFile['servers'].append(int(message)) # Appending new ID to the dict
with open('servers.json', 'w') as writeFile:
json.dump(serverFile, writeFile, indent=4) # Writing dict to Json file
else:
pass # Do whatever you want with this part, maybe an error message would be sent to the command sender or something.
And servers.json should be laid out like this:
{
"servers": [
]
}
Reading the list of server IDs from the file would look like this:
json.loads(open('servers.json', 'r').read())['servers'] # Returns a list of IDs in the file.
And to remove an ID from the list:
#client.command()
async def removeserver(ctx, message = None):
serverList = json.loads(open('servers.json', 'r').read())['servers']
for id in serverList:
if int(message) == id:
serverList.remove(id)
serverDict = {}
serverDict['servers'] = serverList
with open('servers.json', 'w') as writeFile:
json.dump(serverDict, writeFile, indent=4)
The part you'll likely find the most value out of is the if client.get_guild(int(message)) line, as it will let you know whether the ID is valid or not. This can be applied to new functions that could clean up your server list if need be.
I made a "disable module" which is working, but when it loads into a json file I get a error message.
#client.command(aliases=["disable economy"])
async def disable_economy(message):
with open('disable economy.json', 'r+') as f:
channel = json.load(f)
if not f'{message.channel.id}' in channel:
channel[f'{message.channel.id}'] = "Channel ID"
json.dump(channel, f)
await message.channel.send(f"Economy has been disabled in <#{message.channel.id}>. ")
return
if f'{message.channel.id}' in channel:
await message.channel.send("Economy is already disabled in this channel.")
return
After doing the command it loads into a json file like this:
{}{"750485129436201023": "Channel ID"} and the error message I get is: End of file expected. The error is between the 2nd {. Can someone help?
{}{"750485129436201023": "Channel ID"} is not valid JSON.
Valid JSON can only have one root element, such as {}
Change your JSON file to just:
{"750485129436201023": "Channel ID"}
Python is appending to the file, instead of overwriting it, the easiest way to fix this is to seek to the beginning of the file before writing:
f.seek(0)
json.dump(channel, f)
So I'm making an rpg type game in Discord.py Rewrite and when the bot is ready, i run this code and I get the error "json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)"
#client.event
async def on_ready():
global userdata
try:
with open('userdata.json') as f:
userdata = json.load(f)
except FileNotFoundError:
print("Could not load userdata.json")
userdata = {}
The error you see will be thrown when reading in incorrect files.
Thus the problem is most likely the fact that you dont have content in your JSON file, or have created an incorrect JSON file.
To solve this problem you need to put correct json in the file you want to load.
As #Poojan said you can do the following (to stop it throwing errors):
{
}
In order to test if your json file is correct, I recommend using this site: jsonlint.
Write {} in your JSON file and save and run the code