本文有整理在部落格裡。
裡面還有其他奇怪的文章,有空可以來看看喔。
如果你的機器人功能多到一個程度,把全部的程式碼全部塞在一個文件裡顯然不是好辦法。
不但看起來雜亂,也難以維護,就算只是其中一個功能出問題也必須要把整個bot關掉。
這時候就可以使用Cogs的架構來寫,
可以將commands和listener等東西分堆塞在各自文件裡並方便我們裝卸。
照官方文件的說法,比較重要的有這幾點:
每個cogs都是commands.Cog
的子類別
每個command要前加@commands.command()
每個listener要前加@commands.Cog.listener()
Cogs可以用Bot.add_cog()
來註冊
Cogs可以用Bot.remove_cog()
來卸載
通常會跟Extension功能配合
當然單純這樣條列出來是看不懂的,底下來看實例。
其檔案架構通常會長下面這樣
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指令後就能看到結構了。
像這邊unload掉touch後可以發現輸t他也沒反應了,輸help也看不見了。
而load回來的話可以發現指令有反應了,help中也看的到了。
前述的的程式結構較簡單可能沒什麼感覺,但要是程式複雜到如下圖能夠先unload一塊調整完後再load回去還是挺方便的。