Discord Bot

lecturer: 乘一

~基本介紹與實作

Discord Bot是什麼?

其實就是Discord上的Robot

為什麼需要Discord Bot?

有沒有想要每天一份問候?

有沒有想要在Discord裡聽音樂?

有沒有想要在Discord中玩RPG?

主要還是因為它很好玩

我絕對沒有在推銷

那麼 Discord Bot

將會成為你的好選擇!!!

各種Bot

音樂機器人

管理機器人

抓寶機器人

當然還有各種不好說功能機器人

為什麼要自己寫一個Bot?

都有那麼多強大的Bot了,幹嘛自己寫一個?

  1. 針對自己討厭的用戶
  2. 在別人裝弱的時候膜拜他
  3. 幫自己刷存在感
  4. 讓別人覺得你很厲害
  5. 還有更多功能等你寫出來~

因為可以客製化自己的需求!

本次使用之開發環境

事前準備

創建一個機器人

創建一個機器人

創建一個機器人

獲得TOKEN

創建一個機器人

獲得TOKEN

TOKEN很重要!!! TOKEN很重要!!! TOKEN很重要!!!

下一次點進網站的時候TOKEN會消失

截圖或存到一個安全的地方

不要外流到github之類的網站

不然你的bot會被discord停用

創建一個機器人

打開intents

把機器人加進你的伺服器

把機器人加進你的伺服器

  1. 勾BOT

  2. 勾Administrator

  3. 連到生出來的連結

選擇你要加進的伺服器

基本架構

Bot基本架構

import discord    #導入 Discord.py
from discord.ext import commands #導入 commands 雖然目前不會用到
import os    #導入os模組

intents = discord.Intents.all()
bot = commands.Bot(command_prefix='你想要的指令前綴', intents = intents) 
#透過bot與dicord連結,並設定command的前綴(但還不會用到)

@bot.event #這是裝飾器
async def on_ready(): #當機器人完成啟動時
    print('目前登入身份:', bot.user)
    
try:
    bot.run('機器人TOKEN') #就是你剛剛拿到的TOKEN
except:
    os.system("kill 1") #修正程式錯誤(repl會莫名其妙出錯)

Bot基本架構

import discord    #導入 Discord.py
from discord.ext import commands #導入 commands 雖然目前不會用到
import os    #導入os模組

intents = discord.Intents.all()
bot = commands.Bot(command_prefix='你想要的指令前綴', intents = intents) 
#透過bot與dicord連結,並設定command的前綴(但還不會用到)

@bot.event #這是裝飾器
async def on_ready(): #當機器人完成啟動時
    print('目前登入身份:', bot.user)
    
try:
    bot.run('機器人TOKEN') #就是你剛剛拿到的TOKEN
except:
    os.system("kill 1") #修正程式錯誤(repl會莫名其妙出錯)

Event

Event

#當...的時候要做甚麼->event!

@bot.event #裝飾器
async def function_name(parameters): 
  #async 異步協程
  ...

訊息偵測與回答

讓機器人說話

@bot.event
async def on_message(msg): #當偵測到訊息
    if msg.author == bot.user:  #避免無限循環
        return
    if msg.content.startswith("say"):  #偵測msg的開頭
        tmp = msg.content.split(" ", 1)  #將msg切開
        if len(tmp)==1:  #如果長度只有1,代表後面沒東西
            await msg.channel.send("Pardon me?")
        else:
            await msg.channel.send(tmp[1])

當機器人被mention

import asyncio

@bot.event
async def on_message(message): 
	if bot.user.mentioned_in(message): #當Bot被提及
  		delmsg = await message.channel.send(message.author.mention+"幹嘛啦!?") 
        #將訊息存入delmsg方便之後刪除
		await asyncio.sleep(3) #停止3秒
		await delmsg.delete() #刪除訊息
		await message.channel.send(message.author.name+"對不起我不該這麼兇\n")

成員加入與離開

使用機器人來打招呼

@bot.event
async def on_member_join(member): #當有成員加入
        print(f'{member}join!')
        joinchannel = bot.get_channel("channel ID") #獲得特定頻道ID
        await joinchannel.send(member.mention+' 歡迎加入!') #在特定頻道發言
@bot.event
async def on_member_remove(member): #當有成員離開
        print(f'{member}leave~')
        leavechannel=bot.get_channel("channel ID")
        await leavechannel.send(member.mention+'再見!')

或是驅逐他們

當然也可以弄得炫一點

Event

Command

Command

@bot.event
async def on_message(msg):
	await bot.process_commands(msg)
	#解決on_message 與 command 衝突的問題

@bot.command()
async def command_name(ctx): 
	#ctx上下文
	#包含各種訊息,如:發送者、頻道...
	#...

Ping Pong

@bot.command()
async def ping(ctx):
    await ctx.send(f'{round(bot.latency*1000, 2)}ms')
    #bot.latency 機器人延遲

Command

其他的command自己想~

我懶得備課

發揮創意自己製造各式各樣的command吧!

Cog

Cog 是啥?

Bot.py

on_message

on_member

ping

Cog 是啥?

Bot.py

on_message

on_member

ping

Event.py

cmd.py

Cog 是啥?

Bot.py

on_message

on_member

ping

Event.py

cmd.py

Cog 是啥?

Bot.py

on_message

on_member

ping

Event.py

cmd.py

load

Cog

先分開再說

Cog

Command

#原本
import discord 
from discord.ext import commands 

@bot.command()
async def ping(ctx):
  await ctx.send(f'{round(self.bot.latency*1000, 2)}ms')

Command

#改成cog
import discord 
from discord.ext import commands 

class Cmd(commands.Cog): #繼承commands.Cog
  def __init__(self, bot):
    self.bot = bot
  @commands.command() #記得改
  async def ping(self, ctx): #記得加self
    await ctx.send(f'{round(self.bot.latency*1000, 2)}ms')

async def setup(bot):
  await bot.add_cog(Cmd(bot))

Event

#原本event
import discord  #導入 Discord.py
from discord.ext import commands
import asyncio

@bot.event
async def on_message(msg):  #當偵測到訊息
    if msg.author == bot.user:  #避免無限循環
        return
    if msg.content.startswith("say"):  #偵測msg的開頭
        await msg.channel.send("hello")

Event

#改成cog
import discord 
from discord.ext import commands
import asyncio

class Event(commands.Cog): #繼承commands.Cog
    def __init__(self, bot):
        self.bot = bot
    @commands.Cog.listener() #改
    async def on_message(self, msg): #記得加self
        if msg.author == self.bot.user:  #避免無限循環
            return
        if msg.content.startswith("say"):  #偵測msg的開頭
            await msg.channel.send("hello!")

async def setup(bot):
    await bot.add_cog(Event(bot))

Main

import discord  #導入 Discord.py
from discord.ext import commands 
import os  #導入os模組
import asyncio

intents = discord.Intents.all()
bot = commands.Bot(command_prefix='(', intents=intents)

@bot.event  #這是裝飾器
async def on_ready():  #當機器人完成啟動時
    print('目前登入身份:', bot.user)

@bot.command()
async def load(ctx, ext):
    await bot.load_extension(f'cogs.{ext}')
    await ctx.send(f'{ext} loaded successfully.')

@bot.command()
async def unload(ctx, ext):
    await bot.unload_extension(f'cogs.{ext}')
    await ctx.send(f'{ext} unloaded successfully.')

@bot.command()
async def reload(ctx, ext):
    await bot.reload_extension(f'cogs.{ext}')
    await ctx.send(f'{ext} reloaded successfully.')

async def load_extensions(): #一開始要把所有cog載入
    for filename in os.listdir("./cogs"):
        if filename.endswith(".py"): #偵測有py的檔案
            await bot.load_extension(f"cogs.{filename[:-3]}") #去除.py

async def main():
    async with bot:
        await load_extensions()
        await bot.start(os.getenv("TOKEN"))

if __name__ == "__main__": #如果跑的是這個py
    try:
        asyncio.run(main())  #就是你剛剛拿到的TOKEN
    except:
        os.system("kill 1")  #修正程式錯誤(repl會莫名其妙出錯)

Discord Bot還能做什麼?

還可以結合

  • 爬蟲
  • 後端處理
  • 遊戲設計

然後做出一隻強大但沒什麼用的機器人

e.g.

import requests
from bs4 import BeautifulSoup
@bot.event
async def on_ready():
    channel = bot.get_channel(***********)
    url = "**********"
    html = requests.get(url)
    soup = BeautifulSoup(html.text, "html.parser")
    results = soup.find_all("img", class_="post-item-img", limit=5)
    image_links = list(result["src"] for result in results)
    for link in image_links:
        await channel.send(link)    
    await asyncio.sleep(24*60*60)

THE END

是不是很有趣呢?

Made with Slides.com