I was creating a discord bot, and when I used a command(!buy #Role), it crashed with:
cursor.execute("UPDATE users SET cash = cash - {} WHERE id = {}".format(("SELECT cost FROM shop WHERE role_id = {}".format(role.id)).fetchone()[0], ctx.author.id))
AttributeError: 'str' object has no attribute 'fetchone'
I don't understand what's up, because role id is integer! Here code is:
import discord
from discord.ext import commands
import sqlite3
client = commands.Bot(command_prefix='!')
client.remove_command('help')
connection = sqlite3.connect('server.db')
cursor = connection.cursor()
#client.event
async def on_ready():
cursor.execute("""CREATE TABLE IF NOT EXISTS shop (
role_id INT,
id INT,
cost BIGINT
)""")
#client.command(aliases = ['buy', 'buy-role'])
async def __buy(ctx, role: discord.Role = None):
if role is None:
await ctx.send(f"**{ctx.author}**, choose a role, which you want to buy!")
else:
if role in ctx.author.roles:
await ctx.send(f"**{ctx.author}**, you already have this role!")
elif cursor.execute("SELECT cost FROM shop WHERE role_id = {}".format(role.id)).fetchone()[0] > cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]:
await ctx.send(f'**{ctx.author}**, not enough money!')
else:
await ctx.author.add_roles(role)
cursor.execute("UPDATE users SET cash = cash - {} WHERE id = {}".format(("SELECT cost FROM shop WHERE role_id = {}".format(role.id)).fetchone()[0], ctx.author.id))
connection.commit()
await ctx.message.add_reaction('✅')
client.run('MY TOKEN')
PLEASE HELP!
Try to use
cursor.execute("UPDATE users SET cash = %s WHERE id = %s", [value1, value2])
and you can create a variable for the coins in the database and then subtract the price.
Related
`Hi Guys,
I need some help.
So.. ive been developing a discord bot over the last year and trying to make some improvements to the games i have made.. it is basically an economy system that allows users to transfer funds to one another, place bets, and recieve winnings etc.
I have created a slots game that automatically generates winnings and economy but my idea is to modify an exisiting heads or tails game with the same functions to basically:
Allow a user to deposit a bet into an account that holds the winnings/profits/bets etc.
The user will then either select heads or tails to win the challenge.
The winnings will then be transferred directly from the specific account.
My current code is:
mport discord
import random
from discord.ext import commands
from discord.ext import commands, tasks
from discord.ui import select, View
from discord.embeds import Embed
from discord import colour
import asyncio
from itertools import cycle
import os
import json
import datetime
from random import choice
intents = discord.Intents.default()
intents.message_content = True
client = commands.Bot(command_prefix='!', intents=intents) #Command prefix
#Notifies vs code that the bot is running on VS code#
#client.event
async def on_ready():
print("Bot is ready")
#Slot machine command when user enters !slots 50#
#client.command(pass_context=True)
async def slots(ctx, amount=None):
if amount == None:
em = discord.Embed(title=f'❓Please enter an amount❓',color = discord.Color.red())
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
return
bal = await update_bank(ctx.author)
amount = int(amount)
if amount > bal[0]:
em = discord.Embed(title=f'❌You do not have sufficient balance❌')
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
return
if amount < 0:
em = discord.Embed(title=f'❗Amount must be positive❗')
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
return
slots = ['🧝♂️', '🔥']
slot1 = slots[random.randint(0, 1)]
slotOutput = '| :{}: |\n'.format(slot1)
ok = discord.Embed(title = "RTC slot machine", color = discord.Color(0xFFEC))
ok.add_field(name = "{}\nWon".format(slotOutput), value = f'You won {1.9*amount} coins')
won = discord.Embed(title = "Slots Machine", color = discord.Color(0xFFEC))
won.add_field(name = "{}\nWon".format(slotOutput), value = f'You won {1.9*amount} coins')
if slot1:
await update_bank(ctx.author, 1.9 * amount)
await ctx.send(embed = won)
return
The deposit bet command for the agreed bet when user enters !db #hostname 500 for example#
#client.command()
async def db(ctx,member : discord.Member,amount = None):
await open_account(ctx.author)
await open_account(member)
if amount == None:
em = discord.Embed(title=f'❓Please enter an amount you wish to bet❓',color = discord.Color.red())
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
return
bal = await update_bank(ctx.author)
if amount == 'all':
amount = bal[0]
amount = int(amount)
if amount > bal[0]:
em = discord.Embed(title=f'❌You do not have sufficient balance❌',color = discord.Color.red())
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
return
if amount < 0:
em = discord.Embed(title =f'❗Amount must be positive❗',color = discord.Color.red())
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
return
await update_bank(ctx.author,-1*amount,'wallet')
await update_bank(member,amount,'bank')
em = discord.Embed(title=f'⚔{ctx.author.name} sent {amount}M RS3 to {member}', description=f'Please select the game/challenge !coinflip !elements or !yesandno⚔',color = discord.Color.green())
em.timestamp = datetime.datetime.utcnow()
await ctx.send(embed= em)
#Creates account details for member of the channel#
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
users[str(user.id)]["bank"] = 0
with open('bank.json','w') as f:
json.dump(users,f)
return True
#Stores the user wallet amount in the bank.json file#
async def get_bank_data():
with open('bank.json','r') as f:
users = json.load(f)
return users
#Updates the users bank details held within the json file.
async def update_bank(user,change=0,mode = 'wallet'):
users = await get_bank_data()
users[str(user.id)][mode] += change
with open('bank.json','w') as f:
json.dump(users,f)
bal = users[str(user.id)]['wallet'],users[str(user.id)]['bank']
return bal
client.run("'''''")
Im looking for a way to modify the code so it takes the winnings from a specific account by implimenting the account ID or username.
Any ideas?`
#voice.command()
#commands.has_permissions(administrator=True)
async def setup(self, ctx, member: discord.Member = None ):
conn = sqlite3.connect('voice.db')
c = conn.cursor()
guildID = ctx.guild.id
id = ctx.author.id
if ctx.author.id == ctx.guild.owner.id or ctx.author.id == 189887758192476162:
def check(m):
return m.author.id == ctx.author.id
await ctx.channel.send("**You have 60 seconds to answer each question!**")
await ctx.channel.send(f"**Enter the name of the category you wish to create the channels in:(e.g Voice Channels)**")
try:
category = await self.bot.wait_for('message', check=check, timeout = 60.0)
except asyncio.TimeoutError:
await ctx.channel.send('Took too long to answer!')
else:
new_cat = await ctx.guild.create_category_channel(category.content)
await ctx.channel.send('**Enter the name of the voice channel: (e.g Join To Create)**')
try:
channel = await self.bot.wait_for('message', check=check, timeout = 60.0)
except asyncio.TimeoutError:
await ctx.channel.send('Took too long to answer!')
else:
try:
channel = await ctx.guild.create_voice_channel(channel.content, category=new_cat)
c.execute("SELECT * FROM guild WHERE guildID = ? AND ownerID=?", (guildID, id))
voice=c.fetchone()
if voice is None:
c.execute ("INSERT INTO guild VALUES (?, ?, ?, ?)",(guildID,id,channel.id,new_cat.id))
else:
c.execute ("UPDATE guild SET guildID = ?, ownerID = ?, voiceChannelID = ?, voiceCategoryID = ? WHERE guildID = ?",(guildID,id,channel.id,new_cat.id, guildID))
await ctx.channel.send("**You are all setup and ready to go!**")
except:
await ctx.channel.send("You didn't enter the names properly.\nUse `.voice setup` again!")
else:
await ctx.channel.send(f"{ctx.author.mention} only the owner of the server can setup the bot!")
conn.commit()
conn.close()
Spacing is all correct. It give me the error stated in the title and does not tell me what line the error is on. If anyone could offer some feedback that would be amazing. I just don't know what "id" it could be talking about.
I'm pretty sure it's the ctx.guild.owner.id, in which case is not a proper way to retrieve the guild owner
If you want to find the guild's owner id you should enable intents and use ctx.guild.owner_id from here
#client.command(aliases=["lb"])
async def leaderboardie(ctx, x=1):
users = await get_bank_data()
leader_board = {}
total = []
for user in users:
name = int(user)
total_amount = users[user]["wallet"] + users[user]["bank"]
leader_board[total_amount] = name
total.append(total_amount)
total = sorted(total, reverse=True)
em = discord.Embed(title=f"Top {x} Richest People",
description="This is decided on the basis of raw money in the bank and wallet", color=discord.Color(0xfa43ee))
index = 1
for amt in total:
id_ = leader_board[amt]
member = client.get_user(id_)
name = member.name
em.add_field(name=f"{index}. {name}", value=f"{amt}", inline=False)
if index == x:
break
else:
index += 1
await ctx.send(embed=em)
Error i keep getting:
Command raised an exception: AttributeError: 'NoneType' object has no attribute 'name'
It's basically about a leaderboard based on users wallets, but every time i get this error for some reason, if you know the solution tell me.
If you are doing client.get_user(_id), you need to turn on the server members gateway intent in the developer portal. If you do not want to turn on this intent, you can use:
await client.fetch_user(id)
So I tried to make a filtering system, when the warning is less than 3, it works fine until it reaches 4 which means (the ban time) it triggers the mute tho. Here is the code
#commands.Cog.listener()
async def on_message(self, message):
if not message.author.bot:
if not message.author.guild_permissions.manage_messages:
for b in ignored:
if b in message.content.lower():
return
else:
self.cur.execute(f"SELECT text FROM badwords WHERE guild_id = {message.guild.id}")
result = self.cur.fetchall()
bword = [x[0] for x in result]
if any(b in bword for b in message.content.lower().split(" ")):
self.cur.execute(f"SELECT onoff from mutedet WHERE guild_id = {message.guild.id}")
result3 = self.cur.fetchone()
if result3 is not None:
self.cur.execute(f"SELECT role FROM mute WHERE guild_id = {message.guild.id}")
mutedet = self.cur.fetchone()
if mutedet is not None:
self.cur.execute(f"SELECT warn FROM warning WHERE guild_id = {message.guild.id} and user_id = {message.author.id}")
result2 = self.cur.fetchone()
if result2 is None:
role = discord.utils.get(message.author.guild.roles, id=int(mutedet[0]))
sql = f"INSERT INTO warning(guild_id, user_id, warn) VALUES(?,?,?)"
val = (message.guild.id, message.author.id, 1)
self.cur.execute(sql, val)
self.db.commit()
await message.channel.purge(limit=1)
await message.author.send(f"Hey {message.author.mention} you are muted for 10 Minutes, keep doing this will result on getting banned.")
await message.channel.send(f"Hey {message.author.mention}, That word isn't allowed here!")
await message.author.add_roles(role)
await asyncio.sleep(600)
await message.author.remove_roles(role)
await message.author.send("You are unmuted, If you keep doing this you'll be banned!")
elif result2 is not None:
self.cur.execute(f"SELECT warn FROM warning WHERE guild_id = {message.guild.id} and user_id = {message.author.id}")
warnamount = self.cur.fetchone()
role = discord.utils.get(message.author.guild.roles, id=int(mutedet[0]))
wcount = int(warnamount[0])
if wcount >= 3:
self.cur.execute(f"DELETE FROM warning WHERE guild_id = {message.guild.id} and user_id = {message.author.id}")
self.db.commit()
await message.author.send("You have been banned, because of 3 Violates in a row!")
await message.author.ban(reason="3 Violates in a row!")
else:
self.cur.execute(f"SELECT warn FROM warning WHERE guild_id = {message.guild.id} and user_id = {message.author.id}")
warnings = self.cur.fetchone()
warns = int(warnings[0])
sql = f"UPDATE warning SET warn = ? WHERE guild_id = ? and user_id = ?"
val = (warns + 1, message.guild.id, message.author.id)
self.cur.execute(sql, val)
self.db.commit()
await message.channel.purge(limit=1)
await message.author.send(f"Hey {message.author.mention} you are muted for 10 Minutes, keep doing this will result on getting banned.")
await message.channel.send(f"Hey {message.author.mention}, That word isn't allowed here!")
await message.author.add_roles(role)
await asyncio.sleep(600)
await message.author.remove_roles(role)
await message.author.send("You are unmuted, If you keep doing this you'll be banned!")
After the message author got banned, somehow it adds into db as 1 again :/
Any suggestion of better codes logic please?
That function is very large you should refract it to the smaller more abstract version.
Like I think you are testing message for containing bad words you can create a function for it which checks for bad words and return true or false.
You can wrap database operations in function which will be more meaningful and easier to write and reason about.
Separate your database logic from code wrap it into a function
The reason why you're getting muted message again is that you are deleting warning after it reaches 3 and when he sends message back as a warning for users has been deleted result2 is None again and this loop continues.
A possible solution can be to use a table which includes banned members once warning exceeds you can put the user into that table.
guys so I'm working on a Filter that removes swear words. My problem is I'm getting a 'NoneType' object is not subscriptable error. Could anyone explain why and how to fix it? I know that is error is costed by getMutedValue = curs.fetchone()[0] but if I would remove the [0] its wouldn't work.
#client.event
async def on_message(message):
curs.execute('SELECT muted FROM user WHERE userID = (%s)', (message.author.id,))
getMutedValue = curs.fetchone()[0]
curs.execute('SELECT word FROM filter')
getWord = curs.fetchone()
curs.execute('SELECT immunity FROM user WHERE userID = (%s)', (message.author.id,))
getImmunityValue = curs.fetchone()[0]
if getMutedValue == 1:
muted = message.author.mention + ' You are currently muted!'
await message.channel.send(muted)
await message.delete()
if getImmunityValue == 0:
for word in getWord:
if getMutedValue == 0:
if message.content.count(word) > 0:
channel = client.get_channel(729267888539828255)
id = message.author.id
curs.execute('SELECT username FROM user WHERE userID = (%s)', (id,))
getUsername = curs.fetchone()[0]
curs.execute(f'UPDATE user SET warning = +1 WHERE userID = {id}')
db.commit()
curs.execute('SELECT warning FROM user WHERE userID = (%s)', (id,))
getWarning = curs.fetchone()[0]
await message.delete()
await message.channel.send(f'{message.author.mention} Please do not use an swear words. If you continue you will get punished!')
Embed = discord.Embed(
title=f'{getWarning}x Warning from {getUsername}',
color=discord.Colour.red(),
timestamp=datetime.utcnow()
)
Embed.add_field(name='Blacklist Wort:', value=word, inline=False)
Embed.add_field(name='Channel-ID:', value=message.channel.id, inline=False)
Embed.add_field(name='Channel:', value=message.channel, inline=False)
await channel.send(embed=Embed)
await client.process_commands(message)
The fetchone() method can return None if there are no rows to fetch. (Documentation.) What the should the program do next? In the case where you're checking if a user is muted, the most sensible thing is probably to assume that they aren't muted.
For example:
row = curs.fetchone()
if row is not None:
getMutedValue = row[0]
else:
getMutedValue = 0
In the case where you get None back, you have a fallback value, 0. If you get a value back, then you use that value.