本文將同步發布於 Yeecord 部落格 歡迎各位來朝聖ww,轉載等需求請參照我們的 授權說明
還記得剛開始摸索的時候是在 2019 年的樣子,那時候 Google 上壓根沒什麼中文的 Discord 機器人教學,亂翻看到了一篇在講 discord.js 的文章,就此掉入了這個大坑裡面,
後來機器龍在疫情線上上課那時候大爆炸才開始意識到這些嚴重性,每天跟穩定性戰鬥,還好在那時候也有救星的出現,我們最下面的章節將會談到除了 discord.js 還有 其他的選擇。
以下是我踩坑了挺多次總結出來的問題點,看完了再來決定要不要使用 discord.js,或是也可以直接跳去看 我該繼續用 discord.js 嗎?:
人都是有惰性存在的,而使用 discord.js 絕對可以讓你改掉這個壞習慣,我們知道這個套件有許多貼心幫你包好的如 avatarURL
、awaitMessageComponent
函式,好用歸好用,不過遇到 discord.js 大更新時你就得開始忙起來了,
到文章撰寫的時候 discord.js 已經更新到了 v14,我們可以翻閱一下從 v13 更新到 v14、v12 更新到 v13 的文件,看到側邊欄的目錄超過整個頁面的長度,我覺得我還是去躺好好了...
雖然開發團隊在 Discord 伺服器中提及到 v13 版將會繼續支援,並且還沒有訂定該版本的結束週期 EOL (End-of-life),但可以確定的是,這個版本終將會被棄用,還是必須要進行痛苦的轉移過程。
如果你很喜歡 discord.js 並且想要避免每次大更新都要重寫一次,可以將大量使用的函式包一個自己的版本,我們拿 User#avatarURL
來舉個例子:
/**
* @param {import("discord.js").User} user
*/
function avatarUrl(user) {
return user.avatarURL()
}
這樣每當大更新時只需要更改自己包的版本就好了,剩下的時間拿來多打點 APEX 也不過分。
discord.js 完善的快取系統在普通的小量使用上確實是挺方便的,不過在規模越來越成長下,越需要去注意到記憶體的控管,是不是可以努力減少一些不必要的快取,
而 discord.js 的快取在預設都是無法更動的,雖然有提供了 Options#makeCache
的選項,不過在文檔中說明到 GuildManager
、ChannelManager
等核心的功能還是不能被覆寫,像是頻道、身分組及表情符號是最占用記憶體的前幾名,這樣還是令人堪憂。
幸好有人發現了這個問題並製作出 discord.js-light 套件,可以直接覆蓋掉幾乎所有的 Manager 設定,不過因為還是第三方軟體,並不是 discord.js 自帶功能,最好在使用之前注意會不會讓程式崩壞。
我自己有發現了一個神奇但是挺好用的解法,可以直接使用 JavaScript 神奇的 ProtoType 特性,
舉個例子:若你發現你真的不會使用到 ChannelManager#cache
裡的東西,先將 bot.channels
的 set
函式清空,需要用到時使用 ChannelManager#cache
的原型 Map
來執行 set
的工作,
詳細的使用方式及程式碼可以翻閱我們的 原文
當機器人成長到一定的大小後,如何架構將是一個重要的課題,架構層面我們先從如何做解耦 (decouple) 開始,可以把它簡單的理解成兩個元件要如何做拆解,詳細的架構說明可以參考 Day 23: 元件原則 — 耦合性 by JC。
Discord 機器人通常可以拆解為 Gateway 和 Discord 溝通或是接收 Discord 的事件,REST API Proxy 執行發送訊息等操作,而到我最後使用 v13 版本時,所有功能還是都包在一起的,可能他們有在嘗試做一些改變不過我不太確定。
緊耦合對維護來說非常困難,機器人在上線時會依照伺服器數量來分配分片 (Sharding) 的數量,每個分片上線都要先等待五秒的冷卻時間,若每次更新需要重開時,都需要經過一次這樣的上線流程,
而造成的下線時間 (Downtime) 十幾分鐘可是對穩定性和可靠性非常大的致命傷,可以看我們 Google 搜尋結果都可以被洗成這樣了...
在我們部落格的 原文 中將會提及到你該怎麼面對這些變革,以及有什麼實際執行的辦法,歡迎繼續過來朝聖