Пишем своего первого Discord бота [discord.py]

Сегодня мы сделаем такой функционал:
Выдача роли при заходе на сервер, выдача роли по реакции
Бан, очистка сообщений
Поработаем с базой данных
Затронем API.

Так-же прикреплю полностью рабочий код в конце данной статьи.

База

Думаю как установить python вы разберетесь.
Прописываем в консольку:

Код Python:

python3 -m pip install -U discord.py




Импортируем все нужные нам для данного гайда модули, а так-же задаем нужные нам интенты.

Код Python:

import discord
import asyncio
import json
import requests
from discord.ext import commands

intents = discord.Intents.default()
intents.members = True

bot = commands.Bot(command_prefix="!", intents=intents) # вместо ! можно подставь любой префикс.

@bot.event
async def on_ready():
    print("Bots Guide")
    print(f'Logged in as \033[1m\033[31m{bot.user}\033[0m')

async def send_msg(channel, text):
    channel = bot.get_channel(channel)
    await channel.send(text)

bot.run('ваштокен')

Но где мне взять токен и включить интент?
Заходим сюда > discord.com/developers/applications/
Тыкаем по стрелочкам.

Дальше нам нужно немного пролистать вниз и нажать воть сюда

Чтобы узнать токен жмем сюда

И сразу вставляем его вместо ваштокен.

С начальной подготовкой мы справились и переходим к следующему шагу.

Next Level – Код бота:

Начнём мы с самого простого – команды для модерации сервера.
Сделаем очистку сообщений по заданному количеству, бан, а так-же роли по клику на реакцию.

Лично я буду добавлять ко всем данным командам логирование в определенный канал, однако это совсем не обязательно.
Начнем с очистки сообщений.

Код Python:

@bot.command(pass_context=True)
@commands.has_permissions(administrator=True) # проверка на права администрирования сервером
async def clear(ctx, limit: int): # задаем параметр команды limit который является целым числом 
        logs = bot.get_channel(974312499690233896); # вставляем айди канала с логами
        channel = ctx.message.channel # определяем канал для удаления сообщений (там где была отправлена команда)
        await ctx.message.delete() # удаляем сообщение содержащее команду
        await ctx.channel.purge(limit=limit) # очищаем limit последних сообщений
        embed=discord.Embed(title=f"Было удалено {limit} сообщений.", color=0xd36969) #задаем название эмбеда, цвет полосочки
        embed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5181/5181185.png') # вставляем кортиночку
        embed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url) # футер с тем, кто выполнил команду
        await ctx.send(embed=embed) # отправляем эмбед в канал где было удаление
        logembed=discord.Embed(title=f"В чате {channel} удалено {limit} сообщений.", color=0x0B729D) # тот же эмбед только в логи.
        logembed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5181/5181185.png')
        logembed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)
        await logs.send(embed=logembed) # отправляем эмбед в логи
@clear.error
async def clear_error(ctx, error):
    if isinstance(error, commands.MissingPermissions): # если недостаточно прав (нет админки):
        await ctx.message.delete() # удаляем сообщение содержащее команду
        embed=discord.Embed(title="У вас недостаточно прав.", color=0xd36969) # эмбед
        await ctx.send(embed=embed) # отправляем эмбед

А теперь разберемся и с баном.

Сделаем так-же выдачу роли при входе на сервер.

Код Python:

@bot.event
async def on_member_join(member):
    guild = bot.get_guild(idservera) # вместо idservera - айди вашего сервера (ПКМ на сервер в списке, Копировать айди)
    role = discord.utils.get(guild.roles, name="названиеРоли")
    await member.add_roles(role)

А так-же сделаем выдачу ролей по реакциям ведь это так круто!

Код Python:

# начало клик-ролей
@bot.event
async def on_raw_reaction_add(payload):
    ourMessageID = 975132259147456623 # айди сообщения (сначала создаем его командой !react, а потом копируем его айди и вписываем сюда)

    if ourMessageID == payload.message_id:
        member = payload.member # определяем юзера
        guild = member.guild # определяем сервер

        emoji = payload.emoji.name # эмоджи при нажатии на которое выдается роль
        if emoji == '': # само эмоджи
            role = discord.utils.get(guild.roles, name="・Lounge") # определяем роль которую будем выдавать
            await member.add_roles(role) # выдаем рольку

@bot.event
async def on_raw_reaction_remove(payload):
    ourMessageID = 975132259147456623 # айди сообщения (сначала создаем его командой !react, а потом копируем его айди и вписываем сюда)

    if ourMessageID == payload.message_id:
        guild = await(bot.fetch_guild(payload.guild_id))
        emoji = payload.emoji.name # эмоджи при нажатии на которое выдается роль
        if emoji == '': # само эмоджи
            role = discord.utils.get(guild.roles, name="・Lounge") # определяем роль которую будем выдавать

            member = await(guild.fetch_member(payload.user_id))
            if member is not None: # проверяем есть ли он на сервере
                await member.remove_roles(role) # забираем рольку
            else:
                print('not found')

@bot.command()
async def react(ctx):
    channel = bot.get_channel(938448067357728798) # определяем канал, куда будет отправлено сообщение с эмбедом и реакциями
    embed=discord.Embed(title="Заголовок эмбеда", description="""Описание какое-то.""", color=0x5e7abd) # сам эмбед
    embed.set_thumbnail(url="https://cdn-icons-png.flaticon.com/512/1545/1545324.png") # кортиночка
    embed.set_footer(text="ggdt.ru") # футер
    mojj = await channel.send(embed=embed)
    await mojj.add_reaction('') # отправляем эмбед + добавляем реакцию

#конец клик-ролей

Ну и бан сделаем.

Код Python:

@bot.command()
@commands.has_permissions(administrator=True) # проверка на права администрирования сервером
async def ban(ctx, member: discord.Member, reason=None): # определяем пользователя и причину
        await ctx.message.delete() # удаляем сообщение содержащее команду
        await member.ban(reason=reason) # баним с причиной которую указали аргументом
        logs = bot.get_channel(974312499690233896); # вставляем айди канала с логами
        embed=discord.Embed(title=f"Пользователь {member} был забанен.", description=f"Причина блокировки: {reason}", color=0xd36969)
        embed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5426/5426867.png')
        embed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)
        await ctx.send(embed=embed) # отправляем эмбед в канал где была прописана команда
        logembed=discord.Embed(title=f"Пользователь {member} был забанен.", description=f"Указанная причина блокировки: {reason}", color=0x0B729D)
        logembed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5426/5426867.png')
        logembed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)
        await logs.send(embed=logembed) # отправляем эмбед в логи
@ban.error
async def ban_error(ctx, error):
    if isinstance(error, commands.MissingPermissions):
        await ctx.message.delete()
        embed=discord.Embed(title="У вас недостаточно прав.", color=0xd36969)
        await ctx.send(embed=embed)

А так-же чет захотелось сделать отправку эмбедов с discord.club (дабы отправлять эмбеды не залезая в код)

Код Python:

@bot.command()
async def embed(ctx, *, embedhere): # определяем сам эмбед
    await ctx.message.delete() # удаляем сообщение с командой
    embedcontent = json.loads(embedhere)
    embed = discord.Embed.from_dict(embedcontent["embeds"][0]) # достаем эмбед из словаря
    print(embedcontent) #для дебага
    print(embed.to_dict()) #для дебага
    await ctx.send(embed=embed) #отправляем эмбед в чат

Теперь когда вы пропишите “!embed { json embed }” у вас отправится красивенький эмбед.
А теперь немножечко поработаем с БД.

База данных:

Создадим рядом с ботом файлик bd.json.
Теперь добавим туда следующее:

Код Python:

{"bans": 0}

Переходим обратно к нашему боту и пишем функцию, которую будем использовать.

Код Python:

def AddBan(): # функция аддбан
    """Добавит +1 к банам, которые хранятся в bd.json"""
    with open('bd.json', 'r') as f:
        json_data = json.load(f)
        json_data['bans'] += 1 # добавляем 1 к числу
    with open('bd.json', 'w') as f:
        f.write(json.dumps(json_data)) # записываем данные

А теперь просто добавим в конце команды ban эту строку ( после await logs.send ):

Код Python:

AddBan()

Ну и на закуску мы сделаем статистику.

Код Python:

@bot.command()
async def stats(ctx):
    await ctx.message.delete()
    with open('bd.json', 'r') as f:
        json_data = json.load(f)
        awards = json_data["bans"]
        f.close() # читаем bd.json, а конкретно bans.
        
    embed=discord.Embed(title="Общая статистика:", color=0x6098c3) #embed
    embed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/4985/4985595.png')#embed
    embed.add_field(name="Выдано наград:", value=bans, inline=True)# как value мы используем bans из bd.json.
    embed.add_field(name="Что-то еще:", value="0", inline=True)#embed
    embed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)#embed
    await ctx.send(embed=embed)#embed

С БД я вроде закончил.
Ну и закончим нашу статью работой с API.

Api:

Мы будем работать с discord-tracker и проверять кто сидит с юзером в войсе + получать их айдишники.
(работать будет только если это на серверах, на котором есть бот discord трекера.
Useless, просто как пример использования х)

Код Python:

@bot.command()
async def getid(ctx, member: discord.Member): # получаем мембера которого указали в команде
        await ctx.message.delete() # удаляем сообщение с командой
        url_param = f"https://discord-tracker.ru/tracker/get-victim-info/{ctx.member.id}/?format=json"
        cookies = {
           "sessionid":"cookie", # вместо cookie ваш кук
        }
        response = requests.get(url_param, cookies=cookies) # выше задаем куки и ссылку, тут формируем запрос
        result = response.json() # а тут отправляем и получаем json
        result_str = ''
        for i in result['in_voice']['channel']["members"]: # циклично находим всех юзеров с ответа
                usernames = i["name"]
                userids = i['id']
                result_str += f'{usernames} {userids}\n' # выдаем имена и айди
        await ctx.send(f'```{result_str}```') # выдаем готовый ответ

Полный код ниже:

#!/usr/bin/env python
# -*- coding: utf-8 -*- # строка нужна, чтобы не было ошибки Non-UTF-8 code starting with '\xd1' in file ...

import discord
import asyncio
import json
import requests
from discord.ext import commands

intents = discord.Intents.default()
intents.members = True

bot = commands.Bot(command_prefix="!", intents=intents)


@bot.event
async def on_ready():
    print("Lounge Event Local bot started up.")
    print(f'Залогинился как \033[1m\033[31m{bot.user}\033[0m')

async def send_msg(channel, text):
    channel = bot.get_channel(channel)
    await channel.send(text)


def AddBan(): # функция аддбан
    """Добавит +1 к банам, которые хранятся в bd.json"""
    with open('bd.json', 'r') as f:
        json_data = json.load(f)
        json_data['bans'] += 1 # добавляем 1 к числу
    with open('bd.json', 'w') as f:
        f.write(json.dumps(json_data)) # записываем данные

@bot.event
async def on_member_join(member):
	guild = bot.get_guild(idservera) # вместо idservera - айди вашего сервера (ПКМ на сервер в списке, Копировать айди)
	role = discord.utils.get(guild.roles, name="названиеРоли")
	await member.add_roles(role)

# Либо это /\ либо \/ это

# начало клик-ролей
@bot.event
async def on_raw_reaction_add(payload):
    ourMessageID = 975132259147456623 # айди сообщения (сначала создаем его командой !react, а потом копируем его айди и вписываем сюда)

    if ourMessageID == payload.message_id:
    	member = payload.member # определяем юзера
    	guild = member.guild # определяем сервер

    	emoji = payload.emoji.name # эмоджи при нажатии на которое выдается роль
    	if emoji == '?': # само эмоджи
    		role = discord.utils.get(guild.roles, name="・Lounge") # определяем роль которую будем выдавать
    		await member.add_roles(role) # выдаем рольку

@bot.event
async def on_raw_reaction_remove(payload):
    ourMessageID = 975132259147456623 # айди сообщения (сначала создаем его командой !react, а потом копируем его айди и вписываем сюда)

    if ourMessageID == payload.message_id:
    	guild = await(bot.fetch_guild(payload.guild_id))
    	emoji = payload.emoji.name # эмоджи при нажатии на которое выдается роль
    	if emoji == '?': # само эмоджи
    		role = discord.utils.get(guild.roles, name="・Lounge") # определяем роль которую будем выдавать

    		member = await(guild.fetch_member(payload.user_id))
    		if member is not None: # проверяем есть ли он на сервере
    			await member.remove_roles(role) # забираем рольку
    		else:
    			print('not found')

@bot.command()
async def react(ctx):
	channel = bot.get_channel(938448067357728798) # определяем канал, куда будет отправлено сообщение с эмбедом и реакциями
	embed=discord.Embed(title="Заголовок эмбеда", description="""Описание какое-то.""", color=0x5e7abd) # сам эмбед
	embed.set_thumbnail(url="https://cdn-icons-png.flaticon.com/512/1545/1545324.png") # кортиночка
	embed.set_footer(text="ggdt.ru") # футер
	mojj = await channel.send(embed=embed) 
	await mojj.add_reaction('?') # отправляем эмбед + добавляем реакцию
#конец клик-ролей

@bot.command()
async def getid(ctx, member: discord.Member): # получаем мембера которого указали в команде
        await ctx.message.delete() # удаляем сообщение с командой
        url_param = f"https://discord-tracker.ru/tracker/get-victim-info/{ctx.member.id}/?format=json"
        cookies = {
           "sessionid":"cookie", # вместо cookie ваш кук
        }
        response = requests.get(url_param, cookies=cookies) # выше задаем куки и ссылку, тут формируем запрос
        result = response.json() # а тут отправляем и получаем json
        result_str = ''
        for i in result['in_voice']['channel']["members"]: # циклично находим всех юзеров с ответа
                usernames = i["name"]
                userids = i['id']
                result_str += f'{usernames} {userids}\n' # выдаем имена и айди
        await ctx.send(f'```{result_str}```') # выдаем готовый ответ

@bot.command()
async def embed(ctx, *, embedhere): # определяем сам эмбед
	await ctx.message.delete() # удаляем сообщение с командой
	embedcontent = json.loads(embedhere)
	embed = discord.Embed.from_dict(embedcontent["embeds"][0]) # достаем эмбед из словаря
	print(embedcontent) #для дебага
	print(embed.to_dict()) #для дебага
	await ctx.send(embed=embed) #отправляем эмбед в чат

# Команды для модерации сервера.
@bot.command(pass_context=True)
@commands.has_permissions(administrator=True) # проверка на права администрирования сервером
async def clear(ctx, limit: int): # задаем параметр команды limit который является целым числом 
        logs = bot.get_channel(974312499690233896); # вставляем айди канала с логами
        channel = ctx.message.channel # определяем канал для удаления сообщений (там где была отправлена команда)
        await ctx.message.delete() # удаляем сообщение содержащее команду
        await ctx.channel.purge(limit=limit) # очищаем limit последних сообщений
        embed=discord.Embed(title=f"Было удалено {limit} сообщений.", color=0xd36969) #задаем название эмбеда, цвет полосочки
        embed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5181/5181185.png') # вставляем кортиночку
        embed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url) # футер с тем, кто выполнил команду
        await ctx.send(embed=embed) # отправляем эмбед в канал где было удаление
        logembed=discord.Embed(title=f"В чате {channel} удалено {limit} сообщений.", color=0x0B729D) # тот же эмбед только в логи.
        logembed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5181/5181185.png')
        logembed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)
        await logs.send(embed=logembed) # отправляем эмбед в логи
@clear.error
async def clear_error(ctx, error):
    if isinstance(error, commands.MissingPermissions): # если недостаточно прав (нет админки):
        await ctx.message.delete() # удаляем сообщение содержащее команду
        embed=discord.Embed(title="У вас недостаточно прав.", color=0xd36969) # эмбед
        await ctx.send(embed=embed) # отправляем эмбед

@bot.command()
@commands.has_permissions(administrator=True) # проверка на права администрирования сервером
async def ban(ctx, member: discord.Member, reason=None): # определяем пользователя и причину
        await ctx.message.delete() # удаляем сообщение содержащее команду
        await member.ban(reason=reason) # баним с причиной которую указали аргументом
        logs = bot.get_channel(974312499690233896); # вставляем айди канала с логами
        embed=discord.Embed(title=f"Пользователь {member} был забанен.", description=f"Причина блокировки: {reason}", color=0xd36969)
        embed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5426/5426867.png')
        embed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)
        await ctx.send(embed=embed) # отправляем эмбед в канал где была прописана команда
        logembed=discord.Embed(title=f"Пользователь {member} был забанен.", description=f"Указанная причина блокировки: {reason}", color=0x0B729D)
        logembed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/5426/5426867.png')
        logembed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)
        await logs.send(embed=logembed) # отправляем эмбед в логи
        AddBan()
@ban.error
async def ban_error(ctx, error):
    if isinstance(error, commands.MissingPermissions):
        await ctx.message.delete()
        embed=discord.Embed(title="У вас недостаточно прав.", color=0xd36969)
        await ctx.send(embed=embed)

@bot.command()
async def stats(ctx):
	await ctx.message.delete()
	with open('bd.json', 'r') as f:
		json_data = json.load(f)
		awards = json_data["bans"]
		f.close() # читаем bd.json, а конкретно bans.
		
	embed=discord.Embed(title="Общая статистика:", color=0x6098c3) #embed
	embed.set_thumbnail(url='https://cdn-icons-png.flaticon.com/512/4985/4985595.png')#embed
	embed.add_field(name="Выдано наград:", value=bans, inline=True)# как value мы используем bans из bd.json.
	embed.add_field(name="Что-то еще:", value="0", inline=True)#embed
	embed.set_footer(text=f"Выполнено " + ctx.author.name +"#"+ ctx.author.discriminator, icon_url=ctx.author.avatar_url)#embed
	await ctx.send(embed=embed)#embed

bot.run('ваштокен')

2 Comments

  • Я думаю, что Вы ошибаетесь.

    avenue
    Posted 21.10.2022
  • Такой вопрос по поводу роли за клик по эмодзи, как сделать что бы можно было не 1 эмоджи, а несколько, вот я добавил несколько, но выдается только одна, что делать?

    Anonim
    Posted 04.01.2023

Leave a comment

Discord

Наш дискорд сервер

Telegram

Мы в Telegram

AWKA.IO © 2012-2025 Все права защищены. Пользовательское соглашение  |  Контакты  |  О нас | Отказ от ответственности | Полное или частичное копирование материалов сайта без согласования с редакцией запрещено.|

Мы используем cookie, чтобы собирать статистику и делать контент более интересным. Также cookie используются для отображения более релевантной рекламы. Вы можете прочитать подробнее о cookie-файлах и изменить настройки вашего браузера.


Перейти к верхней панели