Bot discord w pythonie – discord.py od podstaw #7

Dzisiaj pokażę jak zrobić chat bota, z wsparciem wielu serwerów

Wybór Api

Jest wiele api na chat boty, ale na potrzeby poradnika skorzystamy z api.pgamerx.com. Aby skorzystać z api musimy się zarejestrować – https://api-info.pgamerx.com/register. Po zarejestrowaniu dostaniemy klucz do api na maila, połączonego z discordem.

Tworzenie bota

importujemy bibliotekę aiohttp i json.

import aiohttp
import json

from discord.ext import commands

Teraz tworzymy instancję bota, zmienną o nazwie bot z prefixem dolara.

bot = commands.Bot(command_prefix="$")

Tworzymy dekorator event i dodajemy w nim funkcję on_guild_join z argumentem guild.

@bot.event
async def on_guild_join(guild):

Teraz trzeba utworzyć plik ai_channel.json, i uzupełnić go następującą treścią

{}

Uwaga, json to nie jest najlepsza opcja na trzymanie ustawień serwera, ale na kilka – maks kilkanaście serwerów jest ok, licz się z tym, że możesz utracić dane z pliku .json.

Otwieramy plik .json w trybie read (r) i ładujemy aktualny kanał, następnie przypisujemy kanał do id naszego serwera jako „Nie ustawiono!”, aby później administrator mógł go ustawić według swojego upodobania.

Następnie dodajemy nasz serwer do „kolekcji” w pliku json.

@bot.event
async def on_guild_join(guild):
    with open("ai_channel.json", "r") as f:
        ai_channel = json.load(f)

    ai_channel[str(guild.id)] = "Nie ustawiono!"

    with open("ai_channel.json", "w") as f:
        json.dump(ai_channel, f)

Teraz tworzymy komendę na zmianę tego kanału

@bot.command(aliases=["set_ai_channel", "sac"])
@commands.has_permissions(administrator=True)
async def setaichannel(ctx, channel: discord.TextChannel):
    with open("ai_channel.json", "r") as f:
        ai_channel = json.load(f)

    ai_channel[str(ctx.guild.id)] = channel.id

    with open("ai_channel.json", "w") as f:
        json.dump(ai_channel, f)
    embed = discord.Embed(
        colour=discord.Colour.green()
    )
    embed.add_field(name="Kanał dla ai", value=f"Ustawiono kanał dla ai jako {channel.mention}")
    await ctx.message.reply(embed=embed, mention_author=False)

Na początku jak możecie zauważyć dodałem alias do komend, co znaczy, że jeśli wpiszemy set_ai_channel lub sac to komenda też się wykona. W kolejnej linijce podałem, że wymagane permisje do wykonania komendy to administrator.

W trzeciej linijce definiujemy komendę, i podajemy argument channel, który jest kanałem tekstowym discorda. Następnie dzieje się to samo co przy evencie on_guild_join, tylko, że kanał zmienia się na ustawiony przez użytkownika.

Teraz musimy stworzyć to na co czekaliśmy, czyli odpowiedź chat bota na wiadomości na danym kanale. Tworzymy dekorator event z funkcją on_message.

@bot.event
async def on_message(message):

Po napisaniu powyższego elementu kodu musimy sprawdzić czy wiadomość jest na kanale przeznaczonym dla chat bota. Sprawdzamy również czy autor wiadomości jest botem, jeśli tak, zwracamy.

    with open("ai_channel.json", "r") as f:
        ai_channel = json.load(f)

    if message.author.bot: return

    if message.channel.id == ai_channel[str(message.guild.id)]:

Teraz musimy wykonać request do api, aby otrzymać wiadomość zwrotną.

        async with aiohttp.ClientSession(headers={"x-api-key": "Wasz klucz"}) as session:
            async with session.get(url='https://api.pgamerx.com/v3/ai/response',
                                   params={"type": "stable", "message": message.content}) as response:
                msg = await response.json()
                await message.reply(msg[0]["message"])
    await bot.process_commands(message)

Pozostaje nam jedynie zostaje uruchomić bota.

bot.run("TOKEN")

Podsumowanie

Bot odpowiada na nasze wiadomości na danym kanale.

Tak prezentuje się finalny kod:

import aiohttp
import json

import discord
from discord.ext import commands


bot = commands.Bot(command_prefix="$")


@bot.event
async def on_ready():
    print(f"Bot jest gotowy!\nZalogowano jako {bot.user}")


@bot.event
async def on_guild_join(guild):
    with open("ai_channel.json", "r") as f:
        ai_channel = json.load(f)

    ai_channel[str(guild.id)] = "Nie ustawiono!"

    with open("ai_channel.json", "w") as f:
        json.dump(ai_channel, f)


@bot.event
async def on_message(message):
    with open("ai_channel.json", "r") as f:
        ai_channel = json.load(f)

    if message.author.bot: return

    if message.channel.id == ai_channel[str(message.guild.id)]:
        async with aiohttp.ClientSession(headers={"x-api-key": "Wasz klucz"}) as session:
            async with session.get(url='https://api.pgamerx.com/v3/ai/response',
                                   params={"type": "stable", "message": message.content}) as response:
                msg = await response.json()
                await message.reply(msg[0]["message"], mention_author=False)
    await bot.process_commands(message)


@bot.command(aliases=["set_ai_channel", "sac"])
@commands.has_permissions(administrator=True)
async def setaichannel(ctx, channel: discord.TextChannel):
    print(channel.id)
    with open("ai_channel.json", "r") as f:
        ai_channel = json.load(f)

    ai_channel[str(ctx.message.guild.id)] = channel.id

    with open("ai_channel.json", "w") as f:
        json.dump(ai_channel, f)

    embed = discord.Embed(
        colour=discord.Colour.green()
    )
    embed.add_field(name="Kanał dla ai", value=f"Ustawiono kanał dla ai jako {channel.mention}")
    await ctx.message.reply(embed=embed, mention_author=False)



bot.run("TOKEN")