Помогите пж, у меня возникла проблема я написанием бота для дискорда на python
Объясните пж что делать т.к. я находил подобные проблемы с ответами но там про какую-то суету в коде говорилось, но ни решения и никакого внятного ответа не было. задал вопрос в дс мне сказали: "установи intents гайдов в инете полно" я еле нашёл такой гайд, я всё сделал как в видео, это только усугубило ситуацию и явно это не является решением проблемы
import discord
from discord.ext import commands
import sqlite3
from config import settings
client = commands.Bot(command_prefix = settings['PREFIX'])
client.remove_command('help')
connection = sqlite3.connect('server.db')
cursor = connection.cursor()
@client.event
async def on_ready():
print('бот {0.user} запущен!'.format(client))
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
name TEXT,
id INT,
cash BIGINT,
rep INT,
lvl INT
)""")
for guild in client.guilds:
for member in guild.members:
if cursor.execute(f"SELECT id FROM users WHERE id ={member.id}").fetchone() is None:
cursor.execute(f"INSERT INTO users VALUES ('{member}',{member.id}, 0, 0, 1)")
else:
pass
connection.commit()
@client.event
async def on_member_join(member):
if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
cursor.execute(f"INSERT INTO users VALUES ('{member}',{member.id}, 0, 0, 1")
connection.commit()
else:
pass
@client.command()
async def balance(ctx, member : discord.Member = None):
if member is None:
await ctx.send(embed = discord.Embed(
description = f"""Баланс **{ctx.author}** составляет **{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]}**"""
))
else:
await ctx.send(embed = discord.Embed(
description = f"""Баланс **{member}** составляет **{cursor.execute("SELECT cash FROM users WHERE id = {}".format(member.id)).fetchone()[0]}**"""
))
client.run(settings['TOKEN'])
Ошибка:
бот Ахмет#0014 запущен!
Ignoring exception in command balance:
Traceback (most recent call last):
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\admin\Desktop\дс серв\bot.py", line 48, in balance
description = f"""Баланс **{ctx.author}** составляет **{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]}**"""
TypeError: 'NoneType' object is not subscriptable
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: 'NoneType' object is not subscriptable
Ответы (1 шт):
Рефракторинг
- Убираем все
else: passони не нужны. - Упрощаем
balance:
@client.command()
async def balance(ctx, member: discord.Member = None):
if member is None:
member = ctx.author
amount = cursor.execute("SELECT cash FROM users WHERE id = {}".format(member.id)).fetchone()[0]
await ctx.send(embed=discord.Embed(
description=f"""Баланс **{member}** составляет **{amount}**"""
))
- Выносим одинаковый функционал, в данном случае мы при инициализации и при заходе пользователя на сервер добавляем его в бд, если его в неё нет, также можно вынсти функциоонал получения пользователя по id и добавление пользователя, давайте же сделаем такие функции:
def select_by_id(id):
return cursor.execute(
"SELECT * FROM users WHERE id = ?", (id,))
def add_member(member):
cursor.execute(
"INSERT INTO users VALUES ('?',?, 0, 0, 1)",
(member, member.id))
def try_to_add_member(member):
if select_by_id(member.id).fetchone() is None:
add_member(member)
return True
return False
- Избавляемся от возможной атаки с использованием SQL-инъекции:
Заменяем всё форматирование дляexecuteна безопасный механизм:
cursor.execute(f"SELECT id FROM users WHERE id ={member.id}")
->
cursor.execute("SELECT id FROM users WHERE id =?", (member.id,)) - Форматируем код
Получилось это
import sqlite3
import discord
from config import settings
from discord.ext import commands
client = commands.Bot(command_prefix=settings['PREFIX'])
client.remove_command('help')
connection = sqlite3.connect('server.db')
cursor = connection.cursor()
def select_by_id(id):
return cursor.execute(
"SELECT * FROM users WHERE id = ?", (id,))
def add_member(member):
cursor.execute(
"INSERT INTO users VALUES ('?',?, 0, 0, 1)",
(member, member.id))
def try_to_add_member(member):
if select_by_id(member.id).fetchone() is None:
add_member(member)
return True
return False
@client.event
async def on_ready():
print('бот {0.user} запущен!'.format(client))
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
name TEXT,
id INT,
cash BIGINT,
rep INT,
lvl INT
)""")
for guild in client.guilds:
for member in guild.members:
try_to_add_member(member)
connection.commit()
@client.event
async def on_member_join(member):
if try_to_add_member(member):
connection.commit()
@client.command()
async def balance(ctx, member=None):
if member is None:
member = ctx.author
amount = select_by_id(member.id).fetchone()["cash"]
await ctx.send(embed=discord.Embed(
description=f"""Баланс **{member}** составляет **{amount}**"""
))
client.run(settings['TOKEN'])
Ошибка
происходит в функцие balance на строке, где мы пытаемся получить amount, т.к. fetchone() возвращает None, и после этого пытается получить доступ к пермоу элеменнту None (None[0]), а т.к. None это не последовательность, то и первого элемента не существует.
Вернёмся к fetchone(), почему эта функция возвращает None?
А потому, что ваш запрос не нашёл ни одной строки с данными параметрами, в данном случае - с данным id.
Что нам надо сделать - обработать такой случай: (ещё по-хорошему бы разобраться, почему возникала такая ошибка, в бд ли проблема или, может, в запросах, а может ещё в чём)
@client.command()
async def balance(ctx, member=None):
if member is None:
member = ctx.author
row = select_by_id(member.id).fetchone()
if row is None:
print("Неизвестный пользователь, добавляем")
add_member(member)
row = select_by_id(member.id).fetchone() # не оптимально, зато понятно
await ctx.send(embed=discord.Embed(
description=f"""Баланс **{member}** составляет **{row["cash"]}**"""
))
Dicord.py
Вам стоит знать, что разработка этого пакета прекращена из-за радикальных изменений, которые вносит Discord, он ожидает, чтобы все боты перешли на новые Слэш-команды к апрелю 2022, и вам стоит этим обеспокоиться, т.к. Dicord.py, почти наверняка не будет работать к этому времени.
Вот оригинальный "пост" от того, кто начал, поддерживал и теперь закрыл Dicord.py