Right now i have a working xp/leveling system, as said in the title is there a way of showing who has the most xp? Kinda like a leaderboard type of thing, If somebody would give a example that would be great!
if message.content.lower().startswith('/xp'):
await client.send_message(message.channel, "You currently have `{}` XP!".format(get_xp(message.author.id)))
user_add_xp(message.author.id, 2)
def user_add_xp(user_id: int, xp: int):
if os.path.isfile("users.json"):
try:
with open('users.json', 'r') as fp:
users = json.load(fp)
users[user_id]['xp'] += xp
with open('users.json', 'w') as fp:
json.dump(users, fp, sort_keys=True, indent=4)
except KeyError:
with open('users.json', 'r') as fp:
users = json.load(fp)
users[user_id] = {}
users[user_id]['xp'] = xp
with open('users.json', 'w') as fp:
json.dump(users, fp, sort_keys=True, indent=4)
else:
users = {user_id: {}}
users[user_id]['xp'] = xp
with open('users.json', 'w') as fp:
json.dump(users, fp, sort_keys=True, indent=4)
def get_xp(user_id: int):
if os.path.isfile('users.json'):
with open('users.json', 'r') as fp:
users = json.load(fp)
return users[user_id]['xp']
else:
return 0
Well, you've already got a way to grab the users via:
with open('users.json', 'r') as fp:
users = json.load(fp)
So, you can combine that with sorted and this should give you a list in order top to bottom of users based on xp.
sorted(users, key=lambda x : users[x].get('xp', 0), reverse=True)
From there you're going to have to take that list and make it into something easy for people to digest. Here's one example.
high_score_list = sorted(users, key=lambda x : users[x].get('xp', 0), reverse=True)
message = ''
for number, user in enumerate(high_score_list):
message += '{0}. {1} with {2}xp\n'.format(number + 1, user, users[user].get('xp', 0))
That should give you the message to send in order from top to bottom displaying their rank, name, and xp.
Related
I keep trying, it was a tutorial. I did exactly what it said. I doubt the next episode will say what's wrong. why do i need so many words ,,,
#client.command()
async def balance(ctx):
await open_account(ctx.author)
user = ctx.author
users = get_bank_data()
wallet_amt = users[str(user.id)]["wallet"]
bank_amt = users[str(user.id)]["bank"]
em = discord.Embed(title = f"{ctx.author.name}'s balance",color=discord.color.dark_green)
em.add_field(name = "Wallet Balance", value = wallet_amt)
em.add_field(name = "Bank Balance", value = bank_amt)
await ctx.send(embed=em)
#client.command()
async def beg(ctx):
await open_account(ctx.author)
users = get_bank_data()
user = ctx.author
earnings = random.randrange(51)
await ctx.send(f"Someone gave you {earnings} coins!!")
users[str(user.id)]["wallet"] += earnings
with open("bank.json", "w") as f:
json.dump(users, f)
def open_account(user):
users = await get_bank_data()
with open("bank.json", "r") as f:
users = json.load(f)
if str(user.id) in users:
return False
else:
users[str(user.id)] = {}
users[str(user.id)]["wallet"] = 0
users[str(user.id)]["bank"] = 0
with open("bank.json", "w") as f:
json.dump(users, f)
return True
def get_bank_data():
with open("bank.json", "r") as f:
users = json.load(f)
return users
but with this error
z:\DBot\bot(1.2).py:108: RuntimeWarning: coroutine 'Command.__call__' was never awaited
with open("bank.json", "r") as f:
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
i don't know what to do. Sorry my questions are bad because i just want someone to answer them, dont have time to make them good
open_account() and get_bank_data() are not required be asynchronous functions,
You can use def open_account(user) and def get_back_data().
If you do that, you should remove await while calling those two functions.
I was trying to make my code a little cleaner by using cogs but it doesn't seem to work. When I do +balance this error comes up: Ignoring exception in command None: discord.ext.commands.errors.CommandNotFound: Command "balance" is not found: Here's the code part in main.py:
for file in os.listdir("./cogs"): # lists all the cog files inside the cog folder.
if file.endswith(".py"): # It gets all the cogs that ends with a ".py".
name = file[:-3] # It gets the name of the file removing the ".py"
bot.load_extension(f"cogs.{name}") # This loads the cog.
And from the balance file:
bot = commands.Bot(command_prefix='+')
class Balance(commands.Cog):
def __init__(self, client):
self.bot = bot
#commands.command(aliases = ["bal"])
async def balance(self, ctx):
await open_account(ctx.author)
user = ctx.author
users = await get_bank_data()
wallet_amt = users[str(user.id)]["wallet"]
#bank_amt = users[str(user.id)]["bank"]
em = discord.Embed(title = f"{ctx.author.name}'s balance",color = (0x95a5a6), description = f"{wallet_amt} dogecoins")
#em.add_field(name = "Bank balance",value = bank_amt)
await ctx.send(embed = em)
async def open_account(user):
users = await get_bank_data()
if str(user.id) in users:
return False
else:
users[str(user.id)] = {}
users[str(user.id)]["wallet"] = 250
users[str(user.id)]["bank"] = 0
with open("mainbank.json","w") as f:
json.dump(users,f)
return True
async def get_bank_data():
with open("mainbank.json","r") as f:
users = json.load(f)
return users
async def update_bank(user,change = 0,mode = "wallet"):
users = await get_bank_data()
users[str(user.id)][mode] += change
with open("mainbank.json","w") as f:
json.dump(users,f)
return True
def setup(bot):
bot.add_cog(Balance(bot))
I'm new to coding and cogs especially so if anyone knows how to fix this, please help me.
I can't tell if the commands and functions you're showing are inside the class or not. Also, why are you creating a new Bot instance, and why does your init function take an argument called client and then set self.bot to bot?
Try replacing client in your init function with bot, or vice versa.
Do you get any errors when you try to run your main file?
Alright, so I am soooo confused. When I do my command "prefix", I get this error
return prefixes[str(message.guild.id)]
KeyError: 'server.id'
Here's all code I got:
#client.event
async def on_guild_join(guild):
with open('prefixes.json', 'r') as f:
prefixes = json.load(f)
prefixes[str(guild.id)] = ['s!', 'S!']
with open('prefixes.json','w') as f:
json.dump(prefixes, f, indent=4)
#client.event
async def on_guild_remove(guild):
with open('prefixes.json', 'r') as f:
prefixes = json.load(f)
prefixes.pop(str(guild.id))
prefixes[str(guild.id)] = ['s!', 'S!']
with open('prefixes.json', 'w') as f:
json.dump(prefixes, f, indent=4)
Command:
#client.command()
async def prefix(ctx, *, prefix):
with open('prefixes.json', 'r') as f:
prefixes = json.load(f)
prefixes[str(ctx.guild.id)] = prefix
with open('prefixes.json', 'w') as f:
json.dump(prefixes, f, indent=4)
await ctx.send(f'Prefix set to: **"{prefix}"**')
also this piece of code:
def get_prefix(client, message):
with open('prefixes.json','r') as f:
prefixes = json.load(f)
return prefixes[str(message.guild.id)]
client = commands.Bot(command_prefix=get_prefix)
Please help me!
nvm got answer:
def get_prefix(client, message):
with open(....) as ...:
prefixes = json.load(...)
try:
# this will error if the guildid is not in the json
return prefixes[str(message.guild.id)]
except:
# this code will run if the stuff in the if errors
# here you need to add the guildid with your default prefix to the json
# the code is pretty similar to what you have in your on_guild_join event, youll just need to change some stuff, like how to get the current guild
# when you did that then do what you had in the try like this:
# it shouldnt error now cause the guildid is now in the json
return prefixes[str(message.guild.id)]
Thank you for trying to help :D (lol)
hello when it error I want it to automatically create folder for the server where the error happened
def get_prefix(client, message):
with open(f'Data/{message.guild.id}/settings.json', 'r') as f:
prefixes = json.load(f)
return prefixes['prefix']
client = commands.Bot(command_prefix=get_prefix, case_insensitive=True)
By using try,except we can able to run a block of code if any error pops up[....]
when the guild already have the settings.json it returns the PREFIX! else it will create a new settings.json for that guild!.
Note that: set some values to the data dict! to store some values into that created settings.json
def get_prefix(client, message):
try:
with open(f'Data/{message.guild.id}/settings.json', 'r') as f:
prefixes = json.load(f)
return prefixes['prefix']
except:
data = {'prefix':'!'}#data is dict to save something on it
with open(f'Data/{message.guild.id}/settings.json', 'w') as f:
json.dump(data, f)
return data['prefix']
client = commands.Bot(command_prefix=get_prefix, case_insensitive=True)
I would like to, as an admin, add points to a specific member's balance
Know how to create a JSON file with all the "points" someone has.
import discord
from discord.ext import commands
import random
import os
import json
# this line of code gives the bot a comand prefix
bot = commands.Bot(command_prefix="/")
# This line of code tells the bot to start up
#bot.event
async def on_ready():
print("The bot is now online!")
#bot.command(pass_context=True)
async def leaderboard(ctx):
await ctx.send("This is a work in progress, this will dieplay the leaderboard")
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 {} ben points".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.keys:
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()
#This line of code tells the bot to run
bot.run("Token")
I am not sure on what I am meant to do from here.
I might be over complicating the code if anyone can make it more efficient I will be incredibly grateful.
Here's the essential usage and everything you'll need to know for the basics of JSON:
# Creating a dictionary with some values
>>> data = {"foo": "bar", "key": "value"}
# Opening a file and writing to it
>>> with open("db.json", "w+") as fp:
... json.dump(data, fp, sort_keys=True, indent=4) # Kwargs for beautification
# Loading in data from a file
>>> with open("db.json", "r") as fp:
... data = json.load(fp)
# Accessing the values
>>> data["foo"]
'bar'
>>> data["key"]
'value'
This can be adapted to suit your needs, perhaps something like:
# Let's say the JSON has the following structure:
# {"users": {112233445566778899: {"points": 0}, 224466881133557799: {"points": 0}}}
# The "users" key is a bit redundant if you're only gonna store users in the file.
# It's down to what you'll be storing in the file and readability etc.
import json
import random
import typing
def add_points(member_id: str, amount: int):
# Open the file first as to load in all the users' data
# Making a new dict would just overwrite the current file's contents
with open("file.json", "r") as fp:
data = json.load(fp)
data["users"][member_id]["points"] += amount
# Write the updated data to the file
with open("file.json", "w+") as fp:
json.dump(data, fp, sort_keys=True, indent=4)
return data["users"][user_id]["points"]
#bot.command()
async def give(ctx, member: typing.Optional[discord.Member]=None, points:typing.Optional[int]=None):
if not member:
member = ctx.author
if not points:
points = random.randint(10, 50)
# Have a separate getter for the points - this was just for the sake of concise code
total_points = add_points(member.id, points)
await ctx.send(f"Successfully gave {member.mention} {points} points! Total: {total_points}")
I'll be happy to clarify anything if need be.
References:
Dictionary exercises - Might be worth taking a look into so then you're comfortable with how they work.
f-Strings - Python 3.6.0+
json.load()
json.dump()
typing.Optional
User.id
commands.Context
Context.author