Discord бот с экономикой с sqlite

от автора

Привет, Хабр!

Хотел поделиться опытом, как я писал бота c экономикой для discord сервера с использованием sqlite и другой мелочи.

Подготовительный этап

Создание бота

Итак, перед тем, как написать бота, нам нужно его создать и получить токен:

  1. Перейти на сайт для разработчиков
  2. Нажать на кнопку «New Application» и назвать бота
  3. Получить токен бота, войдя в вашего бота и найдя в списке «Settings» вкладку «Bot»

Необходимые модули

Как-никак мы пишем на python, а не на ASM, поэтому нам будут необходимы некоторые модули

$ pip install discord.py #само api для работы с ботом

$ pip install tabulate #небольшой модуль для красивых таблиц

Этап написания

Импорт модулей

Импортировать модули также просто, как и написать одну страницу на HTML+CSS.

import sqlite3 #модуль sqlite import discord #модуль discord api from discord.ext import commands #необходимый класс для обработки команд from tabulate import tabulate #удобный модуль для рисования таблиц import json #используется только для обработки инвентаря, но ему можно найти и другое применение 

Подключение к sqlite

Здесь нет ничего сложного. Просто после импорта прописываем следующее:

conn = sqlite3.connect("Discord.db") # или :memory: cursor = conn.cursor() 

Подготовка базы данных

В базе данных будет 2 таблицы shop и users.

CREATE TABLE "shop" ( 	"id"	INT, 	"type"	TEXT, 	"name"	TEXT, 	"cost"	INT ) 

CREATE TABLE "users" ( 	"id"	INT, 	"nickname"	TEXT, 	"mention"	TEXT, 	"money"	INT, 	"rep_rank"	TEXT, 	"inventory"	TEXT, 	"lvl"	INT, 	"xp"	INT ) 

Подготовка к написанию логики бота

Создаем переменную bot.

bot = commands.Bot(command_prefix="_")#в строчке command_prefix можно указать любые знак, букву, слово, словосочетания и т.д.

В конце всего кода мы пишем метод, который запускает нашего бота.

bot.run("Здесь токен, который вы получили на этапе создания бота")

Теперь начнем писать нашего бота.

bot = commands.Bot(command_prefix="_") #Здесь будет логика вашего бота bot.run("Здесь токен, который вы получили на этапе создания бота") 

Дальше пишем событие on_ready(), отвечающее за готовность бота.

@bot.event async def on_ready():     print("Bot Has been runned")#сообщение о готовности     for guild in bot.guilds:#т.к. бот для одного сервера, то и цикл выводит один сервер         print(guild.id)#вывод id сервера         serv=guild#без понятия зачем это         for member in guild.members:#цикл, обрабатывающий список участников             cursor.execute(f"SELECT id FROM users where id={member.id}")#проверка, существует ли участник в БД             if cursor.fetchone()==None:#Если не существует                 cursor.execute(f"INSERT INTO users VALUES ({member.id}, '{member.name}', '<@{member.id}>', 50000, 'S','[]',0,0)")#вводит все данные об участнике в БД             else:#если существует                 pass             conn.commit()#применение изменений в БД 

После этого стоит, чтобы лишний раз не перезапускать бота, написать метод on_member_join()

@bot.event async def on_member_join(member):     cursor.execute(f"SELECT id FROM users where id={member.id}")#все также, существует ли участник в БД     if cursor.fetchone()==None:#Если не существует         cursor.execute(f"INSERT INTO users VALUES ({member.id}, '{member.name}', '<@{member.id}>', 50000, 'S','[]',0,0)")#вводит все данные об участнике в БД     else:#Если существует         pass     conn.commit()#применение изменений в БД 

Если бот у нас экономический, значит должна быть валюта, ее заработок и ее трата. Заработок можно организовать с помощью experience системы.

@bot.event async def on_message(message):     if len(message.content) > 10:#за каждое сообщение длиной > 10 символов...         for row in cursor.execute(f"SELECT xp,lvl,money FROM users where id={message.author.id}"):             expi=row[0]+random.randint(5, 40)#к опыту добавляется случайное число             cursor.execute(f'UPDATE users SET xp={expi} where id={message.author.id}')             lvch=expi/(row[1]*1000)             print(int(lvch))             lv=int(lvch)             if row[1] < lv:#если текущий уровень меньше уровня, который был рассчитан формулой выше,...                 await message.channel.send(f'Новый уровень!')#то появляется уведомление...                 bal=1000*lv                 cursor.execute(f'UPDATE users SET lvl={lv},money={bal} where id={message.author.id}')#и участник получает деньги     await bot.process_commands(message)#Далее это будет необходимо для ctx команд     conn.commit()#применение изменений в БД 

Одну из главных частей мы написали. Осталось написать команды по типу аккаунт, магазин и т.д. Думаю дальше интуитивно понятно.

@bot.command() async def account(ctx): #команда _account (где "_", ваш префикс указаный в начале)     table=[["nickname","money","lvl","xp"]]     for row in cursor.execute(f"SELECT nickname,money,lvl,xp FROM users where id={ctx.author.id}"):         table.append([row[0],row[1],row[2],row[3]])         await ctx.send(f">\n{tabulate(table)}")  @bot.command() async def inventory(ctx):#команда _inventory (где "_", ваш префикс указаный в начале)      counter=0     for row in cursor.execute(f"SELECT inventory FROM users where id={ctx.author.id}"):         data=json.loads(row[0])         table=[["id","type","name"]]         for row in data:             prt=row             for row in cursor.execute(f"SELECT id,type,name FROM shop where id={prt}"):                 counter+=1                 table.append([row[0],row[1],row[2]])                                  if counter==len(data):                     await ctx.send(f'>\n{tabulate(table)}')   @bot.command() async def shop(ctx):#команда _shop (где "_", ваш префикс указаный в начале)     counter=0     table=[["id","type","name","cost"]]     for row in cursor.execute(f"SELECT id,type,name,cost FROM shop"):         counter+=1         table.append([row[0],row[1],row[2],row[3]])         if counter==4:             await ctx.send(f'>\n{tabulate(table)}') 

Если есть магазин, значит можно покупать? Не так-ли?

async def buy(ctx, a: int):     uid=ctx.author.id     await ctx.send('Обработка... Если ответа не последует, указан неверный id предмета [buy {id}]')     for row in cursor.execute(f"SELECT money FROM users where id={uid}"):         money = row[0]         for row in cursor.execute(f"SELECT id,name,cost FROM shop where id={a}"):             cost=row[2]             if money >= cost:#если у вас достаточно денег,то...                 money -=cost                 await ctx.send(f'Вы приобрели "{row[1]}" за {row[2]}')                                  for row in cursor.execute(f"SELECT inventory FROM users where id={uid}"):                     data=json.loads(row[0])                     data.append(a)                     daed=json.dumps(data)                     cursor.execute('UPDATE users SET money=?,inventory = ? where id=?',(money,daed,uid))#добавляет предмет вам в инвентарь                     pass             if money < cost:#иначе сообщает о недостатке                 await ctx.send(f'Недостаточно средств')                 pass     conn.commit()#применение изменений в БД 

Заключение

Вот такой простенький бот у нас получился. Надеюсь это кому-либо поможет.

Я понимаю что в него можно (необходимо) добавить множество функций и фишек, но это голый вариант кода, который могут использовать новички для понимания как работает discord.py, модуль sqlite и встроенные методы python.

Всем спасибо за внимание. До связи!


ссылка на оригинал статьи https://habr.com/ru/post/482290/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *