跳到主要内容

模块与 require

写完的代码不能全堆在一个文件里。Lua 用 require 加载模块,把公共代码抽出来复用。卷娘插件里你几乎天天见 local jn = require("jn")——这就是加载卷娘 SDK 模块。

require 怎么用

require("模块名") 会加载并执行指定模块文件,返回它的返回值:

local jn = require("jn")

require 做的事:

  1. package.path 里按名字找 .lua 文件
  2. 执行该文件
  3. 若有返回值,返回它;否则返回 true
  4. 只加载一次,之后连同表一起缓存,重复 require 拿到同一个模块

写一个自己的模块

一个模块文件其实就是一个返回表的 Lua 文件。新建 utils.lua

-- utils.lua
local M = {}

function M.contains(tbl, value)
for _, v in ipairs(tbl) do
if v == value then return true end
end
return false
end

function M.pick_random(tbl)
return tbl[math.random(#tbl)]
end

return M

main.lua 里加载使用:

-- main.lua
local utils = require("utils")

print(utils.contains({ 1, 2, 3 }, 2)) -- true

卷娘的 SDK 模块:jn

卷娘把整套插件 API 封装进了 jn 模块,你的插件用它拿所有功能:

local jn = require("jn")

jn.log.info("插件启动") -- 日志
jn.json.encode({ a = 1 }) -- JSON 序列化
jn.onebot11.send_group_msg(gid, "hi") -- 发群消息
jn.cache.set("key", value, 60) -- Redis 缓存
jn.database.query("SELECT 1") -- 数据库查询

jn 模块里的字段其实就是 Go 注入的全局表(见 插件开发指南 的 SDK 对照表):

SDK 字段全局表说明
jn.loglog日志
jn.jsonjsonJSON
jn.onebot11onebot11OneBot11 协议
jn.httphttpHTTP 请求
jn.databasedatabase数据库
jn.cachecacheRedis 缓存
jn.t2it2i文生图
jn.sandboxsandbox代码沙箱
jn.agentagentAgent 操作接口
jn.llmllmLLM 调用
jn.filefile插件目录内文件读写
jn.command命令注册

模块的好处:复用 + 隔离

真实插件会把"词库/配置/工具函数"抽成单独模块或用局部表管理。看 redrock_group_manager 的思路——把词库处理逻辑抽成独立文件,main.lua 只负责流程:

-- words.lua(示意)
local M = {}

function M.load_from_files(paths)
local set = {}
for _, path in ipairs(paths) do
local content = jn.file.read(path)
for line in content:gmatch("[^\r\n]+") do
set[line] = true
end
end
return set
end

function M.contains(set, word)
return set[word] == true
end

return M
-- main.lua(示意)
local words = require("words")

local black = words.load_from_files({ "words/black.txt" })
if words.contains(black, msg) then
-- 触发惩罚
end

package.path:模块去哪找

requirepackage.path 里的路径模板找文件。卷娘启动时会给插件追加 sdk/?.lua,所以 require("jn") 能找到 data/pluggins/sdk/jn.lua

你也可以在插件里看到/修改查找路径:

print(package.path)
-- 追加一个目录:
package.path = package.path .. ";/path/to/modules/?.lua"

本章小结

  • require("模块名") 执行并缓存模块文件,返回表的写法最常见
  • 模块文件 = 一个 return M 的表
  • 卷娘的 jn 就是 SDK 模块,封装了全部插件 API
  • 用模块把词库、工具、配置抽出来,main.lua 保持简洁

下一步:常见坑与最佳实践