iT邦幫忙

2022 iThome 鐵人賽

DAY 26
1
Software Development

爬蟲基礎入門與實際應用系列 第 26

DAY26、 Discord bot - Cogs

  • 分享至 

  • xImage
  •  

本文有整理在部落格裡。
裡面還有其他奇怪的文章,有空可以來看看喔。


如果你的機器人功能多到一個程度,把全部的程式碼全部塞在一個文件裡顯然不是好辦法。
不但看起來雜亂,也難以維護,就算只是其中一個功能出問題也必須要把整個bot關掉。
這時候就可以使用Cogs的架構來寫,
可以將commands和listener等東西分堆塞在各自文件裡並方便我們裝卸。

官方文件的說法,比較重要的有這幾點:

  • 每個cogs都是commands.Cog的子類別

  • 每個command要前加@commands.command()

  • 每個listener要前加@commands.Cog.listener()

  • Cogs可以用Bot.add_cog()來註冊

  • Cogs可以用Bot.remove_cog()來卸載

  • 通常會跟Extension功能配合


當然單純這樣條列出來是看不懂的,底下來看實例。
其檔案架構通常會長下面這樣
https://ithelp.ithome.com.tw/upload/images/20221011/20152706EJhEPhiYQA.png
cogs資料夾是拿來放各個cogs的
core資料夾是拿來放一些你cogs可能會常用到的函數。
main.py是拿來運行的檔案,裡面也包含了載入和裝卸cogs的程式碼,會長的類似下面這樣:

from discord.ext import commands
import os

bot = commands.Bot('prefix')

#下面這塊從cogs資料夾中取出所有.py結尾的檔案並用load_extension載入cogs
for filename in os.listdir('./cogs'):
	if filename.endswith('.py'):
		bot.load_extension(f'cogs.{filename[:-3]}') 

@bot.event
async def on_ready():
	print('Test begin...') 
	
#這裡建個指令讓你可以載入Cog
@bot.command()
async def load(ctx, cog_name):
	try:
		bot.load_extension(f'cogs.{cog_name}')
	except:
		await ctx.send('Failed.')
		return
	await ctx.send('load success!')

#這裡建個指令讓你可以卸載Cog
@bot.command()
async def unload(ctx, cog_name):
	try:
		bot.unload_extension(f'cogs.{cog_name}')
	except:
		await ctx.send('Failed.')
		return
	await ctx.send('unload success!')

#這裡建個指令讓你可以重新載入Cog
@bot.command()
async def reload(ctx, cog_name):
	try:
		bot.reload_extension(f'cogs.{cog_name}')
	except:
		await ctx.send('Failed.')
		return
	await ctx.send('reload success!')

if __name__ == "__main__":
	bot.run('TOKEN')


接著在core底下加一個文檔,這裡我叫他init.py

import discord
from discord.ext import commands

class Cog_Extension(commands.Cog):
	def __init__(self, bot):
		self.bot = bot

接著來把一個指令用成cogs。
就拿前天那個请不要随意地触碰我! 十分感谢!來舉例
他原本的程式區塊大概長這樣:

@bot.command(aliases=['touch'])
async def t(message):
	await message.channel.send('请不要随意地触碰我! 十分感谢!')

把他用成cogs的話會需要把它塞進Class並加上我們剛剛寫的東西,所以會長得像這樣

from discord.ext import commands
from core.init import Cog_Extension

class touch(Cog_Extension):        #建議class名稱跟檔案名稱一樣
@commands.command(aliases=['touch'])    
	async def t(self, message):    #記得在參數列最前面加上self
		await message.channel.send('请不要随意地触碰我! 十分感谢!')

記得要import需要的套件

接著在下面加上setup的函數

from discord.ext import commands
from core.init import Cog_Extension

class touch(Cog_Extension):
	@commands.command(aliases=['touch'])
	async def t(self, message):
		await message.channel.send('请不要随意地触碰我! 十分感谢!')

def setup(bot):
	bot.add_cog(touch(bot))
#這裡的bot.add_cog(touch(bot))中的(bot)前面填上你class的名子

這樣運行後給機器人預設的help指令後就能看到結構了。
https://ithelp.ithome.com.tw/upload/images/20221012/20152706dMFbDgmc8p.png

像這邊unload掉touch後可以發現輸t他也沒反應了,輸help也看不見了。
https://ithelp.ithome.com.tw/upload/images/20221012/20152706NNRA2I8xr8.png

而load回來的話可以發現指令有反應了,help中也看的到了。
https://ithelp.ithome.com.tw/upload/images/20221012/20152706uqPycyubVO.png


前述的的程式結構較簡單可能沒什麼感覺,但要是程式複雜到如下圖能夠先unload一塊調整完後再load回去還是挺方便的。
https://ithelp.ithome.com.tw/upload/images/20221012/20152706kGyb4P4XHd.png


上一篇
DAY25、 Discord bot基本指令
下一篇
DAY27、專題三 : yt搜尋機器人 (1)
系列文
爬蟲基礎入門與實際應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言