I need help with the following code:
import discord
from discord.ext import commands, tasks
import os
TOKEN = "tokenthing"
client = commands.Bot(command_prefix="$$")
#client.event
async def on_ready():
test.start()
print("Succesful Login as {0.user}".format(client))
#client.command()
async def GiveMoney(ctx, user : discord.User, value : int):
if value <= 0:
await ctx.send("Can't send negative money.")
return
else:
pass
sender = str(ctx.author)
reciever = str(user)
if os.path.exists(sender+".txt"):
pass
else:
await ctx.send("You Don't have an account. Type $$CreateAccount to create one.")
return
if os.path.exists(reciever+".txt"):
pass
else:
await ctx.send("The Person you are trying to give money doesn't have a bank Account")
return
try:
f= open(sender+".txt", "r")
balance = f.read()
f.close()
balance = int(balance)
balance = balance - value
balance = str(balance)
f = open(sender+".txt", "w")
f.write(balance)
f.close()
except FileNotFoundError:
await ctx.send("You don't have a Bank account. Type $$CreateAccount to create one.")
return
try:
f = open(reciever+".txt", "r")
balance = f.read()
f.close()
balance = int(balance)
balance = balance + value
balance = str(balance)
f = open(reciever+".txt", "w")
f.write(balance)
f.close()
except FileNotFoundError:
await ctx.send("The Person You are sending money dosen't have an account")
print("{0} sent {1} to {2}".format(sender, value, reciever))
#tasks.loop(seconds=10)
async def test(ctx):
for i in range(10):
print(i)
client.run(TOKEN)
I can't seem for the life of me to get it to run the task on bot readiness.
I'm not getting any error or anything it just seems to skip it.
I am using Discord.py-rewrite on a windows 10 machine.
I suspect I missed something with the commands but I'm not sure.
Thanks
Just add await when you start your loop. Because your function is async. Example:
#client.event
async def on_ready():
await test.start()
Related
I am trying to create a discord bot that gives peoples wins and then stores it into a json file. When I run the command ?win # I run into an error that displays their id within the error. I believe this is because their id is not in the json file. However I want my code to create an entry for their id and wins if it is not already inside the json file. Here are my functions and command.
open wins
async def open_wins(user):
users = await get_win_data()
if str(user.id) in users:
return False
users[str(user.id)] = {"Wins": 0}
with open('leaderboard.json',"w") as f:
json.dump(users,f)
return True
Get win data
async def get_win_data():
with open("leaderboard.json", "r") as f:
users = json.load(f)
return users
win code
#client.command()
#commands.has_role("Draft Manager")
async def win(ctx,member: discord.Member = None ):
if not member:
member = ctx.author
await open_wins(member)
users = await get_win_data()
user = member
onewin = 1
await ctx.send(f"You just gained {onewin} win ")
users[str(user.id)]["Wins"] += onewin
with open("leaderboard.json", "w") as f:
json.dump(users, f, indent=4)
Here is my json file
{
"325837218222440460": {
"Wins": 1
}
}
I would like to the note the win command only works when I do "?win" but when I do "?win <#user>" thats when I get an error.
You use await open_wins(member) only when member is None.
But if you use "?win <#user>", #user may be still not recorded to your file. So, you need to use await open_wins(member) function in all cases.
#client.command()
#commands.has_role("Draft Manager")
async def win(ctx,member: discord.Member = None ):
if not member:
member = ctx.author
await open_wins(member)
users = await get_win_data()
user = member
onewin = 1
await ctx.send(f"You just gained {onewin} win ")
users[str(user.id)]["Wins"] += onewin
with open("leaderboard.json", "w") as f:
json.dump(users, f, indent=4)
import discord
from discord.ext import commands
import os
import json
import random
from discord.ext.commands import Bot
os.chdir("")
there is correct path, i checked this
Bot = commands.Bot(command_prefix = "$")
token = 'my token'
which is also correct
#Bot.command()
async def give(ctx, member:discord.Member, amount = None):
await open_account(ctx.author)
await open_account(member)
amount = int(amount)
if amount == None:
await ctx.send("Please enter the amount")
return
bal = await update_bank(ctx.author)
if amount>bal[1]:
await ctx.send("You don't have that much money")
return
if amount<=0:
await ctx.send("Amount must be positive")
return
await update_bank(ctx.author, -1*amount, "wallet")
await update_bank(member, 1*amount, "wallet")
emb = discord.Embed(description = f"You gave {member.name} {amount} gold coins", color = 0x2ecc71)
await ctx.send(embed = emb)
There is whole give command
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"] = 0
with open("mainbank.json", "w") as f:
json.dump(users, f)
return True
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)
bal = [users[str(user.id)]["wallet"]]
return bal
As you can see, there is give command, which doesn't work. I also know, that problem isn't with open_account function, but I am not sure about update_bank.
There is an error:
if amount>bal[1]:
IndexError: list index out of range
If you have idea, please write.
You are nesting the list for the bal inside another list: [users[str(user.id)]["wallet"]]. So if users[str(user.id)]["wallet"] has the value [0, 1], it will actually be [[0, 1]]. There is no index 1, there is only index 0 with a nested list that goes up to the index 1. You can fix this by simply removing the extra brackets: users[str(user.id)]["wallet"].
You could have easily discovered this by printing bal. Knowing how to debug is an incredibly useful skill.
I'm trying to make a random fact send at certain times. It worked before I implemented a dict to hold the random facts and it should work now, the only problem I'm running into is I can't access the guild id inside the on_ready() event. Here is what I have:
async def func(self):
await bot.wait_until_ready()
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
------> guild_id = NEED
channel = bot.get_channel(guild_settings[guild_id]["random_facts_channel_id"])
random_messages = guild_settings[guild_id]["random_facts"].value()
if random_messages is None:
await channel.send(f"You need to add a fact first.")
else:
random_messages = random.choice(random_messages)
await channel.send(random_messages)
#commands.Cog.listener()
async def on_ready(self):
print("Bot is ready.")
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
# Initializing scheduler
scheduler = AsyncIOScheduler()
hour = 12
minute = 0
for guild in bot.guilds:
guild_id = str(guild.id)
try:
hour = guild_settings[str(guild_id)]["random_facts_send_time"]["hour"]
minute = guild_settings[str(guild_id)]["random_facts_send_time"]["minute"]
except KeyError:
print(f"{guild_id} has a KeyError with the random fact feature.")
continue
# Sends "Your Message" at 12PM and 18PM (Local Time)
scheduler.add_job(self.func, CronTrigger(hour=hour, minute=minute, second="0"))
# Starting the scheduler
scheduler.start()
If I were able to somehow get the guild id then I'm sure it would work correctly, I just can't figure out how.
EDIT: This is what I have working so far
async def func(self):
await bot.wait_until_ready()
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
for guild_id in guild_settings:
channel = bot.get_channel(guild_settings[guild_id]["random_facts_channel_id"])
if guild_settings[guild_id]["random_facts"] is not None:
random_facts = []
for values in guild_settings[guild_id]["random_facts"].values():
random_fact = values.split("\n")
random_facts += random_fact
try:
random_choice = random.choice(random_facts)
except IndexError:
continue
await channel.send(random_choice)
#commands.Cog.listener()
async def on_ready(self):
print("Bot is ready.")
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
# Initializing scheduler
scheduler = AsyncIOScheduler()
hour = 12
minute = 0
for guild in bot.guilds:
guild_id = str(guild.id)
try:
hour = guild_settings[str(guild_id)]["random_facts_send_time"]["hour"]
minute = guild_settings[str(guild_id)]["random_facts_send_time"]["minute"]
except KeyError:
print(f"{guild_id} has a KeyError with the random fact feature.")
continue
# Sends "Your Message" at 12PM and 18PM (Local Time)
scheduler.add_job(self.func, CronTrigger(hour=hour, minute=minute, second="0"))
# Starting the scheduler
scheduler.start()
If your bot is on only one server, you can simply get the guild object by using discord.utils.get.
async def func(self):
await bot.wait_until_ready()
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
guild = discord.utils.get(bot.guilds, name="guild's name")
channel = bot.get_channel(guild_settings[guild.id]["random_facts_channel_id"])
random_messages = guild_settings[guild.id]["random_facts"].value()
if random_messages is None:
await channel.send(f"You need to add a fact first.")
else:
random_messages = random.choice(random_messages)
await channel.send(random_messages)
If it's on multiple servers, you have to loop through the guilds and send the messages one by one.
async def func(self):
await bot.wait_until_ready()
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
for guild in bot.guilds:
channel = bot.get_channel(guild_settings[guild.id]["random_facts_channel_id"])
random_messages = guild_settings[guild.id]["random_facts"].value()
if random_messages is None:
await channel.send(f"You need to add a fact first.")
else:
random_messages = random.choice(random_messages)
await channel.send(random_messages)
As #ŁukaszKwieciński said, you can just do this:
async def func():
for guild in client.guilds:
print(guild.id) #Do something with each ID
Or you can waste time and memory doing this (which was my initial approach 😔):
guildIDs = set()
#client.event
async def on_ready():
for guild in client.guilds:
guildIDs.add(guild.id)
#client.event
async def on_guild_join(guild):
guildIDs.add(guild.id)
#client.event
async def on_guild_remove(guild):
guildIDs.remove(guild.id)
guildIDs is an integer set that will contain all the IDs of all the guilds that the bot is present in. The reason I used a set is to prevent repetition of IDs.
You can then use each ID in a function like this:
async def func():
for guildID in guildIDs:
print(guildID) #Do something with each ID
I recommend using tasks extension of discord.py
If you'd like to get the code, here it is.
#tasks.loop(hours=10)
async def func():
await bot.wait_until_ready()
with open('guild_settings.json', 'r') as file:
guild_settings = json.loads(file.read())
for guild_id in guild_settings:
channel = bot.get_channel(guild_settings[guild_id]["random_facts_channel_id"])
if guild_settings[guild_id]["random_facts"] is not None:
random_facts = []
for values in guild_settings[guild_id]["random_facts"].values():
random_fact = values.split("\n")
random_facts += random_fact
try:
random_choice = random.choice(random_facts)
except IndexError:
continue
await channel.send(random_choice)
#tasks.loop(minutes=15)
async def update_interval():
hour = 12
minute = 0
for guild in bot.guilds:
guild_id = str(guild.id)
try:
hour = guild_settings[str(guild_id)]["random_facts_send_time"]["hour"]
minute = guild_settings[str(guild_id)]["random_facts_send_time"]["minute"]
except KeyError:
print(f"{guild_id} has a KeyError with the random fact feature.")
continue
func.cancel()
func.change_interval(hours=hour, minutes=minute)
I hope this is helpful.
I've got a working currency system, but we want ways to earn money. So i want to make mini games, so i made a coin flip game but i can't get it to work, it tells me the command is not found when i try it.I also want to make it so the game costs >currency so you can win a little bit so basically betting
from discord.ext import commands
import discord
import json
import random
from discord.ext.commands import Bot
from discord import Game
import time
import asyncio
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 {} :Ereb: 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.command() #problem
async def on_message(message):
if message.content.startswith('$coinflip'):
randomlist = ["heads","tails",]
await client.send_message(message.channel,(random.choice(randomlist)))***
bot.run("token")
```
You need to decorate your on_message callback with bot.event instead of bot.command. You also need to add a bot.process_commands line so that the other commands are invoked normally.
#bot.event
async def on_message(message):
if message.content.startswith('$coinflip'):
randomlist = ["heads","tails",]
await client.send_message(message.channel,(random.choice(randomlist)))
else:
await bot.process_commands(message)
When this code runs it works getting the user ID from discord and putting they have 100 money in the json, but once you restart the bot you have to register again and it writes the same user ID in the json file thinking it's a new user when it is not.
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 after the bot is turned off and back on and registered twice (fake user IDs):
{"56789045678956789": 100, "56789045678956789": 100}
Need it to be able to recognize the user IDs even after the bot is turned off and back on.
This is happening because JSON objects always have strings for the "keys". So json.dump converts the integer keys to strings. You can do the same by converting the user ids to strings before you use them.
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")
You just need to load the .json file that you have created at program startup. Instead of amounts = {} try this:
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
UPDATE
I believe after reading your comment and reviewing your code the issue is in your register() code.
You have:
if id not in amounts:
But it should be:
if id not in amounts.keys():
I found out the problem and tested it myself, so it isn't the .keys() or the os thing, but in the _save() function. I first did a test with the _save function and without it, and instead of using a called on function, it worked when i did it manually. Like so
(P.S i did this within a cog, only difference is the name #commands.command, which is #bot.command and you need to add "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)
ALSO VERY IMPORTANT NOTE, make sure when you create a json file, it's name ends with ".json" and all that's in it is
{
}