So, I was making a Discord bot using discord.py and here's my code:
#bot.command()
async def list(ctx):
ok = 0
for i in db.keys():
# lmao why is there even a while loop here #
while ok >= 11:
server_num = ok+1
em = discord.Embed(title='Oldest servers in the list!',description=f'Server {server_num}')
em.add_field(name='Name',value=db[i]['name'],inline=False)
em.add_field(name='Description',value=db[i]['description'],inline=False)
em.add_field(name='Tags',value=db[i]['tags'],inline=False)
await ctx.send(embed=em)
ok+=1
But, what I also want is that it returns the servers with most number of upvotes, we have an upvotes system and the code for it is:
#bot.command()
#commands.cooldown(1,7200)
async def upvote(ctx):
try:
id = str(ctx.message.guild.id)
if id in db.keys():
db[id]["upvote"][0] += 1
await ctx.send(f"upvoted ")
save()
except commands.CommandOnCooldown:
await ctx.send('once every 12 hours ;---------------;')
except:
await ctx.send('error ;-;')
And, every upvote is stored in a JSON file (db.json) which looks like this:
{
"738049816357109831": {
"description": "I am a good server",
"id": "738049816357109831",
"link": "https://discord.gg/gQ6FABc",
"name": "Aypro's Lab",
"review(s)": [],
"tags": [
"#good_boi"
],
"upvote": [
0
]
}
}
And I am not really sure how to get the servers with most number of up votes. Thanks to who ever will answer this as it is going to really help me with my bots development.
A simple way that I'd do it would be to incorporate a function to create a temporarily restructured dictionary that allows for you to easily get the max key from your json db.
def get_highest_server(dictionary):
server_votes = {}
for key, value in dictionary.items():
server_votes[key] = dictionary[key]['upvote']
return max(server_votes, key=server_votes.get)
This will iterate through your DB file and restructure it into a dictionary that has only 1 key and one value (the value being the number of upvotes). A demonstration on using this function is as below:
import json
def get_highest_server(dictionary):
server_votes = {}
for key, value in dictionary.items():
server_votes[key] = dictionary[key]['upvote']
return max(server_votes, key=server_votes.get)
with open("db.json", "r") as dFile:
databases = json.load(dFile)
highest_server = get_highest_server(databases)
Related
intro
hello there , iam trying to create a counter/stat system . its stores how many time a user sayed a specific word , and maybe soon more , but for now i just try getting started. i spend the whole sunday with this so far .
i started python 5 days ago , and its the first time i try me in coding , pls explain, be friendly & helpful.
my problem
i just can store one word counter per user.
i have problems creating a command to get the stats.
bot.py :
def load_stats():
with open('stats.json', 'r') as f:
stats = json.load(f)
return stats
def save_stats(stats):
with open('stats.json', 'w') as f:
json.dump(stats, f, indent=4))
log_data = {}
#bot.listen()
async def on_message(message):
if any(x in message.content.lower() for x in ["bye", "cya", "bb", "gn8", "cya later"]):
await loging.meslog_green(bot, message, 'bye')
log_data = load_stats()
authorid = str(message.author.id)
author = str(message.author)
if authorid {'bye'} in log_data:
log_data[str(message.author.id)]['bye'] += 1
save_stats(log_data)
else:
log_data[str(message.author.id)] = {}
log_data[str(message.author.id)]['bye'] = 1
save_stats(log_data)
if any(x in message.content.lower() for x in ["hello", "hey", "hi", "greetings", "good morning", "good afternoon"]):
await loging.meslog_green(bot, message, 'hey')
log_data = load_stats()
authorid = str(message.author.id)
author = str(message.author)
if authorid {'hey'} in log_data:
log_data[str(message.author.id)]['hey'] += 1
save_stats(log_data)
else:
log_data[str(message.author.id)] = {}
log_data[str(message.author.id)]['hey'] = 1
save_stats(log_data)
#bot.command(name='hey')
async def hey(ctx):
stats = load_stats()
await ctx.reply(f'you said {stats[ctx.author.id]["hey"]} times stats ', delete_after=10.0)'
await loging.comlog_green(bot, ctx, 'hey')
the stats.json :
{
"448827301235084672": {
"hey": 2
}
}
If I interpreted your question correctly and you only need to format your file better, you can use the indent option.
If indent is a non-negative integer, then JSON array elements and
object members will be pretty-printed with that indent level. An indent
level of 0 will only insert newlines. None is the most compact
representation.
For example, using
def save_stats(stats):
with open('stats.json', 'w') as f:
json.dump(stats, f, indent=4)
will result in
{
"448827123485084672": {
"hey": 2
},
"884530123033089076": {
"hey": 1
}
}
You don't need to modify the load method because the indent doesn't actually change the meaning of the json data.
I have this bot written in Replit and discord.py and I can’t make the leaderboard work. I don't know why. I followed the Code With Swastik tutorial How to make a leaderboard in an economy Discord bot, episode 4.
I want to make a leaderboard which will show the top 5 people with the most money.
I use a JSON file as the database (I know it’s not recommended, but I know how to use it so I use it).
JSON example for one person:
"coins": 12253,
"job": "none",
"expirience": 0,
"inventory": [],
"bank": 10000
}
The code for the leaderboard command:
#bot.command(aliases=['lb'])
async def leaderboard(ctx, pepol_to_show = 5):
data = await get_bank_data()
lb = {}
total = []
for user in data:
name = int(user)
total_amount = data[user]["coins"] + data[user]["bank"]
lb[total_amount] = name
total.append(total_amount)
total = sorted(total,reverse=True)
em4 = discord.Embed(title = f"Top {pepol_to_show} Richest people", description = "Who has the most potatoes (Wallet + Bank)", color = discord.Colour.red())
index = 1
for amt in total:
id_ = lb[amt]
member = bot.get_usser(id_)
name = member.name
em4.add_field(name = f"{index}. {name}", value = f"{amt}", inline = False)
if index == pepol_to_show:
break
else:
index += 1
await ctx.reply(embed=em4)
async def get_bank_data():
with open("users.json", "r") as f:
data = json.load(f)
return data
When I run the lb command nothing is sent in Discord, and I get 0 errors. I don't have any idea why.
Why doesn’t this work? What do I need to do to fix it?
You have a typo, member = bot.get_usser(id_), here. It should be just get_user. I tested it, and the code works fine otherwise.
You need to set up an error handler to see errors while sending commands with the on_command_error event
Or just a local error handler to see what's wrong:
#leaderboard.error
async def leaderboard_error(ctx, error):
print(error)
print(type(error))
You can get the whole traceback after doing some work with the traceback module.
I have a question, how to use Pymongo to write a store of roles and other items, I tried to do this:
#Bot.event
async def on_ready():
await Bot.change_presence(status = discord.Status.online, activity = discord.Streaming(name = '!help', url = ''))
print(Bot.user.name + " is ready.")
for guild in Bot.guilds:
for member in guild.members:
post = {
"_id": member.id,
"server_id": guild.id,
"balance": 300,
"xp": 0,
"lvl": 1
},
{
"role": 0,
"cost": 0
}
if collection.count_documents({"_id": member.id}) == 0:
collection.insert_one(post)
And
#commands.command()
async def add_shop(self, ctx, role: discord.Role, cost: int):
self.collection.update_one({"_id": ctx.author.id},
{"$set": {"role": role}})
self.collection.update_one({"_id": ctx.author.id},
{"$set": {"cost": cost}})
await ctx.message.add_reaction("✅")
#commands.command()
async def shop(self, ctx):
r = self.collection.find_one({"_id": ctx.author.id}["role"])
c = self.collection.find_one({"_id": ctx.author.id}["cost"])
await ctx.send(r, c)
But it didn't work out for me. I decided to contact you. Thank you in advance!
MongoDB and pymongo can only store objects of certain understood types, such as strings, numbers, dates and a few more that are listed here.
If you attempt to add in other types, objects, classes etc. outside these well defined types, you will get the error mentioned.
You will need to convert any types to the supported types; maybe try and convert to a string (using str(object)) if the class supports this, otherwise there's some useful general documentation here:
https://pymongo.readthedocs.io/en/stable/examples/custom_type.html
This is a simple program to retrieve candlestick data from Binance exchange for several pairs. I found out that it could be done with asyncio package.
import websockets
import asyncio
import json
import pprint
async def candle_stick_data():
url = "wss://stream.binance.com:9443/ws/" #steam address
first_pair = 'xlmbusd#kline_1m' #first pair
async with websockets.connect(url+first_pair) as sock:
pairs = '{"method": "SUBSCRIBE", "params": ["xlmbnb#kline_1m","bnbbusd#kline_1m" ], "id": 1}' #other pairs
await sock.send(pairs)
print(f"> {pairs}")
while True:
resp = await sock.recv()
resp=json.loads(resp)
pprint.pprint(resp)
candle = resp['k']
asyncio.get_event_loop().run_until_complete(candle_stick_data())
I am getting messages and changing type to dict with json.loads(resp). My question is how can I access dict values because candle = resp['k'] causes "Key error 'k'". I am new to asyncio maybe I don't need it at all to retrieve data for several pairs.
updated message screenshot
Your first incoming message really does not have 'k' key in dictionary.
I just added if else block to your code and it works well:
import websockets
import asyncio
import json
import pprint
async def candle_stick_data():
url = "wss://stream.binance.com:9443/ws/" #steam address
first_pair = 'xlmbusd#kline_1m' #first pair
async with websockets.connect(url+first_pair) as sock:
pairs = '{"method": "SUBSCRIBE", "params": ["xlmbnb#kline_1m","bnbbusd#kline_1m" ], "id": 1}' #other pairs
await sock.send(pairs)
print(f"> {pairs}")
while True:
resp = await sock.recv()
resp = json.loads(resp)
# get 'k' key value if it exits, otherwise None
k_key_val = resp.get('k', None)
# easy if else block
if not k_key_val:
print(f"No k key found: {resp}")
else:
pprint.pprint(k_key_val)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(candle_stick_data())
I'm Creating a bot with reCAPTCHA and leveling system.
The data is being stored in a .JSON file (temporarily, I'm trying to learn how to use MySQL and transfer the data to a proper db to prevent corruption of the data)
The .JSON file looks a bit like this
{
"user": [
{
"u": "224906648890638337",
"m": 89,
"lvl": 0,
"score": 28,
"captcha": false,
"captchacode": 123456
},
{
"u": "635042028643811357",
"m": 0,
"lvl": 0,
"score": 0,
"captcha": false,
"captchacode": 12345
]
}
The Captcha code is the code that was sent to a user when they joined the server in the form of an Image.
What I want to do is have a verify command, that looks into the .JSON file and returns the captcacode of the user that sent the verify command.
And then it checks if the captchacode they were sent matches with the one they sent in the verify command.
My code for that:
#commands.command()
async def verification(self, ctx, code):
with open("JSON_files/testdb.json", "r") as f:
db = json.load(f)
if captchacode == code:
await ctx.send("Captcha successfully completed ✅")
remove_unverified = discord.utils.get(ctx.message.guild.roles, name="unverified")
await ctx.author.remove_roles(remove_unverified)
else:
await ctx.send("⛔| Invalid captcha! Make sure to type: `!verification (code that was sent to you)` but without the brackets")
If anyone could help me with that, that would be great.
Comment or just ask if anything needs clarification.
Thanks!
First, you are missing a } in your json file
"captcha": false,
"captchacode": 12345
} <- here
]
}
In your verification function, you can iterate through every user and then check, if the captchacode matches.
Your verification function could be looking like this
#commands.command()
async def verification(self, ctx, code):
with open("JSON_files/testdb.json", "r") as f:
db = json.load(f)
captchacode_matched = False
# iterate through every user
for user in db["user"]:
# get the captchacode
user_captchacode = user["captchacode"]
# check if the code matches
if user_captchacode == code:
captchacode_matched = True
await ctx.send("Captcha successfully completed ✅")
remove_unverified = discord.utils.get(ctx.message.guild.roles, name="unverified")
await ctx.author.remove_roles(remove_unverified)
# break the loop
break
# if no captchacode matched, send invalid captcha
if captchacode_matched == False:
await ctx.send("⛔| Invalid captcha! Make sure to type: `!verification (code that was sent to you)` but without the brackets")
I hope this will work for you