總覽
腳本是擴充您伺服器的小型 Lua 程式。它們在與機器人完全隔離的 Lua 5.5 沙盒程序中執行。腳本絕不會接觸資料庫、檔案系統或其他伺服器。所有功能都必須經過白名單內的主機 API,並透過 IPC 交還給機器人處理。
沒有載入腳本,就不會有程序存在。
bot:* 與 msg:* 的呼叫由機器人檢查權限,而非由 Lua 檢查。
自動管理、歡迎訊息與客服單一律照常運作。腳本只是加強,並非取代。
當機的腳本會被卸載或隔離,機器人仍會持續運作。
沒有瀏覽器內的編輯器。請在真正的編輯器中撰寫 .lua,再於伺服器的「腳本」頁面上傳。
快速開始
- 1
在本機撰寫 .lua 檔案
使用 VS Code、Neovim 或任何編輯器。 - 2
在本機檢查(選用)
script_runner --check file.lua會輸出check: ok。 - 3
上傳
開啟伺服器的「腳本」頁面,貼上程式碼或上傳 .lua 檔案(最大 64 KiB)。 - 4
試執行
在不執行任何內容的情況下,驗證大小、編碼、位元組碼與禁用 API。 - 5
啟用
等待管理團隊核准該版本,然後按下「啟用」。機器人會在數秒內載入。 - 6
設定記錄頻道
在該頻道接收bot:log輸出與錯誤通知。
本機 CLI
執行器與機器人使用的是同一個執行檔。
- script_runner --check file.lua
不執行的靜態語法/禁用 API 檢查。輸出 'check: ok'。
- script_runner --eval 'code'
在本機沙盒中執行一段程式碼。錯誤會輸出類型與訊息。
- script_runner --self-test
執行沙盒、通訊協定與 socket 的自我測試。
生命週期與審核
腳本有版本管理。版本在您提交時即被凍結,並以其 SHA-256 識別。只有已核准的版本可以啟用,而機器人只會載入已啟用的版本。
- 1
撰寫
在本機使用 VS Code、Neovim 或任何編輯器建立 .lua 檔案。設計上不提供瀏覽器內的編輯器。 - 2
試執行/上傳
在伺服器「腳本」頁面貼上程式碼或上傳 .lua 檔案(≤ 64 KiB,不得為二進位)。試執行會在不執行任何內容的情況下驗證大小、編碼、位元組碼與禁用 API。 - 3
審核
每個新腳本與每個新版本都從待處理開始。管理團隊會在程式碼能夠執行之前,核准或拒絕該確切的程式碼修訂。 - 4
啟用
您啟用已核准的版本。待處理或已拒絕的版本無法啟用。機器人只會載入已啟用的版本。 - 5
執行
機器人會將版本(程式碼 + SHA-256,由執行器驗證)載入隔離的 Lua 5.5 沙盒。事件只會分發給以 bot:on 註冊的處理常式。 - 6
更新/還原
上傳新版本(再次進入待處理),或啟用較舊的已核准版本以還原。KV 儲存內容會保留。 - 7
停用/刪除
停用會立即停止載入,「全部停用」會影響該伺服器所有啟用中的腳本。刪除會移除腳本、其版本、KV 與錯誤。
腳本狀態
會以徽章顯示在每個腳本上。
- 草稿
已建立,但尚無啟用的版本。
- 待處理
等待某些事項(例如首次核准),不會以草稿狀態執行。
- 啟用中
已核准的版本已啟用並由機器人載入。
- 已拒絕
管理團隊已拒絕;腳本不會載入。
- 已停用
被手動停用(由您、管理團隊、「全部停用」或配額移除)— 已卸載。
- 已隔離
因濫用限制(速率暴增、佇列暴增、重複錯誤)而自動關閉。已卸載,需要管理團隊處理。
版本審核
每一次程式碼修訂都必須經過管理團隊審核。
- 待處理
管理團隊尚未決定,無法啟用。
- 已核准
可以啟用。已安裝之商店腳本的新上傳會略過佇列(商店項目的版本已核准過)。
- 已拒絕
管理團隊拒絕了此程式碼修訂。請改為上傳新版本。
配額:每個伺服器免費版可有 2 個啟用中的腳本,進階版為 10 個。若配額縮減,超出部分中最早啟用的腳本會自動停用,並透過腳本記錄頻道通知您。
處理常式與事件
使用 bot:on(event, fn) 註冊處理常式。腳本在載入時會回報其註冊的事件,且只有這些事件會傳送給它。未知的事件名稱會導致載入失敗,且每個腳本對每個事件最多可註冊 8 個處理常式。
bot:on("message_create", function(msg)
if msg.content == "!ping" then
msg:reply("pong")
end
end)類訊息事件(message_*、automod_check)會傳遞帶有方法的訊息物件,請參閱訊息物件。
主機呼叫會讓出執行權:當處理常式等待 bot:kv_get 等呼叫時,同一個腳本不會同時執行第二個事件。新事件會在容量為 32 的佇列中等待,溢出時會丟棄最舊的事件,持續的大量湧入則會讓腳本被隔離。
guild_id 一律會被注入事件內容中。事件只會傳送給以 bot:on 註冊的處理常式。未知的事件名稱會導致載入失敗並出現政策錯誤。沒有 voice_state 事件。
事件內容
每個事件內容都帶有 guild_id。欄位為小寫 snake_case 的資料表。
- message_create
id, guild_id, channel_id, author_id, author, content, attachments, referenced_id
在標籤/自動回覆之前觸發。附件:最多 8 筆項目 { id, filename, size }。沒有回覆參照時,referenced_id 為 0。
- message_update
same as message_create
- message_delete
channel_id, id
- message_delete_bulk
channel_id, ids
ids 是已刪除訊息 ID 的陣列。
- guild_member_add
user_id
機器人帳號會被略過。
- guild_member_remove
user_id
- guild_member_update
user_id
- reaction_add
channel_id, id, author_id, user_id, emoji, emoji_id
機器人的反應會被略過。emoji 為名稱,Unicode 表情符號的 emoji_id 為 0。
- reaction_remove
channel_id, id, author_id, user_id, emoji, emoji_id
- channel_create
id, name, type
- channel_update
id, name, type
- channel_delete
id, name
- role_create
id, name
- role_update
id, name
- role_delete
id, name
- thread_create
id, name
- thread_update
id, name
- thread_delete
id
- invite_create
code, uses
- invite_delete
code
- guild_ban_add
user_id
- guild_ban_remove
user_id
- welcome_before
user_id, username
在原生歡迎訊息之前觸發。僅限非機器人的加入。
- goodbye_before
user_id
在原生告別訊息之前觸發。
- ticket_created
ticket_id, user_id, channel_id
- automod_check
content, channel_id, author_id, id
在原生自動管理之前觸發。msg:escalate() 會刪除處理中的訊息;原生拒絕一律優先;msg:allow() 不會有任何作用。
- webhooks_update
channel_id
- emoji_update
count, ids
ids 上限為 8。
- tick
unix
每 60 秒一次,只會傳送給註冊了 bot:on("tick") 的腳本。unix 為 Unix 時間。
主機 API
這些呼叫會透過 IPC 讓出執行權給機器人。每個腳本的速率限制:每 10 秒 30 次主機呼叫,以及每 10 秒 5 次 Discord 傳送(reply、channel_send、react、edit、delete、pin、escalate、http_get)。member_get 與 guild_get 等快取讀取不會直接存取 Discord。
- bot:log(msg)
寫入腳本記錄頻道與錯誤記錄。計入每 10 秒 30 次呼叫的限制。
- bot:kv_get(key)
回傳儲存的 JSON 值或 nil。鍵:1–64 個字元 [A-Za-z0-9_-]。
- bot:kv_set(key, value)
儲存最多 8 KiB 的 JSON。每個腳本 256 個鍵、每個腳本 1 MiB(進階版 8 MiB)、每個伺服器 8 MiB。
- bot:kv_del(key)
刪除一個鍵。
- bot:kv_keys()
回傳最多 256 個已排序的鍵。
- bot:kv_incr(key, delta?)
遞增已儲存的 JSON 數字,預設增量為 1,增量限制在 ±1,000,000,000。
- bot:db_exec(sql, binds?)
對伺服器腳本資料庫執行一條寫入或結構語句(CREATE TABLE/INDEX、INSERT、UPDATE、DELETE、DROP)。選用的綁定參數:由 nil、boolean、number 或 string 組成的陣列,最多 8 個。回傳 { changes, last_insert_rowid }。配額、忙碌或限制問題會回傳 { error, kind } 而不是拋出錯誤;被禁止的語句則會拋出政策錯誤。
- bot:db_query(sql, binds?)
執行一條 SELECT(可帶綁定參數),最多回傳 50 列,每列都是以欄位名稱為鍵的資料表。請務必使用 LIMIT。失敗時會回傳 { error, kind },因此請檢查 rows.error。
- bot:http_get(url)
僅限 HTTPS GET。主機必須位於伺服器允許清單中。回傳 { status, body, truncated };body 上限為 16 KiB。等待時間不計入 100 ms 的 Lua 實際時間限制。
- bot:channel_send(channel_id, text, embed?)
傳送到本伺服器中機器人可寫入的任何頻道。內容規則與 msg:reply 相同。
- bot:channel_get(channel_id)
快取讀取:{ id, name, type, parent_id }。僅限本伺服器。
- bot:member_get(user_id)
快取讀取:{ id, nick, bot, roles(最多 20 個)}。
- bot:role_get(role_id)
快取讀取:{ id, name, position, color }。
- bot:guild_get()
本伺服器快取:{ id, name, owner_id, member_count }。
- bot:self()
機器人使用者:{ id, username, bot }。
- bot:has_role(user_id, role_id)
快取讀取,回傳 { has: true|false }。
- bot:channels()
伺服器頻道的快取清單(最多 50 個)。
- bot:roles()
伺服器身分組的快取清單(最多 50 個)。
- bot:now()
以秒為單位的 Unix 時間。
- bot:id()
此腳本的 UUID。不會讓出執行權,也不計入速率限制。
- bot:message_get(channel_id, message_id)
從機器人訊息快取讀取(不會透過網路擷取)。
- bot:can_send(channel_id)
回傳 { ok: true|false },表示機器人是否可以在該頻道傳送訊息。
bot:http_get 接受的內容
- 僅限 HTTPS
http:// 網址會被拒絕。不得包含使用者資訊(user:pass@host)。
- 伺服器允許清單
主機必須位於該伺服器的 HTTP 允許清單中(「腳本」頁面,最多 32 個主機),由您自行管理。
- 不允許基礎設施主機
IP 字面值、localhost、*.local 與 *.internal 一律會被拒絕。
- 回應
{ status, body, truncated },body 上限 16 KiB。逾時 3 秒。與每 10 秒 5 次的 Discord 配額共用。
訊息物件
訊息事件會傳遞 msg 資料表以及事件內容欄位。這些方法只作用於處理中的事件訊息,您無法擷取並編輯任意訊息。
各處通用的內容規則:文字 1 至 2000 位元組,最多一個嵌入訊息 { title, description, color },提及只會對事件作者解析,@everyone 與 @here 會被移除。不允許檔案與貼圖。
- msg:reply(text, embed?)
在事件所在頻道回覆。提及只會對事件作者解析;@everyone / @here 會被移除。文字 1–2000 位元組,最多一個嵌入訊息。
- msg:react(emoji)
在事件訊息上新增反應。
- msg:unreact(emoji)
移除腳本自己的反應。
- msg:edit(text, embed?)
編輯處理中的訊息。內容規則與回覆相同。
- msg:delete()
刪除處理中的訊息。
- msg:pin() / msg:unpin()
釘選/取消釘選處理中的訊息。
- msg:escalate()
僅限 automod_check:刪除處理中的訊息(額外動作,有速率限制)。原生自動管理的判定一律優先。
- msg:allow()
僅限 automod_check:將訊息標記為允許。這無法推翻原生的拒絕,實際上只是一個沒有作用的標記。
限制與配額
所有限制都放在機器人與執行器共用的單一設定檔中,並在執行時強制套用,不只是在這裡列出。這些數字是目前的預設值。
- 語言
Lua 5.5,僅限文字區塊(位元組碼會被拒絕)。不提供 io/os.file/require/load/debug/coroutine。
- 運算
每個處理常式約 100 ms 實際時間,10,000,000 個指令(計數掛鉤)。
- 記憶體
每個腳本免費版 2 MB,進階版 8 MB。
- 程式碼大小
64 KiB UTF-8 .lua,不得含 NUL 位元組,不得為位元組碼。
- 主機呼叫
每個腳本每 10 秒 30 次(含 bot:log)。
- Discord 傳送
每個腳本每 10 秒 5 次(reply、channel_send、react/unreact、edit、delete、pin/unpin、escalate、http_get)。10 秒內被拒絕 8 次 → 隔離。
- 處理常式
每個腳本每個事件最多 8 個。未知的事件名稱會在載入時被拒絕。
- 事件佇列
每個腳本深度 32,溢出時丟棄最舊的。10 秒內丟棄 8 次以上 → 隔離。
- HTTP
HTTPS + 伺服器允許清單,逾時 3 秒,body 16 KiB,不允許 IP/localhost/內部主機,不允許使用者資訊。
- KV
鍵 1–64 個字元 [A-Za-z0-9_-],值 ≤ 8 KiB JSON,每個腳本 256 個鍵,每個腳本 1 MiB(進階版 8 MiB),每個伺服器 8 MiB。
- 資料庫
每個伺服器一個 SQLite 檔案,由該伺服器所有腳本共用:1 MiB(進階版 8 MiB),每次呼叫一條語句,SQL ≤ 2 KiB,≤ 8 個綁定參數,≤ 50 列,每條語句 20 ms,64 個資料表與索引。不支援 ATTACH、PRAGMA、交易、觸發器、檢視表或 WITH。伺服器上的每個腳本都能讀取並刪除所有資料表。
- 啟用中的腳本
每個伺服器免費版 2 個,進階版 10 個。超出部分中最早啟用的腳本會自動停用。
- 版本
每個腳本的版本數量不限;每個新版本在管理團隊核准前都處於待審核狀態。
- 提及
僅限事件作者。@everyone / @here 會被移除。不允許檔案與貼圖。
- 隔離
3 次錯誤(逾時/記憶體/政策/執行時)→ 專屬的隔離工作程序(最多 4 個),否則隔離並卸載。
- 錯誤記錄
控制台可查看最近 24 小時,項目於 7 天後清除。
- 禁止項目
不得使用 voice_state、mod_* API(封鎖/踢出/逾時),不得跨伺服器存取,不得存取資料庫/檔案系統,不得營利。
- 自動管理
原生自動管理優先執行,且一律優先於腳本。
驗證
在儲存版本之前,後端會執行靜態檢查。試執行會做同樣的檢查但不儲存。沙盒本身則是第二道防線:被禁止的全域變數在執行時根本不存在。
- 大小/編碼
不得為空,≤ 64 KiB,UTF-8 且不含 NUL 位元組。
- 位元組碼
任何以 Lua 位元組碼簽章開頭的內容都會被拒絕。
- 禁用 API
靜態掃描會拒絕:load(、loadfile、dofile、require(、os.execute、io.open、debug.、string.dump、loadstring、getfenv、setfenv、package.、coroutine.、ffi.、jit.
- 執行時沙盒
即使有內容通過了靜態掃描,沙盒也根本不會提供這些全域變數 — 呼叫會因政策錯誤而失敗。
可用的內建項目:不含檔案存取的標準 Lua 函式庫。string、table、math、tostring、tonumber、type、pairs、ipairs、os.time、os.clock、os.difftime 與 bot。
錯誤與隔離
每個處理常式錯誤都會連同類型一起記錄,並顯示在腳本詳細頁面(最近 24 小時)。項目會在 7 天後清除。
- runtime
處理常式中的 Lua 錯誤(存取 nil、引數錯誤等)。訊息包含 Lua 錯誤文字。
- timeout
處理常式超過 100 ms 的實際時間限制,或 IPC 呼叫逾時(1 秒)。
- memory
腳本超過其記憶體上限。
- policy
腳本嘗試了不被允許的操作:未知事件、處理常式過多、使用被禁止的 API、內容過大。
重複濫用會自動升級處理:3 次錯誤(逾時、記憶體、政策、執行時)會讓腳本移至專屬的隔離工作程序。若持續不當行為,或沒有可用的隔離位置(最多 4 個),腳本就會被隔離:卸載並在控制台中標示。速率暴增(10 秒內有 8 次被拒絕的 Discord 傳送,或 8 次佇列丟棄)會立即隔離。系統會透過腳本記錄頻道或私訊通知您。
營運端:機器人可透過緊急開關在不重新啟動的情況下全域暫停,並且 scripts:updated 訊號會在數秒內重新載入變更的版本。兩者皆為管理團隊的操作。
商店
商店讓您能公開分享腳本,並安裝其他伺服器的腳本。發佈與安裝都會建立副本。安裝商店項目會在您的伺服器中建立一個獨立的腳本,不會與作者的程式碼保持連結。
- 發佈
需要一個含有已核准版本的啟用中腳本、一段說明(10–512 個字元)以及 1–8 個標籤([a-z0-9-],1–24 個字元)。首次發佈前必須先接受一次商店服務條款。
- 安裝
安裝會將商店項目複製到您的伺服器成為獨立腳本(草稿、已預先核准的版本,若名稱已被使用則加上後綴)。不會複製 KV。商店項目上的安裝計數會增加。
- 取消發佈
將項目從商店移除。既有的副本會保留並繼續執行,只是不會再收到更新。
- 禁止營利
在說明或程式碼中出現銷售、付費牆、捐款/加密貨幣連結及類似的營利行為,會在發佈時被拒絕,且可能導致腳本被禁用。
- 檢舉
任何擁有伺服器存取權限的人都可以附上原因檢舉商店項目。管理團隊會看到待處理的檢舉佇列,並在審核後關閉檢舉。
- 限制
商店清單每次查詢最多顯示 50 個項目(搜尋、標籤、依安裝數或最新排序)。安裝時適用一般的伺服器腳本配額。
範例
選擇範例以查看其程式碼。