├── events
├── GroupAddInvite.lua
├── GroupManageSet.lua
├── GroupManageRemove.lua
├── GroupFileUpload.lua
├── GroupAddRequest.lua
├── GroupMemberJoin.lua
├── GroupMemberLeave.lua
├── ReceiveTcp.lua
├── AppEnable.lua
├── MQTT.lua
└── Message.lua
├── require
├── say
│ ├── e.png
│ ├── m.png
│ ├── s.png
│ └── head_cover.png
├── chess
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── a.png
│ ├── b.png
│ ├── bg.png
│ ├── c.png
│ ├── d.png
│ ├── e.png
│ ├── f.png
│ ├── g.png
│ └── box.png
├── apps
│ ├── 95poweron.lua
│ ├── 05deladmin.lua
│ ├── 04addadmin.lua
│ ├── 99common.lua
│ ├── 19sese.lua
│ ├── 15bing.lua
│ ├── 01delall.lua
│ ├── 97code.lua
│ ├── 14hitokoto.lua
│ ├── 16rust.lua
│ ├── 08qqmusic.lua
│ ├── 03list.lua
│ ├── 02del.lua
│ ├── 98robot.lua
│ ├── 09animeSearch.lua
│ ├── 11banPlay.lua
│ ├── 18car.lua
│ ├── 13av.lua
│ ├── 12sign.lua
│ ├── 00add.lua
│ ├── 07air.lua
│ ├── 20say.lua
│ ├── 96minecraft.lua
│ ├── 10chess.lua
│ ├── 17homo.lua
│ └── 06almanac.lua
├── xmlhandler
│ ├── README.md
│ ├── print.lua
│ ├── dom.lua
│ └── tree.lua
├── sese.lua
├── xml2lua.lua
├── strings.lua
├── minecraft.lua
├── cq.lua
└── XmlParser.lua
├── .vscode
└── settings.json
├── sandbox
├── nvm.lua
├── misc.lua
├── head.lua
├── utils.lua
└── bit.lua
├── README.md
├── main.lua
└── LICENSE
/events/GroupAddInvite.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 |
3 | end
4 |
--------------------------------------------------------------------------------
/require/say/e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/say/e.png
--------------------------------------------------------------------------------
/require/say/m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/say/m.png
--------------------------------------------------------------------------------
/require/say/s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/say/s.png
--------------------------------------------------------------------------------
/require/chess/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/1.png
--------------------------------------------------------------------------------
/require/chess/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/2.png
--------------------------------------------------------------------------------
/require/chess/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/3.png
--------------------------------------------------------------------------------
/require/chess/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/4.png
--------------------------------------------------------------------------------
/require/chess/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/5.png
--------------------------------------------------------------------------------
/require/chess/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/6.png
--------------------------------------------------------------------------------
/require/chess/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/7.png
--------------------------------------------------------------------------------
/require/chess/a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/a.png
--------------------------------------------------------------------------------
/require/chess/b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/b.png
--------------------------------------------------------------------------------
/require/chess/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/bg.png
--------------------------------------------------------------------------------
/require/chess/c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/c.png
--------------------------------------------------------------------------------
/require/chess/d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/d.png
--------------------------------------------------------------------------------
/require/chess/e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/e.png
--------------------------------------------------------------------------------
/require/chess/f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/f.png
--------------------------------------------------------------------------------
/require/chess/g.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/g.png
--------------------------------------------------------------------------------
/require/chess/box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/chess/box.png
--------------------------------------------------------------------------------
/require/say/head_cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/HEAD/require/say/head_cover.png
--------------------------------------------------------------------------------
/events/GroupManageSet.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 | cq.sendGroupMsg(data.group,"群成员"..cq.code.at(data.qq).."成为了狗管理!")
3 | end
4 |
--------------------------------------------------------------------------------
/events/GroupManageRemove.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 | cq.sendGroupMsg(data.group,"群成员"..cq.code.at(data.qq).."变回了人类!")
3 | end
4 |
--------------------------------------------------------------------------------
/events/GroupFileUpload.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 | cq.sendGroupMsg(data.group,"用户"..cq.code.at(data.qq).."上传了文件\r\n"..
3 | data.file:ToString())
4 | end
5 |
--------------------------------------------------------------------------------
/events/GroupAddRequest.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 | if data.group == 241464054 then
3 | cq.sendGroupMsg(241464054,cq.code.at(data.qq)..
4 | "\r\n欢迎加入,请在群里发“绑定 自己的玩家id”来绑定账号,以便管理员审核该id的申请")
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Lua.diagnostics.globals": [
3 | "LuaEnvName",
4 | "XmlApi",
5 | "Utils",
6 | "Directory",
7 | "import",
8 | "sys",
9 | "TcpServer",
10 | "TimeSpan",
11 | "CQ",
12 | "Http",
13 | "Log",
14 | "Encoding"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/events/GroupMemberJoin.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 | if data.group == 261037783 then
3 | cq.groupCard(data.group,data.qq,"可能是单推")
4 | return
5 | end
6 | cq.groupCard(data.group,data.qq,"没有名字的笨蛋")
7 | if data.group == 241464054 then
8 | cq.sendGroupMsg(241464054,cq.code.at(data.qq)..
9 | "\r\n欢迎加入,请在群里发“绑定 自己的玩家id”来绑定账号,以便管理员审核该id的申请")
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/sandbox/nvm.lua:
--------------------------------------------------------------------------------
1 | local nvm = {}
2 |
3 | local data = {}
4 |
5 | function nvm.set(a,b)
6 | data[a] = b
7 | end
8 |
9 | function nvm.get(a)
10 | return data[a]
11 | end
12 |
13 | function nvm.sett(a,b,c)
14 | if not data[a] then data[a] = {} end
15 | data[a][b] = c
16 | end
17 |
18 | function nvm.gett(a,b,c)
19 | if not data[a] then data[a] = {} end
20 | return data[a][b]
21 | end
22 |
23 | return nvm
24 |
--------------------------------------------------------------------------------
/require/apps/95poweron.lua:
--------------------------------------------------------------------------------
1 | return {--!addadmin
2 | check = function (data)
3 | return data.msg == "开机" and data.qq == Utils.Setting.AdminQQ
4 | end,
5 | run = function (data,sendMessage)
6 | local last = tonumber(XmlApi.Get("settings","lastOnline"))
7 | if last and os.time() - last > 60 then
8 | sendMessage("开机控制器不在线。。")
9 | return true
10 | end
11 | if Mqtt.Publish(XmlApi.Get("settings","poweronTopic"), XmlApi.Get("settings","poweronPayload"), 0) then
12 | sendMessage("已向你电脑发送开机指令")
13 | else
14 | sendMessage("我发不出去开机指令,你查查啥问题")
15 | end
16 | return true
17 | end,
18 | }
19 |
--------------------------------------------------------------------------------
/require/apps/05deladmin.lua:
--------------------------------------------------------------------------------
1 | return {--!deladmin
2 | check = function (data)
3 | return (data.msg:find("! *deladmin *.+") == 1 or data.msg:find("! *deladmin *.+") == 1) and
4 | data.qq == Utils.Setting.AdminQQ
5 | end,
6 | run = function (data,sendMessage)
7 | local keyWord = data.msg:match("(%d+)")
8 | if keyWord and XmlApi.Get("adminList",keyWord) == "" then
9 | sendMessage(cq.code.at(data.qq).."\r\n狗管理"..keyWord.."已经挂了")
10 | else
11 | XmlApi.Delete("adminList",keyWord)
12 | sendMessage(cq.code.at(data.qq).."\r\n已宰掉狗管理"..keyWord)
13 | end
14 | return true
15 | end,
16 | }
17 |
--------------------------------------------------------------------------------
/require/apps/04addadmin.lua:
--------------------------------------------------------------------------------
1 | return {--!addadmin
2 | check = function (data)
3 | return (data.msg:find("! *addadmin *.+") == 1 or data.msg:find("! *addadmin *.+") == 1) and
4 | data.qq == Utils.Setting.AdminQQ
5 | end,
6 | run = function (data,sendMessage)
7 | local keyWord = data.msg:match("(%d+)")
8 | if keyWord and XmlApi.Get("adminList",keyWord) == "admin" then
9 | sendMessage(cq.code.at(data.qq).."\r\n"..keyWord.."已经是狗管理了")
10 | else
11 | XmlApi.Set("adminList",keyWord,"admin")
12 | sendMessage(cq.code.at(data.qq).."\r\n已添加狗管理"..keyWord)
13 | end
14 | return true
15 | end,
16 | }
17 |
--------------------------------------------------------------------------------
/events/GroupMemberLeave.lua:
--------------------------------------------------------------------------------
1 | return function (data)
2 | if data.group == 261037783 then return end--dd提醒群不提醒这种东西
3 | cq.sendGroupMsg(data.group,tostring(data.qq).."永远地离开了这个世界。。")
4 | if data.group == 241464054 then
5 | local player = XmlApi.Get("bindQq",tostring(data.qq))
6 | if player ~= "" then
7 | TcpServer.Send("lp user "..player.." permission set group.default",true)
8 | TcpServer.Send("lp user "..player.." permission unset group.whitelist",true)
9 | end
10 | XmlApi.Delete("bindStep",tostring(data.qq))
11 | XmlApi.Delete("bindQq",tostring(data.qq))
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/require/apps/99common.lua:
--------------------------------------------------------------------------------
1 | return {--通用回复
2 | check = function ()
3 | return true
4 | end,
5 | run = function (data,sendMessage)
6 | if data.qq == 1000000 then
7 | return true
8 | end
9 | local replyGroup = LuaEnvName ~= "private" and XmlApi.RandomGet(tostring(data.group),data.msg) or ""
10 | local replyCommon = XmlApi.RandomGet("common",data.msg)
11 | if replyGroup == "" and replyCommon ~= "" then
12 | sendMessage(replyCommon)
13 | elseif replyGroup ~= "" and replyCommon == "" then
14 | sendMessage(replyGroup)
15 | elseif replyGroup ~= "" and replyCommon ~= "" then
16 | sendMessage(math.random(1,10)>=5 and replyCommon or replyGroup)
17 | else
18 | return false
19 | end
20 | return true
21 | end
22 | }
23 |
--------------------------------------------------------------------------------
/require/apps/19sese.lua:
--------------------------------------------------------------------------------
1 |
2 | return {--b站av号解析
3 | check = function (data)
4 | return data.msg == "色色开关"
5 | end,
6 | run = function (data,sendMessage)
7 | if LuaEnvName == "private" then return end --私聊不管
8 | if (XmlApi.Get("adminList",tostring(data.qq)) ~= "admin" or LuaEnvName == "private")
9 | and data.qq ~= Utils.Setting.AdminQQ then
10 | sendMessage(cq.code.at(data.qq).."你不是狗管理,想成为狗管理请找我的主人呢")
11 | return true
12 | end
13 | local status = XmlApi.Get("sese",tostring(data.group)) == "on"
14 | if status then
15 | XmlApi.Delete("sese",tostring(data.group))
16 | sendMessage("呼~~主人终于拔出来了呢❤")
17 | else
18 | XmlApi.Set("sese",tostring(data.group),"on")
19 | sendMessage("唔唔……唔❤……主人不要❤")
20 | end
21 | return true
22 | end,
23 | explain = function ()
24 | return "❤色色开关"
25 | end
26 | }
27 |
--------------------------------------------------------------------------------
/require/apps/15bing.lua:
--------------------------------------------------------------------------------
1 | local function getImage()
2 | local s = asyncHttpGet("https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&pid=hp&uhd=1&uhdwidth=3840&uhdheight=2160")
3 | local t,result,error = jsonDecode(s)
4 | if result then
5 | if t.images and t.images[1] and t.images[1].url then
6 | return asyncImage("http://www.bing.com"..t.images[1].url).."\r\n"..t.images[1].copyright
7 | else
8 | return "图片加载失败啦"
9 | end
10 | else
11 | return "数据解析失败啦,错误原因:"..error
12 | end
13 | end
14 |
15 | return {--必应美图
16 | check = function (data)
17 | return data.msg:find("必应") == 1 and (data.msg:find("美图") or data.msg:find("壁纸"))
18 | end,
19 | run = function (data,sendMessage)
20 | sendMessage(cq.code.at(data.qq).."已经开始获取了哦")
21 | sys.taskInit(function ()
22 | sendMessage(getImage())
23 | end)
24 | return true
25 | end,
26 | explain = function ()
27 | return "📷必应壁纸"
28 | end
29 | }
30 |
--------------------------------------------------------------------------------
/require/xmlhandler/README.md:
--------------------------------------------------------------------------------
1 | # XML Handlers
2 | This directory contains a list of handlers used by the XML parser to process a XML producing different results.
3 | There are currently 3 available handlers:
4 |
5 | - tree: generates a lua table from an XML content string (the most common used handler).
6 | - print: generates a simple event trace which outputs messages to the terminal during the XML parsing, usually for debugging purposes.
7 | - dom: generates a DOM-like node tree structure with a single ROOT node parent.
8 |
9 | # Usage
10 | To get a handler instance you must call, for instance, `handler = require("xmlhandler.tree")`.
11 | Then, you have to use one the handler instance when getting an instance of the XML parser using `parser = xml2lua.parser(handler)`.
12 | Notice the module `xml2lua` should have been loaded before using `require("xml2lua")`.
13 | This way, the handler is called internally when the `parser:parse(xml)` function is called.
14 |
15 | Check the documentation on the root directory for complete examples.
--------------------------------------------------------------------------------
/sandbox/misc.lua:
--------------------------------------------------------------------------------
1 | local misc = {}
2 |
3 | function misc.setClock()
4 | print("[提示]本环境不允许设置时间操作")
5 | end
6 |
7 | function misc.getClock()
8 | return os.date("*t")
9 | end
10 |
11 | function misc.getWeek()
12 | local clk = os.date("*t")
13 | return ((clk.wday == 1) and 7 or (clk.wday - 1))
14 | end
15 |
16 | function misc.getCalib()
17 | return true
18 | end
19 |
20 | local sn = "defaultSN"
21 | function misc.setSn(s)
22 | sn = s
23 | end
24 |
25 | function misc.getSn()
26 | return sn
27 | end
28 |
29 | local imei = "861234567890123"
30 | function misc.setImei(i,c)
31 | imei = i
32 | if c and type(c) == "function" then c(true) end
33 | end
34 |
35 | function misc.getImei()
36 | return imei
37 | end
38 |
39 | function misc.getVbatt()
40 | return 4100
41 | end
42 |
43 | function misc.getMuid()
44 | return "default_muid_string"
45 | end
46 |
47 | function misc.openPwm() end
48 | function misc.closePwm() end
49 |
50 | return misc
51 |
--------------------------------------------------------------------------------
/require/apps/01delall.lua:
--------------------------------------------------------------------------------
1 | --删除所有匹配词条
2 |
3 | --去除字符串开头的空格
4 | local function kickSpace(s)
5 | if type(s) ~= "string" then return end
6 | while s:sub(1,1) == " " do
7 | s = s:sub(2)
8 | end
9 | return s
10 | end
11 |
12 | return {--!delall
13 | check = function (data)
14 | return data.msg:find("! *delall *.+") == 1 or data.msg:find("! *delall *.+") == 1
15 | end,
16 | run = function (data,sendMessage)
17 | if (XmlApi.Get("adminList",tostring(data.qq)) ~= "admin" or LuaEnvName == "private")
18 | and data.qq ~= Utils.Setting.AdminQQ then
19 | sendMessage(cq.code.at(data.qq).."你不是狗管理,想成为狗管理请找我的主人呢")
20 | return true
21 | end
22 | local keyWord = data.msg:match("! *delall *(.+)")
23 | if not keyWord then keyWord = data.msg:match("! *delall *(.+)") end
24 | keyWord = kickSpace(keyWord)
25 | XmlApi.Delete(tostring(LuaEnvName == "private" and "common" or data.group),keyWord)
26 | sendMessage(cq.code.at(data.qq).."\r\n🗑️删除完成!\r\n"..
27 | "词条:"..keyWord)
28 | return true
29 | end,
30 | explain = function ()
31 | return "🗑️ !delall关键词"
32 | end
33 | }
34 |
--------------------------------------------------------------------------------
/require/apps/97code.lua:
--------------------------------------------------------------------------------
1 | return {--测试代码
2 | check = function (data)
3 | return data.msg:find("#lua") == 1
4 | end,
5 | run = function (data,sendMessage)
6 | if data.qq == Utils.Setting.AdminQQ then
7 | local oldprint = print--临时更改print操作
8 | print = function (...)
9 | local r = {}
10 | for i=1,select('#', ...) do
11 | table.insert(r,tostring(select(i, ...)))
12 | end
13 | if #r == 0 then
14 | table.insert(r,"nil")
15 | end
16 | sendMessage(table.concat(r," "))
17 | end
18 | local result, info = pcall(function ()
19 | load(CQ.Decode(data.msg:sub(5)))()
20 | end)
21 | print = oldprint--改回来
22 | if result then
23 | sendMessage(cq.code.at(data.qq).."成功运行")
24 | else
25 | sendMessage(cq.code.at(data.qq).."运行失败\r\n"..tostring(info))
26 | end
27 | else
28 | sendMessage(cq.code.at(data.qq).."\r\n"..
29 | CQ.Encode(Utils.RunSandBox(CQ.Decode(data.msg:sub(5)))))
30 | end
31 | return true
32 | end,
33 | explain = function ()
34 | return "📘#lua运行lua代码"
35 | end
36 | }
37 |
--------------------------------------------------------------------------------
/require/apps/14hitokoto.lua:
--------------------------------------------------------------------------------
1 | local function hitokoto(data)
2 | local say = asyncHttpGet("http://v1.hitokoto.cn")
3 | local types = {
4 | a = "Anime - 动画",
5 | b = "Comic – 漫画",
6 | c = "Game – 游戏",
7 | d = "Novel – 小说",
8 | e = "Myself – 原创",
9 | f = "Internet – 来自网络",
10 | g = "Other – 其他",
11 | }
12 | local function getText(s)
13 | if not s then return end
14 | local data = JSON:decode(s)
15 | if not data then return end
16 | local hitokoto,saytype,from
17 | if not pcall(function ()
18 | hitokoto,saytype,from = data.hitokoto, data.type, data.from
19 | end) then
20 | return
21 | end
22 | return hitokoto.."\r\n--"..(from or "未知来源").."\r\n"..(types[saytype] or "未知类别")
23 | end
24 | return getText(say) or cq.code.at(data.qq).."\r\n加载失败啦"
25 | end
26 |
27 |
28 |
29 |
30 | return {--一言
31 | check = function (data)
32 | return data.msg == "一言"
33 | end,
34 | run = function (data,sendMessage)
35 | sys.taskInit(function ()
36 | sendMessage(hitokoto(data))
37 | end)
38 | return true
39 | end,
40 | explain = function ()
41 | return "📑一言"
42 | end
43 | }
44 |
--------------------------------------------------------------------------------
/require/apps/16rust.lua:
--------------------------------------------------------------------------------
1 | return {--测试代码
2 | check = function (data)
3 | return data.msg:find("#rust") == 1
4 | end,
5 | run = function (data,sendMessage)
6 | sendMessage(cq.code.at(data.qq).."代码已提交,正在运行~")
7 | sys.taskInit(function ()
8 | local post = {
9 | version= "stable",
10 | optimize= "0",
11 | code=data.msg:sub(string.len("#rust")+1),
12 | edition= "2018",
13 | }
14 | if not post.code:find("fn main") then
15 | post.code = "fn main() {\r\n"..post.code.."\n}\n"
16 | end
17 | local html = asyncHttpPost("https://play.rust-lang.org/evaluate.json",
18 | jsonEncode(post),30000,nil,"application/json")
19 | local d,result,error = jsonDecode(html)
20 | if result then
21 | if d.error then
22 | sendMessage(cq.code.at(data.qq).."报错了qwq\r\n"..tostring(d.error))
23 | else
24 | sendMessage(cq.code.at(data.qq).."\r\n"..tostring(d.result))
25 | end
26 | else
27 | sendMessage(cq.code.at(data.qq).."代码服务器运行报错qwq")
28 | end
29 | end)
30 | return true
31 | end,
32 | explain = function ()
33 | return "☢️#rust运行rust代码"
34 | end
35 | }
36 |
37 |
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # receiver-meow-lua
2 |
3 | [](https://github.com/chenxuuu/receiver-meow-lua/blob/master/LICENSE)
4 | [](https://github.com/chenxuuu/receiver-meow)
5 | [](https://github.com/chenxuuu/receiver-meow-lua/archive/master.zip)
6 |
7 | 接待喵lua插件的lua脚本仓库
8 |
9 | 这个仓库的代码需要配合lua插件本体食用
10 |
11 | lua插件餐具地址:[https://github.com/chenxuuu/receiver-meow](https://github.com/chenxuuu/receiver-meow)
12 |
13 | # 处理流程
14 |
15 | ## 入口文件
16 |
17 | 代码入口为`main.lua`,进行了如下操作:
18 |
19 | 初始化各项需要用到的接口
20 |
21 | 添加需要`require`文件的所在路径
22 |
23 | 分配各个`Task框架`事件到`events`文件夹下的文件
24 |
25 | ## 定时任务
26 |
27 | 在`events/AppEnable.lua`文件中,声明了多个定时任务,同时使用了timer和task接口
28 |
29 | ## 私聊和群消息功能
30 |
31 | 所有私聊消息与群消息,统一经由`events/Message.lua`文件处理
32 |
33 | 接着,会自动遍历加载`require\apps`下的所有`lua`文件,使每个文件的功能都能正常起作用
34 |
35 | 你可以自行删减`require\apps`的文件以便删减功能,注意匹配顺序按文件名来排序
36 |
37 | ## 注意事项
38 |
39 | 调用C#接口,请参考[Nlua](https://github.com/NLua/NLua/)关于`import`函数的使用说明
40 |
41 | 主虚拟机由Task框架调度,具体的任务、定时器用法请见[LuaTask项目的Readme](https://github.com/chenxuuu/LuaTask-csharp)
42 |
--------------------------------------------------------------------------------
/require/sese.lua:
--------------------------------------------------------------------------------
1 | --不可以色色!
2 | --代码逻辑来源:https://github.com/RimoChan/yinglish
3 |
4 | --分词成table
5 | local function jb(s)
6 | local t = {}
7 | local r = Utils.Jieba(s)
8 | for i = 0, r.Count-1 do
9 | table.insert(t,r[i])
10 | end
11 | return t
12 | end
13 |
14 |
15 | local convert = {
16 | function (s) if s == "," or s == "," then return "……" end end,
17 | function (s) if s == "!" or s == "!" then return "❤" end end,
18 | function (s) if #s > 3 and math.random() < 0.5 then return s:sub(1,3).."……"..s:sub(4) end end,
19 | function (s) return s end,
20 | }
21 |
22 | local function se(s)
23 | local t = jb(s)
24 | local sese = {}
25 | for i=1,#t do
26 | for j=1,#convert do
27 | local cr = convert[j](t[i],n)
28 | if cr then
29 | table.insert(sese,cr)
30 | break
31 | end
32 | end
33 | end
34 | if math.random() < 0.5 then
35 | table.insert(sese,"❤")
36 | end
37 | return table.concat(sese)
38 | end
39 |
40 | return function (s)
41 | s = s:gsub("%[CQ:.-%]",""):gsub("\r",""):split("\n")
42 | local t = {}
43 | for i=1,#s do
44 | table.insert(t,se(s[i]))
45 | end
46 | return table.concat(t,"\r\n")
47 | end
48 |
--------------------------------------------------------------------------------
/require/apps/08qqmusic.lua:
--------------------------------------------------------------------------------
1 | local function qqmusic(message)
2 | if message:find("点歌") == 1 then
3 | local songID = message:gsub("点歌 *","")
4 | if not tonumber(songID) then
5 | local html = asyncHttpGet("https://c.y.qq.com/soso/fcgi-bin/client_search_cp", "?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w="..message:gsub("点歌",""):urlEncode())
6 | local str = html:match("callback%((.+)%)")
7 | local j,r,e = jsonDecode(str)
8 | if r and j.data and j.data.song and j.data.song.list and j.data.song.list[1] then
9 | songID = j.data.song.list[1].id
10 | else
11 | return "机器人爆炸了,原因:"..e
12 | end
13 | end
14 | if songID then
15 | return cq.code.music("qq",songID)
16 | else
17 | return "机器人爆炸了,原因:根本没这首歌"
18 | end
19 | end
20 | end
21 |
22 | return {--点歌
23 | check = function (data)
24 | return data.msg:find("点歌") == 1
25 | end,
26 | run = function (data,sendMessage)
27 | sys.taskInit(function()
28 | sendMessage(qqmusic(data.msg))
29 | end)
30 | return true
31 | end,
32 | explain = function ()
33 | return "🎶点歌 加 qq音乐id或歌名"
34 | end
35 | }
36 |
--------------------------------------------------------------------------------
/require/apps/03list.lua:
--------------------------------------------------------------------------------
1 | --去除字符串开头的空格
2 | local function kickSpace(s)
3 | if type(s) ~= "string" then return end
4 | while s:sub(1,1) == " " do
5 | s = s:sub(2)
6 | end
7 | return s
8 | end
9 |
10 | return {--!list
11 | check = function (data)
12 | return data.msg:find("! *list *.+") == 1 or data.msg:find("! *list *.+") == 1
13 | end,
14 | run = function (data,sendMessage)
15 | local keyWord = data.msg:match("! *list *(.+)")
16 | if not keyWord then keyWord = data.msg:match("! *list *(.+)") end
17 | keyWord = kickSpace(keyWord)
18 |
19 | local gt,pt--消息内容table
20 |
21 | local glist
22 | if LuaEnvName ~= "private" then
23 | glist = XmlApi.GetList(tostring(data.group),keyWord)
24 | gt = {}
25 | for i=0,glist.Count-1 do
26 | table.insert(gt,glist[i])
27 | end
28 | end
29 | local plist = XmlApi.GetList("common",keyWord)
30 | pt = {}
31 | for i=0,plist.Count-1 do
32 | table.insert(pt,plist[i])
33 | end
34 |
35 | sendMessage(cq.code.at(data.qq).."\r\n🗂️当前词条回复如下:\r\n"..
36 | (gt and (table.concat(gt,"\r\n").."\r\n共"..tostring(#gt).."条")).."\r\n"..
37 | "全局词库内容:\r\n"..table.concat(pt,"\r\n").."\r\n共"..tostring(#pt).."条")
38 | return true
39 | end,
40 | explain = function ()
41 | return "🗂️ !list关键词"
42 | end
43 | }
44 |
--------------------------------------------------------------------------------
/require/apps/02del.lua:
--------------------------------------------------------------------------------
1 | --删除第一个匹配词条
2 |
3 | --去除字符串开头的空格
4 | local function kickSpace(s)
5 | if type(s) ~= "string" then return end
6 | while s:sub(1,1) == " " do
7 | s = s:sub(2)
8 | end
9 | return s
10 | end
11 |
12 | return {--!del
13 | check = function (data)
14 | return (data.msg:find("! *del *.+:.+") == 1 or data.msg:find("! *del *.+:.+") == 1)
15 | and not (data.msg:find("! *deladmin *.+") == 1 or data.msg:find("! *deladmin *.+") == 1)
16 | end,
17 | run = function (data,sendMessage)
18 | if (XmlApi.Get("adminList",tostring(data.qq)) ~= "admin" or LuaEnvName == "private")
19 | and data.qq ~= Utils.Setting.AdminQQ then
20 | sendMessage(cq.code.at(data.qq).."你不是狗管理,想成为狗管理请找我的主人呢")
21 | return true
22 | end
23 | local keyWord,answer = data.msg:match("! *del *(.+):(.+)")
24 | if not keyWord then keyWord,answer = data.msg:match("! *del *(.-):(.+)") end
25 | keyWord = kickSpace(keyWord)
26 | answer = kickSpace(answer)
27 | if not keyWord or not answer or keyWord:len() == 0 or answer:len() == 0 then
28 | sendMessage(cq.code.at(data.qq).."格式错误,请检查") return true
29 | end
30 | XmlApi.DeleteOne(tostring(LuaEnvName == "private" and "common" or data.group),keyWord,answer)
31 | sendMessage(cq.code.at(data.qq).."\r\n🗑️删除完成!\r\n"..
32 | "词条:"..keyWord.."\r\n"..
33 | "回答:"..answer)
34 | return true
35 | end,
36 | explain = function ()
37 | return "🗑️ !del关键词:回答"
38 | end
39 | }
40 |
--------------------------------------------------------------------------------
/require/apps/98robot.lua:
--------------------------------------------------------------------------------
1 | local robot_qq = cq.loginInfo().qq
2 | return {--@触发QQ智能机器人
3 | check = function (data)
4 | return data.msg:find("%[CQ:at,qq="..robot_qq.."%]") and
5 | data.msg:gsub("%[CQ:.-%]",""):len() > 2
6 | end,
7 | run = function (data,sendMessage)
8 | sys.taskInit(function ()
9 | local text = data.msg:gsub("%[CQ:.-%]",""):gsub(" ","")--过滤掉特殊内容的消息
10 | local appid = XmlApi.Get("settings","qqai_APPID")--应用信息
11 | local appkey = XmlApi.Get("settings","qqai_APPKEY")
12 | --原始请求数据
13 | local rawBody = "app_id="..appid.."&"..
14 | "nonce_str="..getRandomString(20).."&"..
15 | "question="..text:urlEncode().."&"..
16 | "session="..tostring(data.qq).."&"..
17 | "time_stamp="..tostring(os.time())
18 | local sign = Utils.MD5Encrypt(rawBody.."&app_key="..appkey)
19 | rawBody = rawBody.."&sign="..sign:upper()
20 | local http = asyncHttpGet("https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat?"..rawBody)
21 | local d,r = jsonDecode(http)
22 | if r then
23 | if d and d.ret ~= 0 then return end--没结果
24 | if d and d.data and d.data.answer then
25 | sendMessage(cq.code.at(data.qq)..d.data.answer)
26 | return true
27 | end
28 | end
29 | end)
30 | end,
31 | explain = function ()--功能解释,返回为字符串,若无需显示解释,返回nil即可
32 | return "👾 @机器人,进行聊天"
33 | end
34 | }
35 |
--------------------------------------------------------------------------------
/require/apps/09animeSearch.lua:
--------------------------------------------------------------------------------
1 | --查动画
2 | --api key请用自己的
3 | local key = XmlApi.Get("settings","trace.moe")
4 |
5 | local function animeSearch(msg)
6 | local img = msg:match("%[CQ:image,file=.-,url=(.-)%]")
7 |
8 | if not img then return "未在消息中过滤出图片" end
9 |
10 | print("https://api.trace.moe/search?anilistInfo&token="..key.."&url="..img)
11 | local html = HttpGet("https://api.trace.moe/search?anilistInfo&token="..key.."&url="..img,nil,30000)
12 | if not html or html:len() == 0 then
13 | return "查找失败(网站炸了或图片大小超过了1MB)请稍后再试。"
14 | end
15 | local d,r,i = jsonDecode(html)
16 | if r and d.result and #d.result > 0 then
17 | return "搜索结果:\r\n"..
18 | "动画名:"..d.result[1].anilist.title.native.."("..d.result[1].anilist.title.romaji..")\r\n"..
19 | (d.result[1].anilist.title.english and "英文名:"..d.result[1].anilist.title.english.."\r\n" or "")..
20 | (d.result[1].similarity < 0.86 and "准确度:"..tostring(math.floor(d.result[1].similarity*100)).."%"..
21 | "\r\n(准确度过低,请确保这张图片是完整的、没有裁剪过的动画视频截图)\r\n" or "")..
22 | (d.result[1].episode and "话数:"..tostring(d.result[1].episode).."\r\n" or "")..
23 | "by trace.moe"
24 | else
25 | return "没搜到结果,请换一张完整的、没有裁剪过的动画视频截图"
26 | end
27 | end
28 |
29 |
30 |
31 | return {--查动画
32 | check = function (data)
33 | return data.msg:find("查动画") or data.msg:find("搜动画") or
34 | data.msg:find("查番") or data.msg:find("搜番")
35 | end,
36 | run = function (data,sendMessage)
37 | sendMessage(cq.code.at(data.qq).."查询中。。。")
38 | sendMessage(cq.code.at(data.qq).."\r\n"..animeSearch(data.msg))
39 | return true
40 | end,
41 | explain = function ()
42 | return "🎞️查动画 加 没裁剪过的视频截图"
43 | end
44 | }
45 |
--------------------------------------------------------------------------------
/require/apps/11banPlay.lua:
--------------------------------------------------------------------------------
1 |
2 | local function banPlay(msg,qq,g)
3 |
4 | msg = CQ.Decode(msg)
5 | if LuaEnvName == "private" then
6 | return "私聊抽你🐎的奖呢"
7 | end
8 | local cards = XmlApi.Get("banCard",tostring(qq))
9 | cards = cards == "" and 0 or tonumber(cards) or 0
10 | if msg == "抽奖" then
11 | if math.random() > 0.9 then
12 | local banTime = math.random(1,60)
13 | cq.groupBan(g,qq,banTime*60)
14 | return cq.code.at(qq).."恭喜你抽中了禁言"..tostring(banTime).."分钟"
15 | else
16 | local banCard = math.random(-5,6)
17 | cards = cards + banCard
18 | XmlApi.Set("banCard",tostring(qq),tostring(cards))
19 | return cq.code.at(qq).."恭喜你抽中了"..tostring(banCard).."张禁言卡\r\n"..
20 | "当前禁言卡数量:"..tostring(cards)
21 | end
22 | elseif msg == "禁言卡" then
23 | return cq.code.at(qq).."当前禁言卡数量:"..tostring(cards)
24 | elseif msg:find("%d+") then
25 | if cards <= 0 then
26 | return cq.code.at(qq).."你只有"..tostring(cards).."张禁言卡,无法操作"
27 | end
28 | XmlApi.Set("banCard",tostring(qq),tostring(cards-1))
29 | local v = tonumber(msg:match("(%d+)"))
30 | local banTime = math.random(1,60)
31 | cq.groupBan(g,v,banTime*60)
32 | return cq.code.at(qq).."已将"..tostring(v).."禁言"..tostring(banTime).."分钟"
33 | else
34 | return "未匹配到任何命令"
35 | end
36 | end
37 |
38 | return {--抽奖
39 | check = function (data)
40 | return data.msg == "抽奖" or data.msg:find("禁言") == 1
41 | end,
42 | run = function (data,sendMessage)
43 | sendMessage(banPlay(data.msg,data.qq,data.group))
44 | return true
45 | end,
46 | explain = function ()
47 | return "🔒抽奖/禁言卡"
48 | end
49 | }
50 |
--------------------------------------------------------------------------------
/events/ReceiveTcp.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | 处理收到的tcp消息
3 |
4 | 下面的代码为我当前接待喵逻辑使用的代码,可以重写也可以按自己需求进行更改
5 | 详细请参考readme
6 | ]]
7 |
8 | local mc = require("minecraft")
9 |
10 | local solve = {
11 | l = function (msg)
12 | mc.onlineAdd(msg)
13 | cq.sendGroupMsg(241464054,msg.."上线了")
14 | if XmlApi.Row("bindQq",msg) == "" then--自动撤销没在群里的人的白名单
15 | TcpServer.Send("cmdlp user "..msg.." permission set group.default")
16 | TcpServer.Send("cmdlp user "..msg.." permission unset group.whitelist")
17 | end
18 | end,
19 | d = function (msg)
20 | mc.onlineDel(msg)
21 | cq.sendGroupMsg(241464054,msg.."掉线了")
22 | end,
23 | m = function (msg)
24 | if msg:find("%[主世界%]") or
25 | msg:find("%[旧世界%]") or
26 | msg:find("%[创造界%]") or
27 | msg:find("%[下界%]") or
28 | msg:find("%[末地%]") or
29 | msg:find("%[二周目%]") or
30 | msg:find("%[三周目%]") or
31 | msg:find("%[三周目雪世界%]") or
32 | msg:find("%[四周目%]") or
33 | msg:find("%[四周目雪世界%]") or
34 | msg:find("%[资源世界%]") then
35 | cq.sendGroupMsg(241464054,CQ.Encode(msg))
36 | end
37 | end,
38 | c = function ()
39 | cq.sendGroupMsg(241464054,"服务器已启动完成")
40 | mc.onlineClear()
41 | TcpServer.Send("cmdworld create mine")
42 | sys.taskInit(function()
43 | for i=1,12 do
44 | sys.wait(10000)
45 | TcpServer.Send("cmdworld gamerule set mine keepInventory true")
46 | end
47 | end)
48 | end,
49 | }
50 |
51 |
52 | return function (message)
53 | local data = message:split("|")
54 | for i=1,#data do
55 | data[i] = data[i]:gsub("\\\\","\\"):gsub("\\s","|")
56 | local messageType = data[i]:sub(1,1)
57 | if solve[messageType] then
58 | solve[messageType](data[i]:sub(2))
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/require/apps/18car.lua:
--------------------------------------------------------------------------------
1 |
2 | return {--b站av号解析
3 | check = function (data)
4 | return data.msg:lower():find("验车.+") == 1
5 | end,
6 | run = function (data,sendMessage)
7 | local f,l = data.msg:lower():match("验车 *(%l+)[ -]*(%d+)")
8 | print(f,l)
9 | if f and l then
10 | local html,r,e = HttpGet("http://www."..XmlApi.Get("settings","jav")..".com/cn/vl_searchbyid.php?keyword="..f.."-"..l,nil,10000)
11 | if not html then sendMessage(cq.code.at(data.qq).."没找到") print(html,r,e) return true end
12 | local title = html:match([[
]])
13 | local cover = html:match([[发行日期:.-
(.-) | ]])
15 | local len = html:match([[.-
(.-)]])
16 | if title and cover and time and len then
17 | if cover:find("//") == 1 then cover = cover:sub(3) end
18 | local para = jsonEncode({url=cover})
19 | local su = HttpPost("https://xn--ugt.cc/api/set.php",para)
20 | local j,r = jsonDecode(su)
21 | if r and j then
22 | cover = j.content.url
23 | else
24 | cover = "获取失败"
25 | end
26 | sendMessage(cq.code.at(data.qq)..title.."\r\n官方封面:"..cover.."\r\n发行时间:"..time.."\r\n视频时长:"..len.."分钟")
27 | else
28 | print(title , cover , time , len)
29 | sendMessage(cq.code.at(data.qq).."没找到")
30 | end
31 | else
32 | sendMessage(cq.code.at(data.qq).."番号格式不正确")
33 | end
34 | return true
35 | end,
36 | explain = function ()
37 | return "🚕验车 字母 数字"
38 | end
39 | }
40 |
--------------------------------------------------------------------------------
/require/apps/13av.lua:
--------------------------------------------------------------------------------
1 | local function av(bv)
2 | local bvid = bv:match("bv(%w+)") or bv:match("BV(%w+)")
3 | local html
4 | if bvid then
5 | html = HttpGet("http://api.bilibili.com/x/web-interface/view?bvid="..bvid)
6 | else
7 | local av = bv:match("av(%d+)") or bv:match("AV(%d+)")
8 | html = HttpGet("http://api.bilibili.com/x/web-interface/view?aid="..av)
9 | end
10 | if not html then return "查找失败" end
11 | local j,r,e = jsonDecode(html)
12 | if j.code ~= 0 then return "数据解析失败啦" end
13 | local image = j.data.pic and asyncImage(j.data.pic)
14 | return (image and image.."\r\n" or "")..
15 | "http://www.bilibili.com/video/av"..j.data.aid.."\r\n"..j.data.title..
16 | "\r\n"..j.data.desc:gsub(" ","\r\n")..
17 | "\r\n分区:"..(j.data.tname and j.data.tname or "")
18 | end
19 |
20 | return {--b站av号解析
21 | check = function (data)
22 | if data.msg:find("%[CQ:json,data={.-b23.tv.-%]") then
23 | return true
24 | end
25 | local msg = data.msg:gsub("%[CQ:.-%]",""):lower()--防止匹配到cq码
26 | return msg:find("av%d+") or msg:find("bv%w+") or msg:find("https://b23.tv/")
27 | end,
28 | run = function (data,sendMessage)
29 | local msg = data.msg:gsub("%[CQ:.-%]","")
30 |
31 | if data.msg:find("%[CQ:json,data={.-b23.tv.-%]") then
32 | local url = data.msg:match("b23.tv\\-/(.-)%?")
33 | if url then
34 | msg = "https://b23.tv/"..url
35 | else
36 | sendMessage("关爱弱势群体,少发小程序分享")
37 | return
38 | end
39 | end
40 |
41 | if msg:find("https://b23.tv/") then--短链接解码
42 | msg = msg:match("(https://b23.tv/%w+)")
43 | msg = HttpJump(msg)
44 | end
45 | sendMessage(av(msg))
46 | return true
47 | end,
48 | explain = function ()
49 | return "📺b站视频信息获取"
50 | end
51 | }
52 |
--------------------------------------------------------------------------------
/require/apps/12sign.lua:
--------------------------------------------------------------------------------
1 | local function sign(qq,msg,group)
2 | if msg == "开启签到" and qq == Utils.Setting.AdminQQ then
3 | XmlApi.Delete("settings","sign_open"..tostring(group))
4 | return "已开启群"..tostring(group).."的签到功能"
5 | elseif msg == "关闭签到" then
6 | XmlApi.Set("settings","sign_open"..tostring(group),"close")
7 | return "已关闭群"..tostring(group).."的签到功能"
8 | else
9 | local day = os.date("%Y年%m月%d日")--今天
10 | local signData = XmlApi.Get("sign",tostring(qq))
11 | local data = signData == "" and
12 | {
13 | last = 0,--上次签到时间戳
14 | count = 0,--连签计数
15 | } or jsonDecode(signData)
16 |
17 | if data.last == day then
18 | return "你已经签过到啦"
19 | end
20 |
21 | if data.last == os.date("%Y年%m月%d日",os.time()-3600*24) then
22 | data.count = data.count + 1
23 | else
24 | data.count = 1
25 | end
26 | data.last = day
27 | local j = jsonEncode(data)
28 | XmlApi.Set("sign",tostring(qq),j)
29 |
30 | local cards = XmlApi.Get("banCard",tostring(qq))
31 | cards = cards == "" and 0 or tonumber(cards) or 0
32 | local banCard = math.random(1,10)
33 | cards = cards + banCard
34 | XmlApi.Set("banCard",tostring(qq),tostring(cards+data.count-1))
35 | return "签到成功\r\n"..
36 | "抽中了"..tostring(banCard).."张禁言卡\r\n"..
37 | "附赠"..tostring(data.count-1).."张连签奖励\r\n"..
38 | "当前禁言卡数量:"..tostring(cards)
39 | end
40 | end
41 |
42 | return {--签到
43 | check = function (data)
44 | return ((data.msg == "签到" or data.msg == "关闭签到")
45 | and XmlApi.Get("settings","sign_open"..tostring(data.group)) ~= "close") or
46 | (data.msg == "开启签到" and data.qq ~= Utils.Setting.AdminQQ )
47 | end,
48 | run = function (data,sendMessage)
49 | sendMessage(cq.code.at(data.qq)..sign(data.qq,data.msg,data.group))
50 | return true
51 | end,
52 | explain = function ()
53 | return "📊[开启/关闭]签到"
54 | end
55 | }
56 |
--------------------------------------------------------------------------------
/require/apps/00add.lua:
--------------------------------------------------------------------------------
1 | --添加词条
2 |
3 | --去除字符串开头的空格
4 | local function kickSpace(s)
5 | if type(s) ~= "string" then return end
6 | while s:sub(1,1) == " " do
7 | s = s:sub(2)
8 | end
9 | while s:sub(-1,-1) == " " do
10 | s = s:sub(1,-2)
11 | end
12 | return s
13 | end
14 |
15 | --防止切割到不完整的中括号。。。
16 | local function notRightBrackets(s)
17 | local temp = {}
18 | for i=1,#s do
19 | if s:sub(i,i) == "[" then
20 | table.insert(temp,s:sub(i,i))
21 | elseif s:sub(i,i) == "]" then
22 | if temp[#temp] == "[" then
23 | table.remove(temp,#temp)
24 | else
25 | return true
26 | end
27 | end
28 | end
29 | return #temp ~= 0
30 | end
31 |
32 | return {--!add
33 | check = function (data)--检查函数,拦截则返回true
34 | return (data.msg:find("! *add *.+:.+") == 1 or data.msg:find("! *add *.+:.+") == 1)
35 | and not (data.msg:find("! *addadmin *.+") == 1 or data.msg:find("! *addadmin *.+") == 1)
36 | end,
37 | run = function (data,sendMessage)--匹配后进行运行的函数
38 | if (XmlApi.Get("adminList",tostring(data.qq)) ~= "admin" or LuaEnvName == "private")
39 | and data.qq ~= Utils.Setting.AdminQQ then
40 | sendMessage(cq.code.at(data.qq).."你不是狗管理,想成为狗管理请找我的主人呢")
41 | return true
42 | end
43 | local keyWord,answer = data.msg:match("! *add *(.+):(.+)")
44 | if not keyWord then keyWord,answer = data.msg:match("! *add *(.-):(.+)") end
45 | keyWord = kickSpace(keyWord)
46 | answer = kickSpace(answer)
47 | if not keyWord or not answer or keyWord:len() == 0 or answer:len() == 0 or
48 | notRightBrackets(keyWord) then
49 | sendMessage(cq.code.at(data.qq).."格式错误,请检查") return true
50 | end
51 | XmlApi.Add(tostring(LuaEnvName == "private" and "common" or data.group),keyWord,answer)
52 | sendMessage(cq.code.at(data.qq).."\r\n✅添加完成!\r\n"..
53 | "词条:"..keyWord.."\r\n"..
54 | "回答:"..answer)
55 | return true--返回true表示已被处理
56 | end,
57 | explain = function ()--功能解释,返回为字符串,若无需显示解释,返回nil即可
58 | return "✏️ !add关键词:回答"
59 | end
60 | }
61 |
--------------------------------------------------------------------------------
/events/AppEnable.lua:
--------------------------------------------------------------------------------
1 | --插件启动后调用的文件
2 | --目前仅用来注册各种开机后会运行的东西
3 | --并且当前文件的功能,仅在账号为chenxu自己的测试qq下运行
4 |
5 | return function ()
6 | --防止多次启动
7 | if AppFirstStart then return end
8 | AppFirstStart = true
9 |
10 | --仅限作者的机器人号用这个功能
11 | if cq.loginInfo().qq ~= 751323264 and cq.loginInfo().qq ~= 3617883457 then return end
12 |
13 | --mc服务器定时重启
14 | Log.Debug(StateName,"加载mc服务器定时重启任务")
15 | sys.taskInit(function ()
16 | while true do
17 | local delay
18 | local time = os.date("*t")
19 | local next = os.date("*t",os.time())
20 | if time.hour >=3 then
21 | next = os.date("*t",os.time()+3600*24)
22 | next.hour = 3
23 | next.min = 0
24 | next.sec = 0
25 | delay = os.time(next) - os.time()
26 | else
27 | next.hour = 3
28 | next.min = 0
29 | next.sec = 0
30 | delay = os.time(next) - os.time()
31 | end
32 | Log.Debug(StateName,"mc自动重启,延时"..delay.."秒")
33 | sys.wait(delay * 1000)
34 | Log.Debug(StateName,"mc自动重启,开始执行")
35 |
36 | Log.Debug(StateName,"执行服务器空间定期检查任务")
37 | local c = io.popen("df /")
38 | local ct = c:read("*all")
39 | c:close()
40 | if not ct then return end
41 | local free = tostring(ct:match(" +(%d+) +%d+%%")) // 1024
42 | if free < 1024 * 10 then--空间小于10G
43 | cq.sendGroupMsg(567145439,
44 | cq.code.at(961726194)..
45 | "你的小垃圾服务器空间只有"..tostring(free).."M空间了知道吗?快去清理")
46 | end
47 |
48 | if free > 1024 * 15 then
49 | cq.sendGroupMsg(241464054,
50 | "一分钟后,将自动进行服务器例行重启与资源世界回档,请注意自己身上的物品")
51 | TcpServer.Send("一分钟后,将自动进行服务器例行重启与资源世界回档,请注意自己身上的物品")
52 | sys.wait(60000)
53 | TcpServer.Send("cmdstop")
54 | sys.wait(3600*1000)
55 | TcpServer.Send("cmdworld create mine")
56 | end
57 | end
58 | end)
59 | end
60 |
--------------------------------------------------------------------------------
/events/MQTT.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | 处理MQTT各消息的逻辑
3 |
4 | 下面的代码为我当前接待喵逻辑使用的代码,可以重写也可以按自己需求进行更改
5 | 详细请参考readme
6 | ]]
7 |
8 | --对各个topic进行订阅
9 | local function subscribe()
10 | local topics = {
11 | --"live/"..Utils.Setting.ClientID,
12 | "/8266/test_online",
13 | "/tg/receive",--tg消息
14 | }
15 | for i=1,#topics do
16 | local result = Mqtt.Subscribe(topics[i], 0)
17 | Log.Debug(StateName,"MQTT订阅:"..(result and "成功" or "失败")..","..topics[i])
18 | end
19 | end
20 |
21 | local messageEvent
22 | local robot_qq
23 | local tg_bot = "@xxxxxxbot "
24 | local topicAction = {
25 | ["/8266/test_online"] = function (payload)
26 | XmlApi.Set("settings","lastOnline",tostring(os.time()))
27 | end,
28 | ["/tg/receive"] = function (payload)
29 | --data.msg, data.from
30 | local data = jsonDecode(payload)
31 | local to = data.from
32 | data.qq = 0
33 | data.group = data.from
34 | data.send = function(qq,msg)
35 | local s = jsonEncode({
36 | msg = msg,
37 | to = to
38 | })
39 | Mqtt.Publish("/tg/send", s, 0)
40 | end
41 | cq.code.at = function() return "" end
42 | if not robot_qq then
43 | robot_qq = cq.loginInfo().qq
44 | end
45 | if data.msg:find(tg_bot) then
46 | data.msg = data.msg:gsub(tg_bot,"[CQ:at,qq="..robot_qq.."]")
47 | end
48 | if not messageEvent then
49 | local _,info = pcall(function() messageEvent = require("Message") end)
50 | end
51 | if messageEvent then
52 | messageEvent(data)
53 | end
54 | end,
55 | }
56 | return function (message)
57 | --连接成功,马上订阅
58 | if message.t == "connected" then subscribe() return end
59 |
60 | if message.t == "receive" then
61 | Log.Debug(StateName,"MQTT收到消息:"..message.topic..","..message.payload)
62 | --Mqtt.Publish("luaRobot/pub/"..Utils.Setting.ClientID, "publish test", 0)
63 | if topicAction[message.topic] then
64 | topicAction[message.topic](message.payload)
65 | end
66 |
67 |
68 | end
69 | end
70 |
71 |
--------------------------------------------------------------------------------
/events/Message.lua:
--------------------------------------------------------------------------------
1 | --自动读取apps目录,加载所有功能
2 | local apps = {}
3 | local AppList = Utils.GetFileList(Utils.Path.."lua/require/apps/")
4 |
5 | --按文件名排序
6 | local tempList = {}
7 | for i=0,AppList.Length-1 do
8 | local app = AppList[i]:match("/([^/]-)%.lua")
9 | if app then
10 | table.insert(tempList,app)
11 | end
12 | end
13 | AppList = nil
14 | table.sort(tempList)--排序
15 |
16 | --加载每个文件
17 | for i=1,#tempList do
18 | local t
19 | local _,info = pcall(function() t = require("apps."..tempList[i]) end)
20 | if t then
21 | table.insert(apps,t)
22 | Log.Debug(StateName,LuaEnvName.."加载app:"..tempList[i])
23 | end
24 | end
25 | tempList = nil--释放临时table
26 |
27 | local sese = require("sese")
28 |
29 | return function (data)
30 | --封装一个发送消息接口
31 | --自动判断群聊与私聊
32 | local seseStatus = XmlApi.Get("sese",tostring(data.group)) == "on"--色色开关
33 | local mqttSend = data.send
34 | local function sendMessage(s)
35 | if seseStatus then s = sese(s) end--色色开关
36 | if LuaEnvName == "private" then
37 | cq.sendPrivateMsg(data.qq,s)
38 | elseif LuaEnvName == "MQTT" then
39 | mqttSend(data.qq,s)
40 | else
41 | cq.sendGroupMsg(data.group,s)
42 | end
43 | end
44 |
45 | --帮助列表每页最多显示数量
46 | local maxEachPage = 8
47 | --匹配是否需要获取帮助
48 | if data.msg:lower() == "help" or data.msg == "帮助" or data.msg == "菜单" then
49 | local allApp = {}
50 | for i=1,#apps do
51 | local appExplain = apps[i].explain and apps[i].explain()
52 | if appExplain then
53 | table.insert(allApp, appExplain)
54 | end
55 | end
56 | sendMessage("📃命令帮助\r\n"..
57 | table.concat(allApp, "\r\n").."\r\n"..
58 | "📄开源代码:\r\nhttps://www.chenxublog.com/qqrobot")
59 | return
60 | end
61 |
62 | data = {
63 | qq = data.qq,
64 | group = data.group,
65 | msg = data.msg:gsub("(.-gchatpic_new/)%d-(/.-)","%1123456%2")
66 | }
67 |
68 | --遍历所有功能
69 | for i=1,#apps do
70 | if apps[i].check and apps[i].check(data) then
71 | if apps[i].run(data,sendMessage) then
72 | break
73 | end
74 | end
75 | end
76 | end
77 |
78 |
--------------------------------------------------------------------------------
/require/apps/07air.lua:
--------------------------------------------------------------------------------
1 | --空气质量
2 | --请用自己的token
3 | local token = "737aa093c7d9c16b7c6fdc1b70af2fb02bf01e11"
4 | local function getInfo(id)
5 | local html = asyncHttpGet("http://api.waqi.info/feed/@"..tostring(id).."/","token="..token)
6 | local d,r,e = jsonDecode(html)
7 | if not r then return "加载失败" end
8 | return d.data.city.name.."的空气质量如下:"..
9 | (d.data.aqi and "\r\n空气质量指数:"..d.data.aqi or "")..
10 | (d.data.iaqi.pm25 and "\r\npm2.5:"..d.data.iaqi.pm25.v or "")..
11 | (d.data.iaqi.pm10 and "\r\npm2.5:"..d.data.iaqi.pm10.v or "")..
12 | (d.data.iaqi.co and "\r\npm2.5:"..d.data.iaqi.co.v or "")..
13 | (d.data.iaqi.no2 and "\r\npm2.5:"..d.data.iaqi.no2.v or "")..
14 | (d.data.iaqi.o3 and "\r\npm2.5:"..d.data.iaqi.o3.v or "")..
15 | (d.data.iaqi.so2 and "\r\npm2.5:"..d.data.iaqi.so2.v or "")..
16 | (d.data.attributions[1].name and "\r\n数据来源:"..d.data.attributions[1].name or "")..
17 | (d.data.time.s and "\r\n数据更新时间:"..d.data.time.s or "")
18 | end
19 |
20 | local function search(name)
21 | for i=1,name:len() do
22 | if name:byte(i) > 127 then return "城市名称不能用中文!" end
23 | end
24 | local html = asyncHttpGet("http://api.waqi.info/search/","keyword="..name.."&token="..token)
25 | local d,r,e = jsonDecode(html)
26 | if not r then return "加载失败" end
27 | local result = {}
28 | for i=1,#d.data do
29 | table.insert(result, d.data[i].uid..":"..d.data[i].station.name)
30 | end
31 | return "共找到"..tostring(#result).."个监测站:"..
32 | "\r\n"..table.concat(result,"\r\n")..
33 | "\r\n使用指令“空气质量”加监测站编号查看数据"
34 | end
35 |
36 | local function air(message)
37 | if message == "空气质量" then
38 | return "使用帮助:\r\n发送空气质量加城市英文(拼音),即可查询\r\n如:空气质量harbin"
39 | elseif message:find("空气质量") == 1 then
40 | message = message:gsub("空气质量 *","")
41 | if tonumber(message) then
42 | return getInfo(message)
43 | else
44 | return search(message)
45 | end
46 | end
47 | end
48 |
49 | return {--空气质量
50 | check = function (data)
51 | return data.msg:find("空气质量") == 1
52 | end,
53 | run = function (data,sendMessage)
54 | sys.taskInit(function()--用到了异步http,必须新开个任务
55 | sendMessage(cq.code.at(data.qq).."\r\n"..air(data.msg))
56 | end)
57 | return true
58 | end,
59 | explain = function ()
60 | return "☁️空气质量"
61 | end
62 | }
63 |
--------------------------------------------------------------------------------
/require/apps/20say.lua:
--------------------------------------------------------------------------------
1 | --- 判断文件是否存在
2 | function io.exists(path)
3 | local file = io.open(path, "r")
4 | if file then
5 | io.close(file)
6 | return true
7 | end
8 | return false
9 | end
10 |
11 | local pathHead = Utils.Path.."lua/require/say/"
12 |
13 | local function qsay(q,n,s)
14 | --检查和获取头像
15 | local head_path = pathHead..q..".jpg"
16 | if not io.exists(head_path) then
17 | Utils.HttpDownload("https://q1.qlogo.cn/g","b=qq&nk="..q.."&s=100",10000,"",head_path)
18 | end
19 | --背景布
20 | local height = 159
21 | local tw = math.floor(Utils.GetTextWidth(s,pathHead.."yh.ttf",37))--微软雅黑字体,请自行下载
22 | local width = tw+166+70
23 | local pic = Utils.GetBitmap(width,height)
24 | Utils.PutBlock(pic,0,0,width,height,248, 246, 244)
25 | --放头像
26 | Utils.SetImage(pic,6,6,head_path,62,62)
27 | Utils.SetImage(pic,0,0,pathHead.."head_cover.png",76,77)
28 | --气泡开头
29 | Utils.SetImage(pic,77,42,pathHead.."s.png",35,92)
30 | --气泡中间
31 | local count = 0
32 | local lastx = 111
33 | while count < tw do
34 | if tw - count >= 37 then
35 | Utils.SetImage(pic,lastx,42,pathHead.."m.png",37,92)
36 | count = count + 37
37 | lastx = lastx + 37
38 | else
39 | local w = tw - count
40 | Utils.SetImage(pic,lastx - 37 + w,42,pathHead.."m.png",37,92)
41 | count = count + w
42 | lastx = lastx + w
43 | end
44 | end
45 | --气泡结尾
46 | Utils.SetImage(pic,lastx,42,pathHead.."e.png",25,92)
47 | --字
48 | Utils.PutText(pic,111,67,s,pathHead.."yh.ttf",37,0,0,0)
49 | --名
50 | Utils.PutText(pic,96,13,n,pathHead.."yh.ttf",24,124, 123, 122)
51 | local file = Utils.ImageBase64(pic):match("base64,(.+)")
52 | return cq.code.image("base64://"..file)
53 | end
54 |
55 | local function getName(group,qq)
56 | local info = cq.groupMemberInfo(group,qq)
57 | return info.card ~= "" and info.card or info.nickname
58 | end
59 |
60 | return {--
61 | check = function (data)
62 | return data.msg:find("%[CQ:at,qq=%d+%] */.+") == 1
63 | end,
64 | run = function (data,sendMessage)
65 | local q,s = data.msg:match("%[CQ:at,qq=(%d+)%] */(.+)")
66 | if q and s then
67 | sendMessage(qsay(q,getName(data.group,tonumber(q)),CQ.Decode(s)))
68 | return true
69 | end
70 | end,
71 | explain = function ()
72 | return "🗨at/话,生成聊天截图"
73 | end
74 | }
75 |
--------------------------------------------------------------------------------
/require/xmlhandler/print.lua:
--------------------------------------------------------------------------------
1 | ---@module Handler to generate a simple event trace which
2 | --outputs messages to the terminal during the XML
3 | --parsing, usually for debugging purposes.
4 | --
5 | -- License:
6 | -- ========
7 | --
8 | -- This code is freely distributable under the terms of the [MIT license](LICENSE).
9 | --
10 | --@author Paul Chakravarti (paulc@passtheaardvark.com)
11 | --@author Manoel Campos da Silva Filho
12 | local print = {}
13 |
14 | ---Parses a start tag.
15 | -- @param tag a {name, attrs} table
16 | -- where name is the name of the tag and attrs
17 | -- is a table containing the atributtes of the tag
18 | -- @param s position where the tag starts
19 | -- @param e position where the tag ends
20 | function print:starttag(tag, s, e)
21 | io.write("Start : "..tag.name.."\n")
22 | if tag.attrs then
23 | for k,v in pairs(tag.attrs) do
24 | io.write(string.format(" + %s='%s'\n", k, v))
25 | end
26 | end
27 | end
28 |
29 | ---Parses an end tag.
30 | -- @param tag a {name, attrs} table
31 | -- where name is the name of the tag and attrs
32 | -- is a table containing the atributtes of the tag
33 | -- @param s position where the tag starts
34 | -- @param e position where the tag ends
35 | function print:endtag(tag, s, e)
36 | io.write("End : "..tag.name.."\n")
37 | end
38 |
39 | ---Parses a tag content.
40 | -- @param text text to process
41 | -- @param s position where the tag starts
42 | -- @param e position where the tag ends
43 | function print:text(text, s, e)
44 | io.write("Text : "..text.."\n")
45 | end
46 |
47 | ---Parses CDATA tag content.
48 | -- @param text CDATA content to be processed
49 | -- @param s position where the tag starts
50 | -- @param e position where the tag ends
51 | function print:cdata(text, s, e)
52 | io.write("CDATA : "..text.."\n")
53 | end
54 |
55 | ---Parses a comment tag.
56 | -- @param text comment text
57 | -- @param s position where the tag starts
58 | -- @param e position where the tag ends
59 | function print:comment(text, s, e)
60 | io.write("Comment : "..text.."\n")
61 | end
62 |
63 | ---Parses a DTD tag.
64 | -- @param tag a {name, attrs} table
65 | -- where name is the name of the tag and attrs
66 | -- is a table containing the atributtes of the tag
67 | -- @param s position where the tag starts
68 | -- @param e position where the tag ends
69 | function print:dtd(tag, s, e)
70 | io.write("DTD : "..tag.name.."\n")
71 | if tag.attrs then
72 | for k,v in pairs(tag.attrs) do
73 | io.write(string.format(" + %s='%s'\n", k, v))
74 | end
75 | end
76 | end
77 |
78 | --- Parse a XML processing instructions (PI) tag.
79 | -- @param tag a {name, attrs} table
80 | -- where name is the name of the tag and attrs
81 | -- is a table containing the atributtes of the tag
82 | -- @param s position where the tag starts
83 | -- @param e position where the tag ends
84 | function print:pi(tag, s, e)
85 | io.write("PI : "..tag.name.."\n")
86 | if tag.attrs then
87 | for k,v in pairs(tag.attrs) do
88 | io. write(string.format(" + %s='%s'\n",k,v))
89 | end
90 | end
91 | end
92 |
93 | ---Parse the XML declaration line (the line that indicates the XML version).
94 | -- @param tag a {name, attrs} table
95 | -- where name is the name of the tag and attrs
96 | -- is a table containing the atributtes of the tag
97 | -- @param s position where the tag starts
98 | -- @param e position where the tag ends
99 | function print:decl(tag, s, e)
100 | io.write("XML Decl : "..tag.name.."\n")
101 | if tag.attrs then
102 | for k,v in pairs(tag.attrs) do
103 | io.write(string.format(" + %s='%s'\n", k, v))
104 | end
105 | end
106 | end
107 |
108 | return print
--------------------------------------------------------------------------------
/sandbox/head.lua:
--------------------------------------------------------------------------------
1 | --加上需要require的路径
2 | package.path = package.path..
3 | ";./lua/sandbox/?.lua;"
4 |
5 | JSONLIB = require("JSON")
6 | utils = require("utils")
7 |
8 | local less = false
9 | local maxLine = 10
10 | local maxLen = 500
11 | --重写print函数
12 | function print(...)
13 | if less then return end
14 | if lua_run_result_var ~= "" then
15 | lua_run_result_var = lua_run_result_var.."\r\n"
16 | end
17 | for i=1,select('#', ...) do
18 | lua_run_result_var = lua_run_result_var..tostring(select(i, ...))
19 | if i ~= select('#', ...) then
20 | lua_run_result_var = lua_run_result_var.."\t"
21 | end
22 | end
23 | local _, count = lua_run_result_var:gsub("\n", "\n")
24 | if count >= maxLine then
25 | lua_run_result_var = lua_run_result_var.."\r\n...\r\n余下输出过多,自动省略"
26 | less = true
27 | end
28 | if lua_run_result_var:len() >= maxLen then
29 | lua_run_result_var = lua_run_result_var:sub(maxLen).."\r\n...\r\n余下输出过多,自动省略"
30 | less = true
31 | end
32 | end
33 |
34 | json = {
35 | null = "\0",
36 | decode = function (s)--安全的,带解析结果返回的json解析函数
37 | local result, info = pcall(function(t) return JSONLIB:decode(t) end, s)
38 | if result then
39 | return info, true
40 | else
41 | return {}, false, info
42 | end
43 | end,
44 | encode = function (t)
45 | return JSONLIB:encode(t,nil,{null=json.null})
46 | end
47 | }
48 |
49 | do
50 | local runCount = 0
51 | local start = os.time()
52 | local ot = os.time
53 | local e = error
54 | local function trace (event, line)
55 | runCount = runCount + 1
56 | if runCount > 100000 then
57 | e("运行代码量超过阈值")
58 | end
59 | if ot() - start >= 5 then
60 | e("代码运行超时")
61 | end
62 | end
63 | debug.sethook(trace, "l")
64 | end
65 |
66 | loadstring = load
67 |
68 | pack = {
69 | pack = string.pack,
70 | unpack = function (s,f,h)
71 | local t
72 | if h then
73 | t = table.pack(string.unpack(f,s:sub(h)))
74 | else
75 | t = table.pack(string.unpack(f,s))
76 | end
77 | table.insert(t,1,table.remove(t,#t))
78 | return table.unpack(t)
79 | end,
80 | }
81 |
82 | BIT = require("bit")
83 | bit = BIT.bit32
84 | bit.bit = function(b) return bit.lshift(1,b) end
85 | bit.isset = function(v,p) return bit.rshift(v,p) % 2 == 1 end
86 | bit.isclear = function(v,p) return not bit.isset(v,p) end
87 |
88 | nvm = require("nvm")
89 |
90 | log = {
91 | info = print,
92 | trace = print,
93 | debug = print,
94 | warn = print,
95 | error = print,
96 | fatal = print,
97 | }
98 |
99 | misc = require("misc")
100 |
101 | --安全的函数
102 | local safeFunctions = {
103 | assert = true,
104 | setmetatable = true,
105 | getmetatable = true,
106 | error = true,
107 | ipairs = true,
108 | next = true,
109 | pairs = true,
110 | pcall = true,
111 | select = true,
112 | tonumber = true,
113 | tostring = true,
114 | type = true,
115 | unpack = true,
116 | _VERSION = true,
117 | xpcall = true,
118 | string = true,
119 | table = true,
120 | math = true,
121 | print = true,
122 | _G = true,
123 | lua_run_result_var = true,
124 | os = true,
125 | JSONLIB = true,
126 | json = true,
127 | loadstring = true,
128 | pack = true,
129 | lockbox = true,
130 | crypto = true,
131 | bit = true,
132 | nvm = true,
133 | log = true,
134 | misc = true,
135 | }
136 |
137 | --安全的os函数
138 | local safeOsFunctions = {
139 | clock = true,
140 | difftime = true,
141 | time = true,
142 | date = true,
143 | }
144 | --去除所有不安全函数
145 | for fnc in pairs(os) do
146 | if not safeOsFunctions[fnc] then
147 | os[fnc] = nil
148 | end
149 | end
150 | for fnc in pairs(_G) do
151 | if not safeFunctions[fnc] then
152 | _G[fnc] = nil
153 | end
154 | end
155 |
156 |
--------------------------------------------------------------------------------
/sandbox/utils.lua:
--------------------------------------------------------------------------------
1 | --- 模块功能:常用工具类接口
2 | -- @module utils
3 | -- @author openLuat
4 | -- @license MIT
5 | -- @copyright openLuat
6 | -- @release 2017.10.19
7 |
8 | --- 将Lua字符串转成HEX字符串,如"123abc"转为"313233616263"
9 | -- @string str 输入字符串
10 | -- @string[opt=""] separator 输出的16进制字符串分隔符
11 | -- @return hexstring 16进制组成的串
12 | -- @return len 输入的字符串长度
13 | -- @usage
14 | -- string.toHex("\1\2\3") -> "010203" 3
15 | -- string.toHex("123abc") -> "313233616263" 6
16 | -- string.toHex("123abc"," ") -> "31 32 33 61 62 63 " 6
17 | function string.toHex(str, separator)
18 | return str:gsub('.', function(c)
19 | return string.format("%02X" .. (separator or ""), string.byte(c))
20 | end)
21 | end
22 | --- 将HEX字符串转成Lua字符串,如"313233616263"转为"123abc", 函数里加入了过滤分隔符,可以过滤掉大部分分隔符(可参见正则表达式中\s和\p的范围)。
23 | -- @string hex,16进制组成的串
24 | -- @return charstring,字符组成的串
25 | -- @return len,输出字符串的长度
26 | -- @usage
27 | -- string.fromHex("010203") -> "\1\2\3"
28 | -- string.fromHex("313233616263:) -> "123abc"
29 | function string.fromHex(hex)
30 | --滤掉分隔符
31 | local hex = hex:gsub("[%s%p]", ""):upper()
32 | return hex:gsub("%x%x", function(c)
33 | return string.char(tonumber(c, 16))
34 | end)
35 | end
36 |
37 | -- 返回字符串tonumber的转义字符串(用来支持超过31位整数的转换)
38 | -- @string str 输入字符串
39 | -- @return str 转换后的lua 二进制字符串
40 | -- @return len 转换了多少个字符
41 | -- @usage
42 | -- string.toValue("123456") -> "\1\2\3\4\5\6" 6
43 | -- string.toValue("123abc") -> "\1\2\3\a\b\c" 6
44 | function string.toValue(str)
45 | return string.fromHex(str:gsub("%x", "0%1"))
46 | end
47 |
48 | --- 返回utf8编码字符串的长度
49 | -- @string str,utf8编码的字符串,支持中文
50 | -- @return number,返回字符串长度
51 | -- @usage local cnt = string.utf8Len("中国"),str = 2
52 | function string.utf8Len(str)
53 | local len = #str
54 | local left = len
55 | local cnt = 0
56 | local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
57 | while left ~= 0 do
58 | local tmp = string.byte(str, -left)
59 | local i = #arr
60 | while arr[i] do
61 | if tmp >= arr[i] then
62 | left = left - i
63 | break
64 | end
65 | i = i - 1
66 | end
67 | cnt = cnt + 1
68 | end
69 | return cnt
70 | end
71 | --- 返回数字的千位符号格式
72 | -- @number num,数字
73 | -- @return string,千位符号的数字字符串
74 | -- @usage loca s = string.formatNumberThousands(1000) ,s = "1,000"
75 | function string.formatNumberThousands(num)
76 | local k, formatted
77 | formatted = tostring(tonumber(num))
78 | while true do
79 | formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
80 | if k == 0 then break end
81 | end
82 | return formatted
83 | end
84 |
85 | --- 按照指定分隔符分割字符串
86 | -- @string str 输入字符串
87 | -- @string delimiter 分隔符
88 | -- @return 分割后的字符串列表
89 | -- @usage "123,456,789":split(',') -> {'123','456','789'}
90 | function string.split(str, delimiter)
91 | local strlist, tmp = {}, string.byte(delimiter)
92 | if delimiter == "" then
93 | for i = 1, #str do strlist[i] = str:sub(i, i) end
94 | else
95 | for substr in string.gmatch(str .. delimiter, "(.-)" .. (((tmp > 96 and tmp < 123) or (tmp > 64 and tmp < 91) or (tmp > 47 and tmp < 58)) and delimiter or "%" .. delimiter)) do
96 | table.insert(strlist, substr)
97 | end
98 | end
99 | return strlist
100 | end
101 |
102 | --- 返回utf8编码字符串的长度
103 | -- @string str,utf8编码的字符串,支持中文
104 | -- @return number,返回字符串长度
105 | -- @usage local cnt = string.utf8Len("中国"),str = 2
106 | function string.utf8Len(str)
107 | local len = #str
108 | local left = len
109 | local cnt = 0
110 | local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
111 | while left ~= 0 do
112 | local tmp = string.byte(str, -left)
113 | local i = #arr
114 | while arr[i] do
115 | if tmp >= arr[i] then
116 | left = left - i
117 | break
118 | end
119 | i = i - 1
120 | end
121 | cnt = cnt + 1
122 | end
123 | return cnt
124 | end
125 | -- 将一个字符转为urlEncode编码
126 | local function urlEncodeChar(c)
127 | return "%" .. string.format("%02X", string.byte(c))
128 | end
129 | --- 返回字符串的urlEncode编码
130 | -- @string str,要转换编码的字符串
131 | -- @return str,urlEncode编码的字符串
132 | -- @usage string.urlEncode("####133")
133 | function string.urlEncode(str)
134 | return string.gsub(string.gsub(string.gsub(tostring(str), "\n", "\r\n"), "([^%w%.%- ])", urlEncodeChar), " ", "+")
135 | end
136 |
--------------------------------------------------------------------------------
/require/xmlhandler/dom.lua:
--------------------------------------------------------------------------------
1 | ---- @module Handler to generate a DOM-like node tree structure with
2 | -- a single ROOT node parent - each node is a table comprising
3 | -- the fields below.
4 | --
5 | -- node = { _name = ,
6 | -- _type = ROOT|ELEMENT|TEXT|COMMENT|PI|DECL|DTD,
7 | -- _attr = { Node attributes - see callback API },
8 | -- _parent =
9 | -- _children = { List of child nodes - ROOT/NODE only }
10 | -- }
11 | -- where:
12 | -- - PI = XML Processing Instruction tag.
13 | -- - DECL = XML declaration tag
14 | --
15 | -- The dom structure is capable of representing any valid XML document
16 | --
17 | -- Options
18 | -- =======
19 | -- options.(comment|pi|dtd|decl)Node = bool
20 | -- - Include/exclude given node types
21 | --
22 | -- License:
23 | -- ========
24 | --
25 | -- This code is freely distributable under the terms of the [MIT license](LICENSE).
26 | --
27 | --@author Paul Chakravarti (paulc@passtheaardvark.com)
28 | --@author Manoel Campos da Silva Filho
29 | local dom = {
30 | options = {commentNode=1, piNode=1, dtdNode=1, declNode=1},
31 | current = { _children = {n=0}, _type = "ROOT" },
32 | _stack = {}
33 | }
34 |
35 | ---Parses a start tag.
36 | -- @param tag a {name, attrs} table
37 | -- where name is the name of the tag and attrs
38 | -- is a table containing the atributtes of the tag
39 | function dom:starttag(tag)
40 | local node = { _type = 'ELEMENT',
41 | _name = tag.name,
42 | _attr = tag.attrs,
43 | _children = {n=0}
44 | }
45 |
46 | if self.root == nil then
47 | self.root = node
48 | end
49 |
50 | table.insert(self._stack, node)
51 |
52 | table.insert(self.current._children, node)
53 | self.current = node
54 | end
55 |
56 | ---Parses an end tag.
57 | -- @param tag a {name, attrs} table
58 | -- where name is the name of the tag and attrs
59 | -- is a table containing the atributtes of the tag
60 | function dom:endtag(tag, s)
61 | --Table representing the containing tag of the current tag
62 | local prev = self._stack[#self._stack]
63 |
64 | if tag.name ~= prev._name then
65 | error("XML Error - Unmatched Tag ["..s..":"..tag.name.."]\n")
66 | end
67 |
68 | table.remove(self._stack)
69 | end
70 |
71 | ---Parses a tag content.
72 | -- @param text text to process
73 | function dom:text(text)
74 | local node = { _type = "TEXT",
75 | _text = text
76 | }
77 | table.insert(self.current._children, node)
78 | end
79 |
80 | ---Parses a comment tag.
81 | -- @param text comment text
82 | function dom:comment(text)
83 | if self.options.commentNode then
84 | local node = { _type = "COMMENT",
85 | _text = text
86 | }
87 | table.insert(self.current._children, node)
88 | end
89 | end
90 |
91 | --- Parses a XML processing instruction (PI) tag
92 | -- @param tag a {name, attrs} table
93 | -- where name is the name of the tag and attrs
94 | -- is a table containing the atributtes of the tag
95 | function dom:pi(tag)
96 | if self.options.piNode then
97 | local node = { _type = "PI",
98 | _name = tag.name,
99 | _attr = tag.attrs,
100 | }
101 | table.insert(self.current._children, node)
102 | end
103 | end
104 |
105 | ---Parse the XML declaration line (the line that indicates the XML version).
106 | -- @param tag a {name, attrs} table
107 | -- where name is the name of the tag and attrs
108 | -- is a table containing the atributtes of the tag
109 | function dom:decl(tag)
110 | if self.options.declNode then
111 | local node = { _type = "DECL",
112 | _name = tag.name,
113 | _attr = tag.attrs,
114 | }
115 | table.insert(self.current._children, node)
116 | end
117 | end
118 |
119 | ---Parses a DTD tag.
120 | -- @param tag a {name, attrs} table
121 | -- where name is the name of the tag and attrs
122 | -- is a table containing the atributtes of the tag
123 | function dom:dtd(tag)
124 | if self.options.dtdNode then
125 | local node = { _type = "DTD",
126 | _name = tag.name,
127 | _attr = tag.attrs,
128 | }
129 | table.insert(self.current._children, node)
130 | end
131 | end
132 |
133 | ---Parses CDATA tag content.
134 | dom.cdata = dom.text
135 | return dom
136 |
--------------------------------------------------------------------------------
/require/xml2lua.lua:
--------------------------------------------------------------------------------
1 | --- @module Module providing a non-validating XML stream parser in Lua.
2 | --
3 | -- Features:
4 | -- =========
5 | --
6 | -- * Tokenises well-formed XML (relatively robustly)
7 | -- * Flexible handler based event API (see below)
8 | -- * Parses all XML Infoset elements - ie.
9 | -- - Tags
10 | -- - Text
11 | -- - Comments
12 | -- - CDATA
13 | -- - XML Decl
14 | -- - Processing Instructions
15 | -- - DOCTYPE declarations
16 | -- * Provides limited well-formedness checking
17 | -- (checks for basic syntax & balanced tags only)
18 | -- * Flexible whitespace handling (selectable)
19 | -- * Entity Handling (selectable)
20 | --
21 | -- Limitations:
22 | -- ============
23 | --
24 | -- * Non-validating
25 | -- * No charset handling
26 | -- * No namespace support
27 | -- * Shallow well-formedness checking only (fails
28 | -- to detect most semantic errors)
29 | --
30 | -- API:
31 | -- ====
32 | --
33 | -- The parser provides a partially object-oriented API with
34 | -- functionality split into tokeniser and handler components.
35 | --
36 | -- The handler instance is passed to the tokeniser and receives
37 | -- callbacks for each XML element processed (if a suitable handler
38 | -- function is defined). The API is conceptually similar to the
39 | -- SAX API but implemented differently.
40 | --
41 | -- XML data is passed to the parser instance through the 'parse'
42 | -- method (Note: must be passed a single string currently)
43 | --
44 | -- License:
45 | -- ========
46 | --
47 | -- This code is freely distributable under the terms of the [MIT license](LICENSE).
48 | --
49 | --
50 | --@author Paul Chakravarti (paulc@passtheaardvark.com)
51 | --@author Manoel Campos da Silva Filho
52 | local xml2lua = {}
53 | local XmlParser = require("XmlParser")
54 |
55 | ---Recursivelly prints a table in an easy-to-ready format
56 | --@param tb The table to be printed
57 | --@param level the indentation level to start with
58 | local function printableInternal(tb, level)
59 | if tb == nil then
60 | return
61 | end
62 |
63 | level = level or 1
64 | local spaces = string.rep(' ', level*2)
65 | for k,v in pairs(tb) do
66 | if type(v) == "table" then
67 | print(spaces .. k)
68 | printableInternal(v, level+1)
69 | else
70 | print(spaces .. k..'='..v)
71 | end
72 | end
73 | end
74 |
75 | ---Instantiates a XmlParser object to parse a XML string
76 | --@param handler Handler module to be used to convert the XML string
77 | --to another formats. See the available handlers at the handler directory.
78 | -- Usually you get an instance to a handler module using, for instance:
79 | -- local handler = require("xmlhandler/tree").
80 | --@return a XmlParser object used to parse the XML
81 | --@see XmlParser
82 | function xml2lua.parser(handler)
83 | if handler == xml2lua then
84 | error("You must call xml2lua.parse(handler) instead of xml2lua:parse(handler)")
85 | end
86 |
87 | local options = {
88 | --Indicates if whitespaces should be striped or not
89 | stripWS = 1,
90 | expandEntities = 1,
91 | errorHandler = function(errMsg, pos)
92 | error(string.format("%s [char=%d]\n", errMsg or "Parse Error", pos))
93 | end
94 | }
95 |
96 | return XmlParser.new(handler, options)
97 | end
98 |
99 | ---Recursivelly prints a table in an easy-to-ready format
100 | --@param tb The table to be printed
101 | function xml2lua.printable(tb)
102 | printableInternal(tb)
103 | end
104 |
105 | ---Handler to generate a string prepresentation of a table
106 | --Convenience function for printHandler (Does not support recursive tables).
107 | --@param t Table to be parsed
108 | --@return a string representation of the table
109 | function xml2lua.toString(t)
110 | local sep = ''
111 | local res = ''
112 | if type(t) ~= 'table' then
113 | return t
114 | end
115 |
116 | for k,v in pairs(t) do
117 | if type(v) == 'table' then
118 | v = xml2lua.toString(v)
119 | end
120 | res = res .. sep .. string.format("%s=%s", k, v)
121 | sep = ','
122 | end
123 | res = '{'..res..'}'
124 |
125 | return res
126 | end
127 |
128 | --- Loads an XML file from a specified path
129 | -- @param xmlFilePath the path for the XML file to load
130 | -- @return the XML loaded file content
131 | function xml2lua.loadFile(xmlFilePath)
132 | local f, e = io.open(xmlFilePath, "r")
133 | if f then
134 | --Gets the entire file content and stores into a string
135 | return f:read("*a")
136 | end
137 |
138 | error(e)
139 | end
140 |
141 | return xml2lua
142 |
--------------------------------------------------------------------------------
/require/strings.lua:
--------------------------------------------------------------------------------
1 | --- 模块功能:常用工具类接口
2 | -- @module utils
3 | -- @author openLuat
4 | -- @license MIT
5 | -- @copyright openLuat
6 | -- @release 2017.10.19
7 |
8 | --- 将Lua字符串转成HEX字符串,如"123abc"转为"313233616263"
9 | -- @string str 输入字符串
10 | -- @string[opt=""] separator 输出的16进制字符串分隔符
11 | -- @return hexstring 16进制组成的串
12 | -- @return len 输入的字符串长度
13 | -- @usage
14 | -- string.toHex("\1\2\3") -> "010203" 3
15 | -- string.toHex("123abc") -> "313233616263" 6
16 | -- string.toHex("123abc"," ") -> "31 32 33 61 62 63 " 6
17 | function string.toHex(str, separator)
18 | return str:gsub('.', function(c)
19 | return string.format("%02X" .. (separator or ""), string.byte(c))
20 | end)
21 | end
22 | --- 将HEX字符串转成Lua字符串,如"313233616263"转为"123abc", 函数里加入了过滤分隔符,可以过滤掉大部分分隔符(可参见正则表达式中\s和\p的范围)。
23 | -- @string hex,16进制组成的串
24 | -- @return charstring,字符组成的串
25 | -- @return len,输出字符串的长度
26 | -- @usage
27 | -- string.fromHex("010203") -> "\1\2\3"
28 | -- string.fromHex("313233616263:) -> "123abc"
29 | function string.fromHex(hex)
30 | --滤掉分隔符
31 | local hex = hex:gsub("[%s%p]", ""):upper()
32 | return hex:gsub("%x%x", function(c)
33 | return string.char(tonumber(c, 16))
34 | end)
35 | end
36 |
37 | -- 返回字符串tonumber的转义字符串(用来支持超过31位整数的转换)
38 | -- @string str 输入字符串
39 | -- @return str 转换后的lua 二进制字符串
40 | -- @return len 转换了多少个字符
41 | -- @usage
42 | -- string.toValue("123456") -> "\1\2\3\4\5\6" 6
43 | -- string.toValue("123abc") -> "\1\2\3\a\b\c" 6
44 | function string.toValue(str)
45 | return string.fromHex(str:gsub("%x", "0%1"))
46 | end
47 |
48 | --- 返回utf8编码字符串的长度
49 | -- @string str,utf8编码的字符串,支持中文
50 | -- @return number,返回字符串长度
51 | -- @usage local cnt = string.utf8Len("中国"),str = 2
52 | function string.utf8Len(str)
53 | local len = #str
54 | local left = len
55 | local cnt = 0
56 | local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
57 | while left ~= 0 do
58 | local tmp = string.byte(str, -left)
59 | local i = #arr
60 | while arr[i] do
61 | if tmp >= arr[i] then
62 | left = left - i
63 | break
64 | end
65 | i = i - 1
66 | end
67 | cnt = cnt + 1
68 | end
69 | return cnt
70 | end
71 | --- 返回数字的千位符号格式
72 | -- @number num,数字
73 | -- @return string,千位符号的数字字符串
74 | -- @usage loca s = string.formatNumberThousands(1000) ,s = "1,000"
75 | function string.formatNumberThousands(num)
76 | local k, formatted
77 | formatted = tostring(tonumber(num))
78 | while true do
79 | formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
80 | if k == 0 then break end
81 | end
82 | return formatted
83 | end
84 |
85 | --- 按照指定分隔符分割字符串
86 | -- @string str 输入字符串
87 | -- @string delimiter 分隔符
88 | -- @return 分割后的字符串列表
89 | -- @usage "123,456,789":split(',') -> {'123','456','789'}
90 | function string.split(str, delimiter)
91 | local strlist, tmp = {}, string.byte(delimiter)
92 | if delimiter == "" then
93 | for i = 1, #str do strlist[i] = str:sub(i, i) end
94 | else
95 | for substr in string.gmatch(str .. delimiter, "(.-)" .. (((tmp > 96 and tmp < 123) or (tmp > 64 and tmp < 91) or (tmp > 47 and tmp < 58)) and delimiter or "%" .. delimiter)) do
96 | table.insert(strlist, substr)
97 | end
98 | end
99 | return strlist
100 | end
101 |
102 | --- 返回utf8编码字符串的长度
103 | -- @string str,utf8编码的字符串,支持中文
104 | -- @return number,返回字符串长度
105 | -- @usage local cnt = string.utf8Len("中国"),str = 2
106 | function string.utf8Len(str)
107 | local len = #str
108 | local left = len
109 | local cnt = 0
110 | local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
111 | while left ~= 0 do
112 | local tmp = string.byte(str, -left)
113 | local i = #arr
114 | while arr[i] do
115 | if tmp >= arr[i] then
116 | left = left - i
117 | break
118 | end
119 | i = i - 1
120 | end
121 | cnt = cnt + 1
122 | end
123 | return cnt
124 | end
125 | -- 将一个字符转为urlEncode编码
126 | local function urlEncodeChar(c)
127 | return "%" .. string.format("%02X", string.byte(c))
128 | end
129 | --- 返回字符串的urlEncode编码
130 | -- @string str,要转换编码的字符串
131 | -- @return str,urlEncode编码的字符串
132 | -- @usage string.urlEncode("####133")
133 | function string.urlEncode(str)
134 | return string.gsub(string.gsub(string.gsub(tostring(str), "\n", "\r\n"), "([^%w%.%- ])", urlEncodeChar), " ", "+")
135 | end
136 |
137 |
138 | --- 将utf8编码字符转换为其他字符
139 | -- @string str,要转换编码的字符串
140 | -- @string str,编码名称,如果错了会直接崩
141 | -- @return str,目标编码的字符串
142 | -- @usage ("测试"):utf8To("gb2312")
143 | function string.utf8To(str,encoding)
144 | import("System")
145 | local s = Encoding.GetEncoding(encoding):GetBytes(str)
146 | local t = {}
147 | for i=0,s.Length-1 do table.insert(t,string.char(s[i])) end
148 | return table.concat(t)
149 | end
150 |
--------------------------------------------------------------------------------
/require/xmlhandler/tree.lua:
--------------------------------------------------------------------------------
1 | local function init()
2 | local obj = {
3 | root = {},
4 | options = {noreduce = {}}
5 | }
6 |
7 | obj._stack = {obj.root, n=1}
8 | return obj
9 | end
10 |
11 | --- @module XML Tree Handler.
12 | -- Generates a lua table from an XML content string.
13 | -- It is a simplified handler which attempts
14 | -- to generate a more 'natural' table based structure which
15 | -- supports many common XML formats.
16 | --
17 | -- The XML tree structure is mapped directly into a recursive
18 | -- table structure with node names as keys and child elements
19 | -- as either a table of values or directly as a string value
20 | -- for text. Where there is only a single child element this
21 | -- is inserted as a named key - if there are multiple
22 | -- elements these are inserted as a vector (in some cases it
23 | -- may be preferable to always insert elements as a vector
24 | -- which can be specified on a per element basis in the
25 | -- options). Attributes are inserted as a child element with
26 | -- a key of '_attr'.
27 | --
28 | -- Only Tag/Text & CDATA elements are processed - all others
29 | -- are ignored.
30 | --
31 | -- This format has some limitations - primarily
32 | --
33 | -- * Mixed-Content behaves unpredictably - the relationship
34 | -- between text elements and embedded tags is lost and
35 | -- multiple levels of mixed content does not work
36 | -- * If a leaf element has both a text element and attributes
37 | -- then the text must be accessed through a vector (to
38 | -- provide a container for the attribute)
39 | --
40 | -- In general however this format is relatively useful.
41 | --
42 | -- It is much easier to understand by running some test
43 | -- data through 'testxml.lua -simpletree' than to read this)
44 | --
45 | -- Options
46 | -- =======
47 | -- options.noreduce = { = bool,.. }
48 | -- - Nodes not to reduce children vector even if only
49 | -- one child
50 | --
51 | -- License:
52 | -- ========
53 | --
54 | -- This code is freely distributable under the terms of the [MIT license](LICENSE).
55 | --
56 | --@author Paul Chakravarti (paulc@passtheaardvark.com)
57 | --@author Manoel Campos da Silva Filho
58 | local tree = init()
59 |
60 | ---Instantiates a new handler object.
61 | --Each instance can handle a single XML.
62 | --By using such a constructor, you can parse
63 | --multiple XML files in the same application.
64 | --@return the handler instance
65 | function tree:new()
66 | local obj = init()
67 |
68 | obj.__index = self
69 | setmetatable(obj, self)
70 |
71 | return obj
72 | end
73 |
74 | --Gets the first key of a table
75 | --@param tb table to get its first key
76 | --@return the table's first key, nil if the table is empty
77 | --or the given parameter if it isn't a table
78 | local function getFirstKey(tb)
79 | if type(tb) == "table" then
80 | for k, v in pairs(tb) do
81 | return k
82 | end
83 |
84 | return nil
85 | end
86 |
87 | return tb
88 | end
89 |
90 | --- Recursively removes redundant vectors for nodes
91 | -- with single child elements
92 | function tree:reduce(node, key, parent)
93 | for k,v in pairs(node) do
94 | if type(v) == 'table' then
95 | self:reduce(v,k,node)
96 | end
97 | end
98 | if #node == 1 and not self.options.noreduce[key] and
99 | node._attr == nil then
100 | parent[key] = node[1]
101 | else
102 | node.n = nil
103 | end
104 | end
105 |
106 | ---Parses a start tag.
107 | -- @param tag a {name, attrs} table
108 | -- where name is the name of the tag and attrs
109 | -- is a table containing the atributtes of the tag
110 | function tree:starttag(tag)
111 | local node = {}
112 | if self.parseAttributes == true then
113 | node._attr=tag.attrs
114 | end
115 |
116 | --Table in the stack representing the tag being processed
117 | local current = self._stack[#self._stack]
118 |
119 | if current[tag.name] then
120 | table.insert(current[tag.name], node)
121 | else
122 | current[tag.name] = {node; n=1}
123 | end
124 |
125 | table.insert(self._stack, node)
126 | end
127 |
128 | ---Parses an end tag.
129 | -- @param tag a {name, attrs} table
130 | -- where name is the name of the tag and attrs
131 | -- is a table containing the atributtes of the tag
132 | function tree:endtag(tag, s)
133 | --Table in the stack representing the tag being processed
134 | local current = self._stack[#self._stack]
135 | --Table in the stack representing the containing tag of the current tag
136 | local prev = self._stack[#self._stack-1]
137 | if not prev[tag.name] then
138 | error("XML Error - Unmatched Tag ["..s..":"..tag.name.."]\n")
139 | end
140 | if prev == self.root then
141 | -- Once parsing complete, recursively reduce tree
142 | self:reduce(prev, nil, nil)
143 | end
144 |
145 | local firstKey = getFirstKey(current)
146 | table.remove(self._stack)
147 | end
148 |
149 | ---Parses a tag content.
150 | -- @param t text to process
151 | function tree:text(t)
152 | local current = self._stack[#self._stack]
153 | table.insert(current, t)
154 | end
155 |
156 | ---Parses CDATA tag content.
157 | tree.cdata = tree.text
158 | tree.__index = tree
159 | return tree
160 |
--------------------------------------------------------------------------------
/main.lua:
--------------------------------------------------------------------------------
1 | --导入需要的命名空间
2 | --主库
3 | import("ReceiverMeow","ReceiverMeow")
4 | --luaenv库
5 | import("ReceiverMeow","ReceiverMeow.LuaEnv")
6 | import("ReceiverMeow","ReceiverMeow.GoHttp")
7 | import("System.Text")
8 |
9 | StateName = "lua虚拟机("..LuaEnvName..")"
10 |
11 | Log.Info(StateName,"加载新虚拟机"..LuaEnvName)
12 |
13 | --重写print函数,重定向到debug接口输出
14 | function print(...)
15 | local r = {}
16 | for i=1,select('#', ...) do
17 | table.insert(r,tostring(select(i, ...)))
18 | end
19 | if #r == 0 then
20 | table.insert(r,"nil")
21 | end
22 | Log.Info(StateName,table.concat(r," "))
23 | end
24 |
25 | --加上需要require的路径
26 | package.path = package.path..";./lua/require/?.lua;./lua/events/?.lua;"
27 | package.cpath = package.cpath..";./lua/require/?.lua;./lua/events/?.lua;"
28 |
29 | --加载字符串工具包
30 | require("strings")
31 |
32 | --安全的,带解析结果返回的json解析函数
33 | --返回值:数据,是否成功,错误信息
34 | JSON = require("JSON")
35 | function jsonDecode(s)
36 | local result, info = pcall(function(t) return JSON:decode(t) end, s)
37 | if result then
38 | return info, true
39 | else
40 | return {}, false, info
41 | end
42 | end
43 | function jsonEncode(t)
44 | local result, info = pcall(function(t) return JSON:encode(t) end, t)
45 | if result then
46 | return info, true
47 | else
48 | return "", false, info
49 | end
50 | end
51 |
52 | --加载CQ库
53 | cq = require("cq")
54 |
55 | --唯一id
56 | local idTemp = 0
57 | function getId()
58 | idTemp = idTemp + 1--没必要判断是否溢出,溢出自动变成负数
59 | return idTemp
60 | end
61 |
62 | --封装一个简便的http get接口
63 | function HttpGet(url,para,timeout,cookie)
64 | local r,e = pcall(function() return Utils.HttpGet(url,para or "",timeout or 5000,cookie or "") end)
65 | if r then
66 | return e,r
67 | else
68 | return nil,r,e
69 | end
70 | end
71 | asyncHttpGet = HttpGet
72 |
73 | --封装一个简便的http post接口
74 | function HttpPost(url,para,timeout,cookie,contentType,header,getCookie)
75 | local r,e = pcall(function()
76 | return Utils.HttpPost(url,para or "",timeout or 5000,cookie or "",
77 | contentType or "application/x-www-form-urlencoded",header,getCookie)
78 | end)
79 | if r then
80 | return e,r
81 | else
82 | return nil,r,e
83 | end
84 | end
85 | asyncHttpPost = HttpPost
86 |
87 | --封装一个简便的http jump接口
88 | function HttpJump(url,timeout,cookie)
89 | local r,e = pcall(function() return Utils.HttpJump(url,timeout or 5000,cookie or "") end)
90 | if r then
91 | return e,r
92 | else
93 | return nil,r,e
94 | end
95 | end
96 |
97 | --封装一个文件下载接口
98 | function HttpDownload(url, path, timeout, cookie)
99 | local r,e = pcall(function()
100 | return Utils.HttpDownload(url,"", timeout or 15000,cookie,path)
101 | end)
102 | if r then
103 | return e,r
104 | else
105 | return nil,r,e
106 | end
107 | end
108 | --兼容老接口
109 | asyncFileDownload = function(url, path, maxSize, timeout)
110 | HttpDownload(url, path, timeout)
111 | end
112 |
113 | --根据url显示图片
114 | function asyncImage(url)
115 | return cq.code.image(url)
116 | end
117 |
118 | --加强随机数随机性
119 | math.randomseed(tostring(Utils.Ticks()):reverse():sub(1, 6))
120 |
121 | --获取随机字符串
122 | function getRandomString(len)
123 | local str = "1234567890abcdefhijklmnopqrstuvwxyz"
124 | local ret = ""
125 | for i = 1, len do
126 | local rchr = math.random(1, string.len(str))
127 | ret = ret .. string.sub(str, rchr, rchr)
128 | end
129 | return ret
130 | end
131 |
132 | --分配各个事件
133 | local events = {
134 | AppEnable = "AppEnable",--启动事件
135 | --FriendAdd = "",--好友已添加
136 | --FriendAddRequest = "",--好友请求
137 | GroupAddRequest = "GroupAddRequest",--加群请求
138 | GroupAddInvite = "GroupAddInvite",--机器人被邀请进群
139 | --GroupBanSpeak = "",--群禁言
140 | --GroupUnBanSpeak = "",--群解除禁言
141 | GroupManageSet = "GroupManageSet",--设置管理
142 | GroupManageRemove = "GroupManageRemove",--取消管理
143 | GroupMemberExit = "GroupMemberLeave",--群成员减少,主动退--┐---→统一处理
144 | GroupMemberRemove = "GroupMemberLeave",--群成员减少,被踢--┘
145 | GroupMemberInvite = "GroupMemberJoin",--群成员增加,被邀请--┐---→统一处理
146 | GroupMemberPass = "GroupMemberJoin",--群成员增加,申请的----┘
147 | GroupMessage = "Message",--群消息-------┐---→统一处理
148 | PrivateMessage = "Message",--私聊消息---┘
149 | GroupFileUpload = "GroupFileUpload",--有人上传文件
150 | -- GroupRecall = "",--撤回
151 | -- FriendRecall = "",
152 | -- Poke = "",--戳一戳
153 | -- LuckyKing = "",--群红包运气王
154 | -- Honor = "",--群成员荣誉变更
155 | TcpServer = "ReceiveTcp",--收到tcp客户端发来的数据
156 | --MQTT = "MQTT",--处理MQTT连接逻辑
157 | }
158 |
159 | --如果是MQTT环境,只加载MQTT事件
160 | if LuaEnvName == "MQTT" then
161 | events = {MQTT = "MQTT"}
162 | end
163 |
164 | --每个虚拟机应该加载的事件(不包括group)
165 | local envEvents = {
166 | main = {
167 | "AppEnable",
168 | --"FriendAdd",
169 | --"FriendAddRequest",
170 | "GroupAddRequest",
171 | "GroupAddInvite",
172 | },
173 | private = {
174 | "PrivateMessage",
175 | --"FriendRecall",
176 | }
177 | }
178 |
179 | local function regEvents(i,j)
180 | local f
181 | local _,info = pcall(function() f = require(j) end)
182 | if f then
183 | sys.tiggerRegister(i,f)
184 | Log.Debug(StateName,LuaEnvName.."注册事件"..i..","..j)
185 | else
186 | Log.Warn(StateName,LuaEnvName.."注册事件失败"..i..","..(info or "错误信息为空"))
187 | end
188 | end
189 |
190 | if envEvents[LuaEnvName] then
191 | for i=1,#envEvents[LuaEnvName] do
192 | regEvents(envEvents[LuaEnvName][i],events[envEvents[LuaEnvName][i]])
193 | end
194 | else
195 | for i,j in pairs(events) do
196 | regEvents(i,j)
197 | end
198 | end
199 |
--------------------------------------------------------------------------------
/require/minecraft.lua:
--------------------------------------------------------------------------------
1 | local mc = {}
2 |
3 | local formList = {"commit3","basic1","basic2","basic3","basic4","basic5",
4 | "basic6","basic7","basic8","basic9","basic10","basic11","basic12","basic13",
5 | "basic14","basic15",--"commit4","mc1","mc2","mc3","mc4","mc5","mc6","mc7","mc8",
6 | --"mc9","mc10","mc11",
7 | "commit5","text1","text2","text3","text4","text5","text6",
8 | "text7","text8","text9","commit6","last1","last2","last3","last4",}
9 |
10 | local formTitle = {
11 | commit3 = "基本信息",
12 | basic1 = "从哪里知道的这个服务器?",
13 | basic2 = "你的id(不允许中文、仅限英文和下划线)",
14 | basic3 = "帐号是正版还是盗版?",
15 | basic4 = "写上自己QQ号,用于接收初始密码和过审通知,此项重要勿填错",
16 | basic5 = "年龄",
17 | basic6 = "minecraft的熟悉程度?",
18 | basic7 = "对糖拌服的了解程度",
19 | basic8 = "请问你是否有去过其他服务器?如果有的话,请简述你的经历,并带上对那个服务器的评价。",
20 | basic9 = "请问你是从哪个Minecraft版本开始玩的?",
21 | basic10 = "您是否会将游戏帐号与他人共享?",
22 | basic11 = "是否会加糖拌苦力怕官方群?(填完会给你加群密码,记得加群)",
23 | basic12 = "是否服从服务器的相关规定以及管理组相关人员决定?",
24 | basic13 = "如果你违反了服务器的相关条例,你会怎么做?",
25 | basic14 = "是否会卷入玩家纠纷中",
26 | basic15 = "是否有在其他MC网站/服务器进行过技术研讨或是管理方面的事务?如果有,请描述一下",
27 | commit4 = "游戏常识性问题",
28 | mc1 = "下面哪个mod,不是服务器现在有的?",
29 | mc2 = "以下哪件事情在糖拌服是允许的?",
30 | mc3 = "在Minecraft1.2.5版本中喂什么可以让猪繁殖?",
31 | mc4 = "下面关于红石的说法错误的是?",
32 | mc5 = "下面关于甘蔗的叙述错误的是?",
33 | mc6 = "下面关于僵尸的说法中错误的是?",
34 | mc7 = "以下哪个附魔是普通玩家无法附魔出的?",
35 | mc8 = "下面关于龙蛋的说法错误的是?",
36 | mc9 = "下面关于床的说法错误的是?",
37 | mc10 = "糖拌服中发现自己东西被偷了,想查询方块记录看看是谁偷的,怎么做?",
38 | mc11 = "你觉得选择题你能对几题?",
39 | commit5 = "简答题",
40 | text1 = "请给出你认为你可以通过审核的理由",
41 | text2 = "请想象当op玩脱导致你损失时你将会做什么?想什么?",
42 | text3 = "在服务器里生活有什么注意事项?",
43 | text4 = "请简单的阐述一下对糖拌服的第一印象和对糖拌服运营情况的评价",
44 | text5 = "请说出你对高频、大型红石电路与刷怪塔的看法",
45 | text6 = "假如你的建筑被熊孩子破坏了,请简述对熊孩子的正确做法",
46 | text7 = "请写出服务器建造常识",
47 | text8 = "会被封禁的行为有哪些",
48 | text9 = "会被处予三年以上、七年以下的封禁处罚的行为有哪些",
49 | commit6 = "收尾",
50 | last1 = "怎样才会有白名单",
51 | last2 = "审核的管理是不是24小时都盯着电脑",
52 | last3 = "豆腐脑是甜的好还是咸的好",
53 | last4 = "如果可以,请给予此申请表单一些建议或意见",
54 | }
55 |
56 | function mc.getData(p)
57 | local onlineData = XmlApi.Get("minecraftData",p)
58 | local data = onlineData == "" and
59 | {
60 | time = 0,
61 | last = "offline",
62 | ltime = os.time(),
63 | money = 0,
64 | } or jsonDecode(onlineData)
65 | if not data.money then--如果没金币数据
66 | data.money = math.floor(data.time/60)
67 | end
68 | return data
69 | end
70 |
71 | --开始统计在线时长
72 | local function startCount(p)
73 | local data = mc.getData(p)
74 | if data.last == "online" then return end--上次信息本来就是在线,停止记录
75 | data.last = "online"
76 | data.ltime = os.time()
77 | local d,r = jsonEncode(data)
78 | if r then
79 | XmlApi.Set("minecraftData",p,d)
80 | end
81 | end
82 |
83 | --结束统计在线时长
84 | local function stopCount(p)
85 | local data = mc.getData(p)
86 | if data.last == "offline" then return end--上次信息本来就是离线,停止记录
87 | data.last = "offline"
88 | local last = data.time
89 | data.time = data.time + os.time() - data.ltime
90 | data.money = data.money + math.floor((data.time - last)/60)--加钱
91 | data.ltime = os.time()
92 | local d,r = jsonEncode(data)
93 | if r then
94 | XmlApi.Set("minecraftData",p,d)
95 | end
96 | end
97 |
98 | --添加在线的人
99 | function mc.onlineAdd(p)
100 | local onlineData = XmlApi.Get("minecraftData","[online]")
101 | local online = {}--存储在线所有人id
102 | if onlineData ~= "" then
103 | online = onlineData:split(",")
104 | end
105 | local onlineResult = {}
106 | while #online > 0 do
107 | local player = table.remove(online,1)
108 | if player ~= p then
109 | table.insert(onlineResult,player)
110 | end
111 | end
112 | table.insert(onlineResult,p)
113 | XmlApi.Set("minecraftData","[online]",table.concat(onlineResult,","))
114 | startCount(p)
115 | end
116 |
117 | --删除在线的人
118 | function mc.onlineDel(p)
119 | local onlineData = XmlApi.Get("minecraftData","[online]")
120 | local online = {}--存储在线所有人id
121 | if onlineData ~= "" then
122 | online = onlineData:split(",")
123 | end
124 | local onlineResult = {}
125 | while #online > 0 do
126 | local player = table.remove(online,1)
127 | if player ~= p then
128 | table.insert(onlineResult,player)
129 | end
130 | end
131 | XmlApi.Set("minecraftData","[online]",table.concat(onlineResult,","))
132 | stopCount(p)
133 | end
134 |
135 | --删除所有在线的人
136 | function mc.onlineClear()
137 | local onlineData = XmlApi.Get("minecraftData","[online]")
138 | local online = {}--存储在线所有人id
139 | if onlineData ~= "" then
140 | online = onlineData:split(",")
141 | end
142 | while #online > 0 do
143 | local player = table.remove(online,1)
144 | stopCount(player)
145 | end
146 | XmlApi.Set("minecraftData","[online]","")
147 | end
148 |
149 | --获取某人的表单
150 | function mc.GetForm(id)
151 | local unread = asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=unread")
152 | if not unread:find(",") then
153 | return
154 | end
155 | unread = unread:sub(1,-2):split(",")
156 | for i=#unread,1,-1 do
157 | print("https://www.sweetcreeper.com/form/get.php","m=get&id="..unread[i])
158 | local html = asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=get&id="..
159 | unread[i])
160 | local d,r,e = jsonDecode(html)
161 | if r and d and d.basic2 == id then
162 | return d
163 | end
164 | end
165 | end
166 |
167 | --获取所有现存表单
168 | function mc.listForm()
169 | local rt = {}
170 | local unread = asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=unread")
171 | if not unread:find(",") then
172 | return
173 | end
174 | unread = unread:sub(1,-2):split(",")
175 | for i=#unread,1,-1 do
176 | print("https://www.sweetcreeper.com/form/get.php","m=get&id="..unread[i])
177 | local html = asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=get&id="..
178 | unread[i])
179 | local d,r,e = jsonDecode(html)
180 | if r and d then
181 | table.insert(rt,d.basic2)
182 | end
183 | end
184 | return rt
185 | end
186 |
187 | function mc.readForm(id)
188 | local form = mc.GetForm(id)
189 | if not form then
190 | return "这人没提交申请,发“查申请id”可以手动查"
191 | end
192 | local r = {}
193 | for i=1,#formList do
194 | if form[formList[i]] then
195 | table.insert(r,"["..tostring(i).."]"..
196 | formTitle[formList[i]].."\r\n"..form[formList[i]])
197 | end
198 | end
199 | return table.concat(r,"\r\n")
200 | end
201 |
202 | function mc.markForm(id)
203 | local unread = asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=unread")
204 | if not unread:find(",") then
205 | return
206 | end
207 | unread = unread:sub(1,-2):split(",")
208 | for i=#unread,1,-1 do
209 | local html = asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=get&id="..
210 | unread[i])
211 | local d,r,e = jsonDecode(html)
212 | if r and d.basic2 == id then
213 | asyncHttpGet("https://www.sweetcreeper.com/form/get.php","m=mark&id="..
214 | unread[i])
215 | end
216 | end
217 | end
218 |
219 | return mc
220 |
--------------------------------------------------------------------------------
/require/cq.lua:
--------------------------------------------------------------------------------
1 | --CQ接口处理库
2 | local cq = {}
3 |
4 | local function hg(p,t)
5 | local r = Http.Send(p,(jsonEncode(t)))
6 | Log.Debug("HTTP接口返回",r)
7 | return jsonDecode(r)
8 | end
9 |
10 | --发送私聊信息
11 | function cq.sendPrivateMsg(qq,msg,autoEscape)
12 | local r = hg("send_private_msg",{
13 | user_id = qq,
14 | message = msg,
15 | auto_escape = autoEscape and true or false
16 | })
17 | if r.status == "ok" and r.data.message_id then
18 | return r.data.message_id
19 | else
20 | Log.Warn("发送失败,报错信息:",r.wording)
21 | end
22 | end
23 |
24 | --发送群信息
25 | function cq.sendGroupMsg(group,msg,autoEscape)
26 | local r
27 | if type(group) == "string" then
28 | r = hg("send_guild_channel_msg",{
29 | guild_id = group:match("c(.+),.+"),
30 | channel_id = group:match("c.+,(.+)"),
31 | message = msg,
32 | })
33 | else
34 | r = hg("send_group_msg",{
35 | group_id = group,
36 | message = msg,
37 | auto_escape = autoEscape and true or false
38 | })
39 | end
40 | if r.status == "ok" and r.data.message_id then
41 | return r.data.message_id
42 | else
43 | Log.Warn("发送失败,报错信息:",r.wording)
44 | end
45 | end
46 |
47 | --撤回信息
48 | function cq.deleteMsg(id)
49 | return hg("delete_msg",{
50 | message_id = id
51 | }).status
52 | end
53 |
54 | --给好友点赞
55 | function cq.like(qq,times)
56 | return hg("send_like",{
57 | user_id = qq,
58 | times = times
59 | }).status
60 | end
61 |
62 | --踢人
63 | function cq.groupKick(group,qq,rejectAdd)
64 | return hg("set_group_kick",{
65 | group_id = group,
66 | user_id = qq,
67 | reject_add_request = rejectAdd and true or false
68 | }).status
69 | end
70 |
71 | --禁言某qq
72 | function cq.groupBan(group,qq,duration)
73 | return hg("set_group_ban",{
74 | group_id = group,
75 | user_id = qq,
76 | duration = duration
77 | }).status
78 | end
79 |
80 | --禁言匿名
81 | function cq.groupBanAnonymous(group,flag,duration)
82 | return hg("set_group_anonymous_ban",{
83 | group_id = group,
84 | anonymous = flag,
85 | duration = duration
86 | }).status
87 | end
88 |
89 | --全员禁言
90 | function cq.groupBanAll(group,enable)
91 | return hg("set_group_whole_ban",{
92 | group_id = group,
93 | enable = enable and true or false
94 | }).status
95 | end
96 |
97 | --设置管理员
98 | function cq.groupAdmin(group,qq,enable)
99 | return hg("set_group_admin",{
100 | group_id = group,
101 | user_id = qq,
102 | enable = enable and true or false
103 | }).status
104 | end
105 |
106 | --设置群是否可匿名
107 | function cq.groupAnonymous(group,enable)
108 | return hg("set_group_anonymous",{
109 | group_id = group,
110 | enable = enable and true or false
111 | }).status
112 | end
113 |
114 | --修改某人群备注(群名片)
115 | function cq.groupCard(group,qq,card)
116 | return hg("set_group_card",{
117 | group_id = group,
118 | user_id = qq,
119 | card = card
120 | }).status
121 | end
122 |
123 | --修改群名
124 | function cq.groupName(group,name)
125 | return hg("set_group_name",{
126 | group_id = group,
127 | group_name = name,
128 | }).status
129 | end
130 |
131 | --退群
132 | function cq.groupLeave(group,dismiss)
133 | return hg("set_group_leave",{
134 | group_id = group,
135 | is_dismiss = dismiss and true or false--解散
136 | }).status
137 | end
138 |
139 | --设置群组专属头衔
140 | function cq.groupTitle(group,qq,name,duration)
141 | return hg("set_group_special_title",{
142 | group_id = group,
143 | user_id = qq,
144 | special_title = name,
145 | duration = duration or -1
146 | }).status
147 | end
148 |
149 | --处理加好友请求
150 | function cq.friendAddRequest(tag,approve,name)
151 | return hg("set_friend_add_request",{
152 | flag = tag,
153 | approve = approve and true or false,
154 | remark = name or ""
155 | }).status
156 | end
157 |
158 | --处理加群请求/邀请
159 | function cq.groupAddRequest(tag,rtype,approve,reason)
160 | return hg("set_group_add_request",{
161 | flag = tag,
162 | sub_type = rtype,
163 | approve = approve and true or false,
164 | reason = reason or ""
165 | }).status
166 | end
167 |
168 | --获取登录号信息,返回包含qq和nickname的table
169 | function cq.loginInfo()
170 | local d = hg("get_login_info",{}).data
171 | return {
172 | qq = d.user_id,
173 | nickname = d.nickname
174 | }
175 | end
176 |
177 | --获取陌生人信息
178 | function cq.qqInfo(qq,refresh)
179 | return hg("get_stranger_info",{
180 | user_id = qq,
181 | no_cache = refresh and true or false
182 | }).data
183 | end
184 |
185 | --获取好友列表
186 | function cq.friendList()
187 | return hg("get_friend_list",{}).data
188 | end
189 |
190 | --获取群信息
191 | function cq.groupInfo(group,refresh)
192 | return hg("get_group_info",{
193 | group_id = group,
194 | no_cache = refresh and true or false
195 | }).data
196 | end
197 |
198 | --获取群列表
199 | function cq.groupList()
200 | return hg("get_group_list",{}).data
201 | end
202 |
203 | --获取群成员信息
204 | function cq.groupMemberInfo(group,qq,refresh)
205 | return hg("get_group_member_info",{
206 | group_id = group,
207 | user_id = qq,
208 | no_cache = refresh and true or false
209 | }).data
210 | end
211 |
212 | --获取群成员列表
213 | function cq.groupMemberList(group)
214 | return hg("get_group_member_list",{
215 | group_id = group,
216 | }).data
217 | end
218 |
219 | --获取群荣誉信息
220 | --要获取的群荣誉类型,可传入 talkative performer legend strong_newbie emotion,或传入 all 获取所有数据
221 | function cq.groupHonor(group,t)
222 | return hg("get_group_honor_info",{
223 | group_id = group,
224 | ["type"] = t
225 | }).data
226 | end
227 |
228 | --获取 Cookies
229 | function cq.cookie(domain)
230 | return hg("get_cookies",{
231 | domain = domain,
232 | }).data.cookies
233 | end
234 |
235 | --获取 CSRF Token
236 | function cq.csrfToken()
237 | return hg("get_csrf_token",{}).data.token
238 | end
239 |
240 | --获取 QQ 相关接口凭证
241 | function cq.credentials(domain)
242 | return hg("get_credentials",{
243 | domain = domain,
244 | }).data
245 | end
246 |
247 | --获取语音文件路径
248 | function cq.record(file,format)
249 | return hg("get_record",{
250 | file = file,
251 | out_format = format
252 | }).data.file
253 | end
254 |
255 | --获取图片文件路径
256 | function cq.record(file)
257 | return hg("get_image",{
258 | file = file,
259 | }).data.file
260 | end
261 |
262 | --获取运行状态
263 | function cq.status()
264 | return hg("get_status",{}).data
265 | end
266 |
267 | --获取go cqhttp版本信息
268 | function cq.info()
269 | return hg("get_version_info",{}).data
270 | end
271 |
272 |
273 | --从消息中过滤出图片文件名
274 | function cq.getImage(msg)
275 | return msg:match("%[CQ:image,.*file=(.-%.image),")
276 | end
277 |
278 | --图片 OCR
279 | function cq.ocr(img)
280 | if img:find("%[") then--说明没转换
281 | img = cq.getImage(img)
282 | end
283 | if not img then return end
284 | local r = hg("ocr_image",{
285 | image = img,
286 | }).data
287 | if not r then return end
288 | local text = {}
289 | for i,j in pairs(r.texts) do
290 | if j.confidence > 50 then
291 | table.insert(text,j.text)
292 | end
293 | end
294 | return table.concat(text,"\n")
295 | end
296 |
297 | --cq码
298 | cq.code = {}
299 |
300 | --QQ 表情
301 | --id表对应见https://github.com/richardchien/coolq-http-api/wiki/%E8%A1%A8%E6%83%85-CQ-%E7%A0%81-ID-%E8%A1%A8
302 | function cq.code.face(id)
303 | return "[CQ:face,id="..tostring(id).."]"
304 | end
305 |
306 | --发图片
307 | --flash表示闪照
308 | --文件参数例子
309 | --绝对路径,例如 file:///C:\\Users\Richard\Pictures\1.png,格式使用 file URI
310 | --网络 URL,例如 http://i1.piimg.com/567571/fdd6e7b6d93f1ef0.jpg
311 | --Base64 编码,例如 base64://iVBORw0KGgoAAAANSUhEUgAAA...
312 | function cq.code.image(file,flash)
313 | return "[CQ:image,file="..CQ.Encode(file)..(flash and ",type=flash" or "").."]"
314 | end
315 |
316 | --发语音
317 | --文件参数例子
318 | --绝对路径,例如 file:///C:\\Users\1.amr,格式使用 file URI
319 | --网络 URL,例如 http://i1.piimg.com/567571/1.amr
320 | --Base64 编码,例如 base64://iVBORw0KGgoAAAANSUhEUgAAA...
321 | function cq.code.record(file)
322 | return "[CQ:record,file="..CQ.Encode(file).."]"
323 | end
324 |
325 | --发视频
326 | --文件参数例子
327 | --绝对路径,例如 file:///C:\\Users\1.amr,格式使用 file URI
328 | --网络 URL,例如 http://i1.piimg.com/567571/1.amr
329 | --Base64 编码,例如 base64://iVBORw0KGgoAAAANSUhEUgAAA...
330 | function cq.code.video(file)
331 | return "[CQ:video,file="..CQ.Encode(file).."]"
332 | end
333 |
334 | --at某人 all表示全体
335 | function cq.code.at(qq)
336 | return "[CQ:at,qq="..tostring(qq).."]"
337 | end
338 |
339 | --魔法表情猜拳
340 | function cq.code.rps()
341 | return "[CQ:rps]"
342 | end
343 |
344 | --魔法表情骰子
345 | function cq.code.dice()
346 | return "[CQ:dice]"
347 | end
348 |
349 | --窗口抖动(现在是最简的戳一戳)
350 | function cq.code.shake()
351 | return "[CQ:shake]"
352 | end
353 |
354 | --戳一戳
355 | --类型与id见https://git.io/JLGOk
356 | function cq.code.poke(t,id)
357 | return "[CQ:poke,type="..t..",id="..id.."]"
358 | end
359 |
360 | --匿名发消息标志
361 | function cq.code.anonymous()
362 | return "[CQ:anonymous]"
363 | end
364 |
365 | --链接分享
366 | function cq.code.share(url,title,content,image)
367 | return "[CQ:share,url="..CQ.Encode(url)..",title="..CQ.Encode(title)..
368 | ",content="..CQ.Encode(content)..",image="..CQ.Encode(image).."]"
369 | end
370 |
371 | --好友/群名片
372 | --t可选group、qq
373 | function cq.code.contact(t,id)
374 | return "[CQ:contact,type="..t..",id="..id.."]"
375 | end
376 |
377 | --位置
378 | function cq.code.location(lat,lon,title,content)
379 | return "[CQ:location,lat="..lat..",lon="..lon..",title="..CQ.Encode(title)..
380 | ",content="..CQ.Encode(content).."]"
381 | end
382 |
383 | --音乐简单卡片
384 | --t可选qq 163 xm (QQ 音乐、网易云音乐、虾米音乐)
385 | function cq.code.music(t,id)
386 | return "[CQ:music,type="..t..",id="..id.."]"
387 | end
388 |
389 | --音乐复杂卡片
390 | function cq.code.musicFull(url,audio,title,content,image)
391 | return "[CQ:music,type=custom,url="..CQ.Encode(url)..",audio="..CQ.Encode(audio)..
392 | ",title="..CQ.Encode(title)..",content="..CQ.Encode(content)..",image="..CQ.Encode(image).."]"
393 | end
394 |
395 | --回复
396 | function cq.code.reply(id)
397 | return "[CQ:reply,id="..id.."]"
398 | end
399 |
400 | --xml消息
401 | function cq.code.xml(xml)
402 | return "[CQ:xml,data="..CQ.Encode(xml).."]"
403 | end
404 |
405 | --json消息
406 | function cq.code.xml(json)
407 | return "[CQ:json,data="..CQ.Encode(json).."]"
408 | end
409 |
410 | return cq
411 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/require/apps/96minecraft.lua:
--------------------------------------------------------------------------------
1 | local mcApi = require("minecraft")
2 | local function apiTcpSend(msg,cmd)
3 | if cmd then TcpServer.Send("cmd"..msg) return end
4 | msg = msg:gsub("%[CQ:.-%]","[特殊]"):gsub("\r","")
5 | TcpServer.Send(msg)
6 | end
7 |
8 | local function sendMessage(g,m)
9 | if g==241464054 then
10 | apiTcpSend("[群消息][接待喵]"..m)
11 | end
12 | cq.sendGroupMsg(g,m)
13 | end
14 |
15 |
16 | local function mc(msg,qq,group)
17 | if group == 241464054 then --玩家群
18 | local player = XmlApi.Get("bindQq",tostring(qq))
19 | local step = XmlApi.Get("bindStep",tostring(qq))
20 | apiTcpSend("[群消息]["..(player == "" and "无名氏"..tostring(qq) or player).."]"..msg)
21 |
22 | if msg:find("绑定") == 1 and player == "" then--绑定命令
23 | local player = msg:match("([a-zA-Z0-9_]+)")
24 | player = XmlApi.Row("bindQq",player) ~= "" and "" or player
25 | if player == "" then
26 | sendMessage(241464054,cq.code.at(qq).."id重复,换个吧")
27 | elseif player then
28 |
29 | XmlApi.Set("bindQq",tostring(qq),player)
30 | XmlApi.Set("bindStep",tostring(qq),"waiting")
31 | sendMessage(241464054,cq.code.at(qq).."绑定"..player.."成功!\r\n"..
32 | "请耐心等待管理员审核白名单申请哟~\r\n"..
33 | "如未申请请打开此链接:https://www.chenxublog.com/scf\r\n"..
34 | "如果过去24小时仍未被审核,请回复“催促审核”来进行催促")
35 |
36 | sendMessage(567145439, "接待喵糖拌管理:\r\n玩家"..player.."\r\n已成功绑定"..
37 | "\r\n下面是他的白名单申请内容")
38 | sys.taskInit(function ()
39 | local form = mcApi.readForm(player)..
40 | "\r\n如果符合要求,请回复“通过"..tostring(qq).."”来给予白名单"..
41 | "\r\n如果不符合要求,请回复“不通过"..tostring(qq).."空格原因”来给打回去重填"
42 | while form:len() > 0 do
43 | sendMessage(567145439,form:sub(1,9000))
44 | form = form:sub(9001)
45 | end
46 | end)
47 | else
48 | sendMessage(241464054,cq.code.at(qq).."id不符合要求,仅允许数字、字母、下划线")
49 | end
50 | return true
51 | elseif player == "" then--没绑定id
52 | step = tonumber(step) or 0
53 | if step >= 3 then
54 | cq.groupBan(241464054,qq,10*60)
55 | sendMessage(241464054,cq.code.at(qq).."你没有绑定游戏id,请在十分钟后,发送“绑定”加上id,来绑定自己的id")
56 | else
57 | sendMessage(241464054,cq.code.at(qq).."你没有绑定游戏id,请发送“绑定”加上id,来绑定自己的id")
58 | XmlApi.Set("bindStep",tostring(qq),tostring(step+1))
59 | end
60 | return true
61 | elseif msg:find("查询.+") == 1 or msg == "查询" then--查询某玩家在线信息
62 | local p = msg == "查询" and player or msg:match("查询(%w+)")
63 | local data = mcApi.getData(p)
64 | if data.time == 0 then
65 | local tempqq = msg:match("%d+")
66 | if tempqq then
67 | p = XmlApi.Get("bindQq",tostring(tempqq))
68 | data = mcApi.getData(p)
69 | end
70 | if data.time == 0 then
71 | sendMessage(241464054,cq.code.at(qq).."未查询到该玩家信息")
72 | return true
73 | end
74 | end
75 | if data.last == "online" then
76 | data.time = data.time + os.time() - data.ltime
77 | end
78 | sendMessage(241464054,cq.code.at(qq)..
79 | p.."\r\n"..
80 | "当前状态:"..(data.last == "online" and "在线" or "离线").."\r\n"..
81 | "累计在线:"..string.format("%d小时%d分钟", math.floor(data.time/(60*60)), math.floor(data.time/60)%60)..
82 | (data.last == "online" and "" or "\r\n上次在线时间:"..os.date("%Y年%m月%d日",data.ltime))..
83 | "\r\n在线奖励余额:"..data.money.."\r\n在线时群里发“领取+数量”可取出")
84 | return true
85 | elseif msg:find("领取%d+") == 1 then
86 | local sum = msg:match("领取(%d+)")
87 | if not sum then return end
88 | sum = tonumber(sum)
89 | local data = mcApi.getData(player)
90 | if data.last == "offline" then--不在线
91 | sendMessage(241464054,cq.code.at(qq).."你绑定的id为"..player..
92 | ",请上线后再操作")
93 | return true
94 | elseif data.money < sum then--余额不够
95 | sendMessage(241464054,cq.code.at(qq).."你余额只有"..data.money)
96 | return true
97 | else
98 | apiTcpSend("eco add "..player.." "..sum,true)
99 | data.money = data.money - sum
100 | local d,r = jsonEncode(data)
101 | XmlApi.Set("minecraftData",player,d)
102 | sendMessage(241464054,cq.code.at(qq).."领取成功,还剩"..data.money)
103 | return true
104 | end
105 | elseif msg == "在线" then
106 | local onlineData = XmlApi.Get("minecraftData","[online]")
107 | local online = {}--存储在线所有人id
108 | if onlineData ~= "" then
109 | online = onlineData:split(",")
110 | end
111 | sendMessage(241464054,cq.code.at(qq).."当前在线人数"..tostring(#online).."人:"..
112 | (onlineData=="" and "" or "\r\n"..onlineData))
113 | return true
114 | elseif msg == "激活" then--激活
115 | if step == "pass" or step == "done" then
116 | local data = mcApi.getData(player)
117 | if data.last == "offline" then
118 | sendMessage(241464054,cq.code.at(qq).."你绑定的id为"..player..
119 | ",请上线后再操作")
120 | else
121 | sendMessage(241464054,cq.code.at(qq).."已给予玩家"..player.."权限")
122 | apiTcpSend("lp user "..player.." permission set group.whitelist",true)
123 | apiTcpSend("lp user "..player.." permission unset group.default",true)
124 | if step == "pass" then
125 | XmlApi.Set("bindStep",tostring(qq),"done")
126 | end
127 | end
128 | elseif step == "waiting" then
129 | sendMessage(241464054,cq.code.at(qq).."你还没通过审核呢")
130 | end
131 | return true
132 | elseif msg == "催促审核" and step == "waiting" then--催促审核
133 | sendMessage(567145439, "接待喵糖拌管理:\r\n玩家"..player.."\r\n仅行了催促操作"..
134 | "\r\n请及时检查该玩家是否已经提交白名单申请")
135 | sendMessage(241464054,cq.code.at(qq).."催促成功")
136 |
137 | sys.taskInit(function ()
138 | local form = mcApi.readForm(player)..
139 | "\r\n如果符合要求,请回复“通过"..tostring(qq).."”来给予白名单"..
140 | "\r\n如果不符合要求,请回复“不通过"..tostring(qq).."空格原因”来给打回去重填"
141 | while form:len() > 0 do
142 | sendMessage(567145439,form:sub(1,9000))
143 | form = form:sub(9001)
144 | end
145 | end)
146 | return true
147 | elseif msg:find("重置密码") == 1 and (step == "pass" or step == "done") then
148 | local password = getRandomString(6)
149 | apiTcpSend("flexiblelogin resetpw "..player.." "..password,true)
150 | sendMessage(241464054,cq.code.at(qq).."已重置,请看私聊")
151 | cq.sendPrivateMsg(qq,"密码重置成功,初始密码为:"..password.."\r\n"..
152 | "请在登陆后使用命令/changepassword [密码] [确认密码]来修改密码")
153 | return true
154 | end
155 | elseif group == 567145439 then --管理群
156 | if msg:find("命令") == 1 then
157 | local cmd = msg:sub(("命令"):len()+1)
158 | apiTcpSend(cmd,true)
159 | sendMessage(group,cq.code.at(qq).."命令"..cmd.."已执行")
160 | return true
161 | elseif msg:find("删除 *%d+") == 1 then
162 | local qq = msg:match("删除 *(%d+)")
163 | local player = XmlApi.Get("bindQq",tostring(qq))
164 | if player ~= "" then
165 | XmlApi.Delete("bindStep",tostring(qq))
166 | XmlApi.Delete("bindQq",tostring(qq))
167 | apiTcpSend("lp user "..player.." permission set group.default",true)
168 | apiTcpSend("lp user "..player.." permission unset group.whitelist",true)
169 | sendMessage(567145439,"已删除玩家"..player.."的绑定信息")
170 | else
171 | sendMessage(567145439,"没找到这个玩家")
172 | end
173 | return true
174 | elseif msg:find("通过 *%d+") == 1 then
175 | local qq = msg:match("通过 *(%d+)")
176 | local player = XmlApi.Get("bindQq",tostring(qq))
177 | local step = XmlApi.Get("bindStep",tostring(qq))
178 | if player == "" then
179 | sendMessage(567145439,"该qq没有进行过绑定")
180 | elseif step ~= "waiting" then
181 | sendMessage(567145439,"玩家"..player.."不在待审核名单中")
182 | else
183 | XmlApi.Set("bindStep",tostring(qq),"pass")
184 | sendMessage(567145439,"已通过"..player.."的白名单申请")
185 | sendMessage(241464054,cq.code.at(tonumber(qq)).."你的白名单申请已经通过了哟~\r\n"..
186 | "游戏上线后,在群里发送“激活”即可获取权限~\r\n"..
187 | "你的id:"..player)
188 | sys.taskInit(function ()--标记为已读取
189 | mcApi.markForm(player)
190 | end)
191 | end
192 | return true
193 | elseif msg:find("不通过 *%d+ .+") == 1 then
194 | local qq,reason = msg:match("不通过 *(%d+) (.+)")
195 | local player = XmlApi.Get("bindQq",tostring(qq))
196 | local step = XmlApi.Get("bindStep",tostring(qq))
197 | if player == "" then
198 | sendMessage(567145439,"该qq没有进行过绑定")
199 | elseif step ~= "waiting" then
200 | sendMessage(567145439,"玩家"..player.."不在待审核名单中")
201 | else
202 | sendMessage(567145439,"已打回"..player.."的白名单申请,原因:"..reason)
203 | sendMessage(241464054,cq.code.at(tonumber(qq)).."你的白名单申请并没有通过。\r\n"..
204 | "原因:"..reason.."\r\n"..
205 | "请按照原因重新填写白名单:https://www.chenxublog.com/scf\r\n"..
206 | "你的id:"..player.."\r\n如果重新填完了,请发送“催促审核”来让管理重审")
207 | sys.taskInit(function ()--标记为已读取
208 | mcApi.markForm(player)
209 | end)
210 | end
211 | return true
212 | elseif msg:find("查申请.*") == 1 then
213 | local player = msg:match("查申请 *(.+)")
214 | sys.taskInit(function ()
215 | if player then
216 | local form = mcApi.readForm(player)
217 | while form:len() > 0 do
218 | sendMessage(567145439,form:sub(1,9000))
219 | form = form:sub(9001)
220 | end
221 | else
222 | local list = mcApi.listForm(player)
223 | sendMessage(567145439,"目前未查看的申请:\r\n"..table.concat(list,"\r\n"))
224 | end
225 | end)
226 | return true
227 | elseif msg == "清空在线" then
228 | mcApi.onlineClear()
229 | sendMessage(567145439,cq.code.at(qq).."已清空所有在线信息")
230 | return true
231 | elseif msg == "清理裂隙" then
232 | apiTcpSend("kill @e[type=thaumcraft:fluxrift]",true)
233 | sendMessage(567145439,cq.code.at(qq).."已执行清理裂隙命令")
234 | return true
235 | end
236 | end
237 | end
238 |
239 | return {--mc群管理逻辑
240 | check = function (data)
241 | return data.group == 241464054 or data.group == 567145439
242 | end,
243 | run = function (data,sendMessage)
244 | return mc(data.msg,data.qq,data.group)
245 | end
246 | }
247 |
--------------------------------------------------------------------------------
/require/apps/10chess.lua:
--------------------------------------------------------------------------------
1 | --象棋
2 |
3 | --存储数据规则:
4 | --<对方qq号>,<发起人1/被发起人0>,<上一步下过1/上一步没下过0>,<棋盘每一行内容>
5 |
6 | --显示棋盘内容,返回值为最终图片
7 | --print(show(dataNow,{x=1,y=1},{x=2,y=1}))
8 | local function show(data,last,now)
9 | local xtable = {8,65,122,179,236,293,350,407,464}
10 | local ytable = {8,65,122,179,236,293,350,407,464,521}
11 | local pic = Utils.GetBitmap(544,624)
12 | Utils.SetImage(pic,1,1,Utils.Path.."lua/require/chess/bg.png",544,674)
13 | for i=1,#data do
14 | for j=1,9 do
15 | if data[i]:sub(j,j)~="." then
16 | Utils.SetImage(pic,xtable[j],ytable[i],Utils.Path.."lua/require/chess/"..data[i]:sub(j,j)..".png",54,54)
17 | end
18 | end
19 | end
20 | if last then Utils.SetImage(pic,xtable[last.x],ytable[last.y],Utils.Path.."lua/require/chess/box.png",54,54) end
21 | if now then Utils.SetImage(pic,xtable[now.x],ytable[now.y],Utils.Path.."lua/require/chess/box.png",54,54) end
22 | local file = Utils.ImageBase64(pic):match("base64,(.+)")
23 | return cq.code.image("base64://"..file)
24 | end
25 |
26 | --初始化棋盘与双方的最初数据
27 | local function init(fromqq,anotherqq)
28 | if fromqq == anotherqq then
29 | return cq.code.at(tonumber(fromqq)).."无法与自己下棋"
30 | end
31 | local dataNow = {
32 | "abcdedcba",
33 | ".........",
34 | ".f.....f.",
35 | "g.g.g.g.g",
36 | ".........",
37 | ".........",
38 | "7.7.7.7.7",
39 | ".6.....6.",
40 | ".........",
41 | "123454321",}
42 | XmlApi.Set("chess",fromqq,anotherqq..",0,1,"..table.concat(dataNow, "/"))
43 | XmlApi.Set("chess",anotherqq,fromqq..",1,0,"..table.concat(dataNow, "/"))
44 | return show(dataNow).."\r\n"..
45 | ("已开局,红色为"..cq.code.at(tonumber(anotherqq))..",黑色为"..cq.code.at(tonumber(fromqq))).."\r\n"..
46 | ("接下来请"..cq.code.at(tonumber(anotherqq)).."走子")
47 | end
48 |
49 | --显示当前棋盘
50 | local function showNow(fromqq)
51 | local str1 = XmlApi.Get("chess",fromqq)
52 | --获取己方已保存数据
53 | if not str1:find(",") then return cq.code.at(tonumber(fromqq)).."你没有正在进行的棋局" end
54 | local t1 = str1:split(",")
55 | local str2 = XmlApi.Get("chess",t1[1])
56 | --判断对方是否在棋局中
57 | if not str2:find(",") then return cq.code.at(tonumber(fromqq)).."对手已退出棋局,请重新开局" end
58 | local t2 = str2:split(",")
59 | --判断对方的对手qq是否相同,棋盘数据是否相同
60 | if t2[1] ~= fromqq or t1[4] ~= t2[4] then return cq.code.at(tonumber(fromqq)).."对手已退出棋局,请重新开局" end
61 |
62 | local pieces = t1[4]:split("/")
63 | return (show(pieces)).."\r\n"..
64 | (cq.code.at(tonumber(fromqq)).."棋盘状态如上").."\r\n"..
65 | ("接下来该"..cq.code.at(tonumber(t1[3] == "1" and t1[1] or fromqq)).."走子")
66 | end
67 |
68 | --走子处理
69 | local function play(moveData,fromqq)
70 | local str1 = XmlApi.Get("chess",fromqq)
71 | --获取己方已保存数据
72 | if not str1:find(",") then return cq.code.at(tonumber(fromqq)).."你没有正在进行的棋局" end
73 | local t1 = str1:split(",")
74 | --判断是否轮到改人走子
75 | if t1[3] == "1" then return cq.code.at(tonumber(fromqq)).."还没有轮到你走子哦" end
76 | local str2 = XmlApi.Get("chess",t1[1])
77 | --判断对方是否在棋局中
78 | if not str2:find(",") then return cq.code.at(tonumber(fromqq)).."对手已退出棋局,请重新开局" end
79 | local t2 = str2:split(",")
80 | --判断对方的对手qq是否相同,棋盘数据是否相同
81 | if t2[1] ~= fromqq or t1[4] ~= t2[4] then return cq.code.at(tonumber(fromqq)).."对手已退出棋局,请重新开局" end
82 |
83 | --整理前后位置数据
84 | moveData = moveData:upper()
85 | local movet = {A=1,B=2,C=3,D=4,E=5,F=6,G=7,H=8,I=9,J=10}--坐标转换表
86 | local lastx,nextx = moveData:match("(%d)%u(%d)")
87 | local lasty,nexty = moveData:match("(%u)%d(%u)")
88 | lastx,nextx = tonumber(lastx),tonumber(nextx)
89 | lasty = movet[lasty]
90 | nexty = movet[nexty]
91 | --判断走子是否合法
92 | if not (lastx and nexty and lasty and nextx and
93 | lastx > 0 and lastx < 10 and
94 | lasty > 0 and lasty < 11 and
95 | nextx > 0 and nextx < 10 and
96 | nexty > 0 and nexty < 11) then
97 | return cq.code.at(tonumber(fromqq)).."走子位置错误,请检查命令"
98 | end
99 |
100 | --棋盘当前状态的table
101 | local pieces = t1[4]:split("/")
102 | --获取某座标的棋子
103 | local function getPoint(x,y)
104 | return pieces[y]:sub(x,x)
105 | end
106 | --移动棋子到指定坐标,返回被吃的棋子名称
107 | local function movePoint(x,y,xx,yy)
108 | local pick = pieces[yy]:sub(xx,xx)
109 | pieces[yy] = pieces[yy]:sub(1,xx-1)..pieces[y]:sub(x,x)..pieces[yy]:sub(xx+1)
110 | pieces[y] = pieces[y]:sub(1,x-1).."."..pieces[y]:sub(x+1)
111 | return pick
112 | end
113 | local pick = getPoint(lastx,lasty)
114 | --检查选择的子是否合法
115 | if pick == "." then return cq.code.at(tonumber(fromqq)).."所选起始位置无棋子,请检查命令" end
116 | if (pick:find("%d") and t1[2] == "0") or (pick:find("%l") and t1[2] == "1") then
117 | return cq.code.at(tonumber(fromqq))..(t1[2] == "1" and "红" or "黑").."色的棋子才是你的哦,不要动别人的棋子"
118 | end
119 | --检查目标坐标是否为己方棋子
120 | local dest = getPoint(nextx,nexty)
121 | if (dest:find("%d") and t1[2] == "1") or (dest:find("%l") and t1[2] == "0") then
122 | return cq.code.at(tonumber(fromqq)).."你不能吃自己的棋子"
123 | end
124 |
125 | --检查走子是否合规
126 | local function max(a,b) return a>b and a or b end--取最大的
127 | local function min(a,b) return a 5 then return false end--不能过界
156 | if (x+2==xx and y+2==yy and getPoint(x+1,y+1)==".") or
157 | (x-2==xx and y+2==yy and getPoint(x-1,y+1)==".") or
158 | (x-2==xx and y-2==yy and getPoint(x-1,y-1)==".") or
159 | (x+2==xx and y-2==yy and getPoint(x+1,y-1)==".") then
160 | return true
161 | else
162 | return false
163 | end
164 | end,
165 | ["3"] = function(x,y,xx,yy)--象,红方
166 | if yy < 6 then return false end--不能过界
167 | if (x+2==xx and y+2==yy and getPoint(x+1,y+1)==".") or
168 | (x-2==xx and y+2==yy and getPoint(x-1,y+1)==".") or
169 | (x-2==xx and y-2==yy and getPoint(x-1,y-1)==".") or
170 | (x+2==xx and y-2==yy and getPoint(x+1,y-1)==".") then
171 | return true
172 | else
173 | return false
174 | end
175 | end,
176 | d = function(x,y,xx,yy)--士,黑方
177 | if xx<4 or xx>6 or yy>3 then return false end--不能过界
178 | if math.abs(x-xx)==1 and math.abs(y-yy)==1 then
179 | return true
180 | else
181 | return false
182 | end
183 | end,
184 | ["4"] = function(x,y,xx,yy)--士,红方
185 | if xx<4 or xx>6 or yy<8 then return false end--不能过界
186 | if math.abs(x-xx)==1 and math.abs(y-yy)==1 then
187 | return true
188 | else
189 | return false
190 | end
191 | end,
192 | e = function(x,y,xx,yy)--将,黑方
193 | if xx<4 or xx>6 or yy>3 then return false end--不能过界
194 | if math.abs(x-xx) + math.abs(y-yy) == 1 then--xy只有一个变化加一
195 | return true
196 | else
197 | return false
198 | end
199 | end,
200 | ["5"] = function(x,y,xx,yy)--帅,红方
201 | if xx<4 or xx>6 or yy<8 then return false end--不能过界
202 | if math.abs(x-xx) + math.abs(y-yy) == 1 then--xy只有一个变化加一
203 | return true
204 | else
205 | return false
206 | end
207 | end,
208 | f = function(x,y,xx,yy)--炮
209 | if x~=xx and y ~= yy and math.abs(x-xx)+math.abs(y-yy) < 1 then return false end--必须有一个坐标不变
210 | local count = 0
211 | if x==xx then for i=min(y,yy),max(y,yy) do--横着走
212 | if getPoint(x,i) ~= "." then count = count + 1 end
213 | end end
214 | if y==yy then for i=min(x,xx),max(x,xx) do--竖着走
215 | if getPoint(i,y) ~= "." then count = count + 1 end
216 | end end
217 | if (count == 3 and getPoint(xx,yy) ~= ".") or count == 1 then--中途无子或跳着吃子
218 | return true
219 | else
220 | return false
221 | end
222 | end,
223 | g = function(x,y,xx,yy)--卒,黑方
224 | if y < 6 then--在己方内
225 | if math.abs(x-xx)==0 and yy-y==1 then return true else return false end
226 | else
227 | if math.abs(x-xx)+math.abs(y-yy)==1 and yy-y>=0 then return true else return false end
228 | end
229 | end,
230 | ["7"] = function(x,y,xx,yy)--兵,红方
231 | if y > 5 then--在己方内
232 | if math.abs(x-xx)==0 and yy-y==-1 then return true else return false end
233 | else
234 | if math.abs(x-xx)+math.abs(y-yy)==1 and yy-y<=0 then return true else return false end
235 | end
236 | end,
237 | }
238 | checkRule["1"] = checkRule.a
239 | checkRule["2"] = checkRule.b
240 | checkRule["6"] = checkRule.f
241 | --应用规则并阻止不合规的走子
242 | if not checkRule[getPoint(lastx,lasty)](lastx,lasty,nextx,nexty) then
243 | return cq.code.at(tonumber(fromqq)).."这枚棋子不能这么走"
244 | end
245 |
246 | local eat = movePoint(lastx,lasty,nextx,nexty)
247 | if eat=="e" or eat=="5" then
248 | XmlApi.Set("chess",fromqq,"")
249 | XmlApi.Set("chess",t1[1],"")
250 | return (show(pieces,{x=lastx,y=lasty},{x=nextx,y=nexty})).."\r\n"..
251 | (cq.code.at(tonumber(fromqq)).."赢了"..cq.code.at(tonumber(t1[1]))).."\r\n"..
252 | ("恭喜,本局结束")
253 | else
254 | local piecesStr = table.concat(pieces, "/")
255 | XmlApi.Set("chess",fromqq,t1[1]..","..t1[2]..",1,"..piecesStr)
256 | XmlApi.Set("chess",t1[1],t2[1]..","..t2[2]..",0,"..piecesStr)
257 | return (show(pieces,{x=lastx,y=lasty},{x=nextx,y=nexty})).."\r\n"..
258 | (cq.code.at(tonumber(fromqq)).."已走子").."\r\n"..
259 | ("接下来请"..cq.code.at(tonumber(t1[1])).."走子")
260 | end
261 | end
262 |
263 | local function chess(fromqq,message)
264 | local fromqq = tostring(fromqq)
265 | local message = tostring(message)
266 | if message:find("象棋") == 1 then
267 | message = message:gsub(" ","")
268 | if message == "象棋开局" then
269 | XmlApi.Set("chess",fromqq,"wait")
270 | return (cq.code.at(tonumber(fromqq))).."\r\n"..
271 | ("已开启新的一局").."\r\n"..
272 | ("其他人使用命令:\r\n象棋加入"..fromqq.."\r\n可加入棋局")
273 | elseif message:find("象棋加入") == 1 then
274 | local anotherqq = message:gsub("象棋加入","")
275 | if XmlApi.Get("chess",anotherqq) ~= "wait" then
276 | return (cq.code.at(tonumber(fromqq))).."\r\n"..
277 | ("未找到用户"..anotherqq.."开启的棋局")
278 | else
279 | return init(fromqq,anotherqq)
280 | end
281 | elseif message == "象棋退出" then
282 | XmlApi.Set("chess",fromqq,"")
283 | return (cq.code.at(tonumber(fromqq))).."\r\n"..
284 | ("已退出所有棋局")
285 | elseif message:find("象棋走") == 1 and message:len() == string.len("象棋走A5B5") then
286 | return play(message:sub(string.len("象棋走")),fromqq)
287 | elseif message == "象棋棋盘" then
288 | return showNow(fromqq)
289 | else
290 | return [[象棋命令帮助📍
291 | ⚔️象棋开局 开启新一轮棋局
292 | 🗡️象棋加入 加 对方qq号 加入对方棋局
293 | 🚪象棋退出 退出当前棋局
294 | 📌象棋棋盘 查看当前的棋盘状态
295 | 🛡️象棋走 加 前后坐标 移动棋子
296 | 如:象棋走A5B5
297 | 仅限同群对战]]
298 | end
299 | end
300 | end
301 |
302 |
303 | return {--象棋
304 | check = function (data)
305 | return data.msg:find("象棋") == 1
306 | end,
307 | run = function (data,sendMessage)
308 | sendMessage(chess(data.qq,data.msg))
309 | return true
310 | end,
311 | explain = function ()
312 | return "♟象棋 查看象棋功能帮助"
313 | end
314 | }
315 |
--------------------------------------------------------------------------------
/require/apps/17homo.lua:
--------------------------------------------------------------------------------
1 | local initial = {
2 | [0]="(1-1)*4514",
3 | [1]="11/(45-1)*4",
4 | [2]="-11+4-5+14",
5 | [3]="11*-4+51-4",
6 | [4]="-11-4+5+14",
7 | [5]="11-4*5+14",
8 | [6]="1-14+5+14",
9 | [7]="11-4+5-1-4",
10 | [8]="11-4+5/1-4",
11 | [9]="11-4+5+1-4",
12 | [10]="-11/4+51/4",
13 | [11]="11*-4+51+4",
14 | [12]="-11+4+5+14",
15 | [13]="1*14-5/1+4",
16 | [14]="11+4-5/1+4",
17 | [15]="1+14-5+1+4",
18 | [16]="11-4-5+14",
19 | [17]="11+4*5-14",
20 | [18]="1+1+4*5*1-4",
21 | [19]="1+1+4*5+1-4",
22 | [20]="-11+45-14",
23 | [21]="-1-1+4+5+14",
24 | [22]="1*14+5-1+4",
25 | [23]="1*14-5+14",
26 | [24]="1+14-5+14",
27 | [25]="11*4-5-14",
28 | [26]="11-4+5+14",
29 | [27]="11+4*5/1-4",
30 | [28]="11+4*5+1-4",
31 | [29]="-11+45-1-4",
32 | [30]="1*-1+45-14",
33 | [31]="1/1*45-14",
34 | [32]="1*1+45-14",
35 | [33]="1+1+45-14",
36 | [34]="1-14+51-4",
37 | [35]="11*4+5-14",
38 | [36]="11+4*5+1+4",
39 | [37]="-11+45-1+4",
40 | [38]="-11+45*1+4",
41 | [39]="-11+45+1+4",
42 | [40]="-11+4*51/4",
43 | [41]="1/1*45*1-4",
44 | [42]="11+45-14",
45 | [43]="1+1*45+1-4",
46 | [44]="114-5*14",
47 | [45]="11+4*5+14",
48 | [46]="11*4+5+1-4",
49 | [47]="1/-1+45-1+4",
50 | [48]="-11+45+14",
51 | [49]="1*1*45/1+4",
52 | [50]="1+1*45/1+4",
53 | [51]="11+45-1-4",
54 | [52]="11+45/1-4",
55 | [53]="11+45+1-4",
56 | [54]="11-4+51-4",
57 | [55]="-1+14*5-14",
58 | [56]="1*14*5-14",
59 | [57]="1+14*5-14",
60 | [58]="-1+1*45+14",
61 | [59]="114-51-4",
62 | [60]="11+45*1+4",
63 | [61]="1+1+45+14",
64 | [62]="1+14+51-4",
65 | [63]="11*4+5+14",
66 | [64]="11*4+5*1*4",
67 | [65]="1*14*5-1-4",
68 | [66]="1*14*5-1*4",
69 | [67]="1-1*4+5*14",
70 | [68]="1+1-4+5*14",
71 | [69]="1*14+51+4",
72 | [70]="11+45+14",
73 | [71]="(1+14)*5-1*4",
74 | [72]="-1-1+4+5*14",
75 | [73]="1*14*5-1+4",
76 | [74]="1/1*4+5*14",
77 | [75]="1+14*5*1+4",
78 | [76]="1+1+4+5*14",
79 | [77]="11-4+5*14",
80 | [78]="(1+1)*4+5*14",
81 | [79]="1*-1+4*5/1*4",
82 | [80]="1-1+4*5*1*4",
83 | [81]="1/1+4*5*1*4",
84 | [82]="1+1+4*5/1*4",
85 | [83]="-1+14+5*14",
86 | [84]="1*14+5*14",
87 | [85]="1+14+5*14",
88 | [86]="(1+1)*45*1-4",
89 | [87]="11+4*(5+14)",
90 | [88]="1*14*(5+1)+4",
91 | [89]="(1+14)*5+14",
92 | [90]="-114+51*4",
93 | [91]="11*4+51-4",
94 | [92]="(1+1)*(45-1)+4",
95 | [93]="(1+1)*45-1+4",
96 | [94]="114-5/1*4",
97 | [95]="114-5-14",
98 | [96]="11*(4+5)+1-4",
99 | [97]="1+1*4*(5+1)*4",
100 | [98]="1+1+4*(5+1)*4",
101 | [99]="11*4+51+4",
102 | [100]="1*(1+4)*5*1*4",
103 | [101]="1+1*4*5*(1+4)",
104 | [102]="11*(4+5)-1+4",
105 | [103]="11*(4+5)+1*4",
106 | [104]="114-5-1-4",
107 | [105]="114+5-14",
108 | [106]="114-5+1-4",
109 | [107]="11-4*-(5+1)*4",
110 | [110]="-(11-451)/4",
111 | [111]="11+4*5*(1+4)",
112 | [112]="114-5-1+4",
113 | [113]="114-5/1+4",
114 | [114]="11*4+5*14",
115 | [115]="114+5*1-4",
116 | [116]="114+5+1-4",
117 | [117]="(1-14)*(5-14)",
118 | [118]="(1+1)*(45+14)",
119 | [120]="-(1+1)*4*5*(1-4)",
120 | [121]="11*(45-1)/4",
121 | [122]="114+5-1+4",
122 | [123]="114-5+14",
123 | [124]="114+5+1+4",
124 | [125]="-1-14*(5-14)",
125 | [126]="1*(14-5)*14",
126 | [127]="1-14*(5-14)",
127 | [128]="1+1+(4+5)*14",
128 | [129]="114+5*-(1-4)",
129 | [130]="-1+145-14",
130 | [131]="1*145-14",
131 | [132]="1+145-14",
132 | [133]="114+5+14",
133 | [134]="114+5/1*4",
134 | [135]="-1/1*45*(1-4)",
135 | [136]="1*1-45*(1-4)",
136 | [137]="1+1-45*(1-4)",
137 | [138]="-1*(1+45)*(1-4)",
138 | [139]="-1+145-1-4",
139 | [140]="1*145-1-4",
140 | [141]="1+145-1-4",
141 | [142]="1+145*1-4",
142 | [143]="1+145+1-4",
143 | [146]="11+45*-(1-4)",
144 | [147]="-1+145-1+4",
145 | [148]="1*145-1+4",
146 | [149]="1*145*1+4",
147 | [150]="1+145*1+4",
148 | [151]="1+145+1+4",
149 | [152]="(1+1)*4*(5+14)",
150 | [154]="11*(4-5)*-14",
151 | [157]="1*(1-4)*-51+4",
152 | [158]="-1+145+14",
153 | [159]="1*145+14",
154 | [160]="1+145+14",
155 | [161]="114+51-4",
156 | [165]="11*-45/(1-4)",
157 | [168]="(11+45)*-(1-4)",
158 | [169]="114+51+4",
159 | [170]="(11-45)*-(1+4)",
160 | [171]="114*(5+1)/4",
161 | [172]="11*4*(5-1)-4",
162 | [174]="-1-1+(45-1)*4",
163 | [175]="-1+1*(45-1)*4",
164 | [176]="1*1*(45-1)*4",
165 | [177]="1+1*(45-1)*4",
166 | [178]="-1-1+45*1*4",
167 | [179]="-1/1+45*1*4",
168 | [180]="1*1*45*1*4",
169 | [181]="1+1*45*1*4",
170 | [182]="1+1+45/1*4",
171 | [183]="-1+1*(45+1)*4",
172 | [184]="114+5*14",
173 | [185]="1-1*-(45+1)*4",
174 | [186]="1+1+(45+1)*4",
175 | [187]="1/-1+4*(51-4)",
176 | [188]="1-1-(4-51)*4",
177 | [189]="-11-4+51*4",
178 | [190]="1*-14+51*4",
179 | [191]="1-14+51*4",
180 | [192]="(1+1)*4*(5+1)*4",
181 | [195]="(1-14)*5*(1-4)",
182 | [196]="-(1+1)*4+51*4",
183 | [197]="-11+4+51*4",
184 | [198]="-1-1+4*51-4",
185 | [199]="1*-1+4*51-4",
186 | [200]="1/1*4*51-4",
187 | [201]="1/1-4+51*4",
188 | [202]="1+1-4+51*4",
189 | [204]="(1-1)/4+51*4",
190 | [206]="11*4*5-14",
191 | [207]="-1+1*4*51+4",
192 | [208]="1*1*4+51*4",
193 | [209]="1+1*4*51+4",
194 | [210]="1+1+4+51*4",
195 | [211]="11-4+51*4",
196 | [212]="(1+1)*4+51*4",
197 | [214]="-11+45*(1+4)",
198 | [215]="11*4*5-1-4",
199 | [216]="11*4*5-1*4",
200 | [217]="11*4*5+1-4",
201 | [218]="1*14+51*4",
202 | [219]="1+14+51*4",
203 | [220]="1*1*(4+51)*4",
204 | [221]="1/1+4*(51+4)",
205 | [222]="1+1+4*(51+4)",
206 | [223]="11*4*5-1+4",
207 | [224]="11*4*5/1+4",
208 | [225]="11*4*5+1+4",
209 | [226]="1*1+45*(1+4)",
210 | [227]="1+1+45*(1+4)",
211 | [229]="1145/(1+4)",
212 | [230]="1*(1+45)*(1+4)",
213 | [231]="11+4*(51+4)",
214 | [234]="11*4*5+14",
215 | [235]="1*(1+4)*(51-4)",
216 | [236]="11+45*(1+4)",
217 | [240]="(11+4)*(5-1)*4",
218 | [247]="-(1-14)*(5+14)",
219 | [248]="11*4+51*4",
220 | [251]="1*-(1+4)*-51-4",
221 | [252]="(114-51)*4",
222 | [257]="(1+1)/4*514",
223 | [259]="1*(1+4)*51+4",
224 | [260]="1*(14+51)*4",
225 | [265]="-1+14*(5+14)",
226 | [266]="1*14*(5+14)",
227 | [267]="1+14*(5+14)",
228 | [268]="11*4*(5+1)+4",
229 | [269]="-11+4*5*14",
230 | [270]="(1+1)*45*-(1-4)",
231 | [275]="1*(1+4)*(51+4)",
232 | [278]="-1-1+4*5*14",
233 | [279]="1*-1+4*5*14",
234 | [280]="1-1+4*5*14",
235 | [281]="1+14*5/1*4",
236 | [282]="1+1+4*5*14",
237 | [285]="(11+4)*(5+14)",
238 | [286]="(1145-1)/4",
239 | [291]="11+4*5*14",
240 | [297]="-11*(4+5)*(1-4)",
241 | [300]="(11+4)*5/1*4",
242 | [312]="(1-14)*-(5+1)*4",
243 | [318]="114+51*4",
244 | [325]="-(1-14)*5*(1+4)",
245 | [327]="-(114-5)*(1-4)",
246 | [329]="(11-4)*(51-4)",
247 | [335]="-1+14*(5+1)*4",
248 | [336]="1*14*(5+1)*4",
249 | [337]="1-14*-(5+1)*4",
250 | [341]="11*(45-14)",
251 | [349]="-1+14*5*(1+4)",
252 | [350]="1*(1+4)*5*14",
253 | [351]="1+14*-5*-(1+4)",
254 | [352]="(1+1)*(45-1)*4",
255 | [353]="(11-4)*51-4",
256 | [357]="(114+5)*-(1-4)",
257 | [360]="(1+1)*45*1*4",
258 | [361]="(11-4)*51+4",
259 | [363]="(1+1451)/4",
260 | [368]="(1+1)*(45+1)*4",
261 | [375]="(1+14)*5*(1+4)",
262 | [376]="(1+1)*4*(51-4)",
263 | [385]="(11-4)*(51+4)",
264 | [396]="11*4*-(5-14)",
265 | [400]="-114+514",
266 | [404]="(1+1)*4*51-4",
267 | [412]="(1+1)*4*51+4",
268 | [432]="(1-145)*(1-4)",
269 | [434]="-1-145*(1-4)",
270 | [435]="-1*145*(1-4)",
271 | [436]="-11+451-4",
272 | [438]="(1+145)*-(1-4)",
273 | [440]="(1+1)*4*(51+4)",
274 | [444]="-11+451+4",
275 | [445]="-1-1+451-4",
276 | [446]="1*-1+451-4",
277 | [447]="1/1*451-4",
278 | [448]="1+1*451-4",
279 | [449]="1+1+451-4",
280 | [450]="(1+1)*45*(1+4)",
281 | [452]="114*(5-1)-4",
282 | [453]="-1-1+451+4",
283 | [454]="-1+1*451+4",
284 | [455]="1-1+451+4",
285 | [456]="1*1+451+4",
286 | [457]="1+1+451+4",
287 | [458]="11+451-4",
288 | [460]="114*(5-1)+4",
289 | [466]="11+451+4",
290 | [470]="-11*4+514",
291 | [476]="(114+5)/1*4",
292 | [480]="11*(45-1)-4",
293 | [481]="11*45-14",
294 | [488]="11*(45-1)+4",
295 | [490]="11*45-1-4",
296 | [491]="11*45-1*4",
297 | [492]="11*45+1-4",
298 | [495]="11*(4+5)*(1+4)",
299 | [498]="11*45-1+4",
300 | [499]="11*45*1+4",
301 | [500]="11*45+1+4",
302 | [501]="1-14+514",
303 | [502]="11*(45+1)-4",
304 | [506]="-(1+1)*4+514",
305 | [507]="-11+4+514",
306 | [508]="-1-1-4+514",
307 | [509]="11*45+14",
308 | [510]="1-1-4+514",
309 | [511]="1*1-4+514",
310 | [512]="1+1-4+514",
311 | [513]="-11*(4-51)-4",
312 | [514]="(1-1)/4+514",
313 | [516]="-1-1+4+514",
314 | [517]="-1+1*4+514",
315 | [518]="1-1+4+514",
316 | [519]="1+1*4+514",
317 | [520]="1+1+4+514",
318 | [521]="11-4+514",
319 | [522]="(1+1)*4+514",
320 | [527]="-1+14+514",
321 | [528]="1*14+514",
322 | [529]="1+14+514",
323 | [545]="(114-5)*(1+4)",
324 | [556]="114*5-14",
325 | [558]="11*4+514",
326 | [560]="(1+1)*4*5*14",
327 | [561]="11/4*51*4",
328 | [565]="114*5-1-4",
329 | [566]="114*5*1-4",
330 | [567]="114*5+1-4",
331 | [573]="114*5-1+4",
332 | [574]="114*5/1+4",
333 | [575]="114*5+1+4",
334 | [576]="1*(145-1)*4",
335 | [579]="-1+145*1*4",
336 | [580]="1*145/1*4",
337 | [581]="1+145*1*4",
338 | [584]="114*5+14",
339 | [595]="(114+5)*(1+4)",
340 | [601]="11*(4+51)-4",
341 | [609]="11*(4+51)+4",
342 | [611]="(1-14)*-(51-4)",
343 | [612]="-1*(1-4)*51*4",
344 | [616]="1*-(1-45)*14",
345 | [619]="-11+45*14",
346 | [628]="114+514",
347 | [629]="1*-1+45*14",
348 | [630]="1*1*45*14",
349 | [631]="1*1+45*14",
350 | [632]="1+1+45*14",
351 | [641]="11+45*14",
352 | [644]="1*(1+45)*14",
353 | [649]="11*(45+14)",
354 | [657]="-1+14*(51-4)",
355 | [658]="1*14*(51-4)",
356 | [659]="1+14*(51-4)",
357 | [660]="(114+51)*4",
358 | [667]="-(1-14)*51+4",
359 | [680]="114*(5+1)-4",
360 | [688]="114*(5+1)+4",
361 | [704]="11*4*(5-1)*4",
362 | [705]="(1+14)*(51-4)",
363 | [709]="-1+14*51-4",
364 | [710]="1*14*51-4",
365 | [711]="1+14*51-4",
366 | [715]="(1-14)*-(51+4)",
367 | [717]="-1-14*-51+4",
368 | [718]="1*14*51+4",
369 | [719]="1+14*51+4",
370 | [720]="(1-145)*-(1+4)",
371 | [724]="-1-145*-(1+4)",
372 | [725]="1*145*(1+4)",
373 | [726]="1+145*(1+4)",
374 | [730]="(1+145)*(1+4)",
375 | [761]="(1+14)*51-4",
376 | [769]="(11+4)*51+4",
377 | [770]="1*14*(51+4)",
378 | [771]="1+14*(51+4)",
379 | [784]="(11+45)*14",
380 | [805]="-11+4*51*4",
381 | [814]="-1-1+4*51*4",
382 | [815]="-1+1*4*51*4",
383 | [816]="1*1*4*51*4",
384 | [817]="1*1+4*51*4",
385 | [818]="1+1+4*51*4",
386 | [825]="(11+4)*(51+4)",
387 | [827]="11+4*51*4",
388 | [836]="11*4*(5+14)",
389 | [880]="11*4*5*1*4",
390 | [894]="(1+1)*(451-4)",
391 | [898]="(1+1)*451-4",
392 | [906]="(1+1)*451+4",
393 | [910]="-(1-14)*5*14",
394 | [979]="-1+14*5*14",
395 | [980]="1*14*5*14",
396 | [981]="1+14*5*14",
397 | [1020]="1*(1+4)*51*4",
398 | [1026]="114*-(5-14)",
399 | [1036]="(1+1)*(4+514)",
400 | [1050]="(11+4)*5*14",
401 | [1056]="11*4*(5+1)*4",
402 | [1100]="11*4*5*(1+4)",
403 | [1131]="1145-14",
404 | [1140]="(1145-1)-4",
405 | [1141]="1145-1*4",
406 | [1142]="1145+1-4",
407 | [1148]="1145-1+4",
408 | [1149]="1145+1*4",
409 | [1150]="1145+1+4",
410 | [1159]="1145+14",
411 | [1260]="(1+1)*45*14",
412 | [1386]="11*(4+5)*14",
413 | [1428]="(11-4)*51*4",
414 | [1446]="-1+1451-4",
415 | [1447]="1*1451-4",
416 | [1448]="1+1451-4",
417 | [1454]="-1+1451+4",
418 | [1455]="1*1451+4",
419 | [1456]="1+1451+4",
420 | [1485]="11*-45*(1-4)",
421 | [1526]="(114-5)*14",
422 | [1542]="1*-(1-4)*514",
423 | [1632]="(1+1)*4*51*4",
424 | [1666]="(114+5)*14",
425 | [1710]="114*-5*(1-4)",
426 | [1760]="-(11-451)*4",
427 | [1793]="-11+451*4",
428 | [1800]="1*-(1-451)*4",
429 | [1802]="-1-1+451*4",
430 | [1803]="1*-1+451*4",
431 | [1804]="1-1+451*4",
432 | [1805]="1+1*451*4",
433 | [1806]="1+1+451*4",
434 | [1808]="1*(1+451)*4",
435 | [1815]="11+451*4",
436 | [1824]="114*(5-1)*4",
437 | [1848]="(11+451)*4",
438 | [1936]="11*(45-1)*4",
439 | [1980]="11*45*1*4",
440 | [2016]="-(1-145)*14",
441 | [2024]="11*(45+1)*4",
442 | [2029]="-1+145*14",
443 | [2030]="1*145*14",
444 | [2031]="1+145*14",
445 | [2044]="(1+145)*14",
446 | [2045]="-11+4*514",
447 | [2054]="-1-1+4*514",
448 | [2055]="-1/1+4*514",
449 | [2056]="1/1*4*514",
450 | [2057]="1/1+4*514",
451 | [2058]="1+1+4*514",
452 | [2067]="11+4*514",
453 | [2068]="11*4*(51-4)",
454 | [2166]="114*(5+14)",
455 | [2240]="11*4*51-4",
456 | [2248]="11*4*51+4",
457 | [2280]="114*5*1*4",
458 | [2420]="11*4*(51+4)",
459 | [2475]="11*45*(1+4)",
460 | [2570]="1*(1+4)*514",
461 | [2652]="(1-14)*51*-4",
462 | [2736]="114*(5+1)*4",
463 | [2850]="114*5*(1+4)",
464 | [2855]="-1+14*51*4",
465 | [2856]="1*14*51*4",
466 | [2857]="1+14*51*4",
467 | [3060]="(11+4)*51*4",
468 | [3080]="11*4*5*14",
469 | [3435]="-1145*(1-4)",
470 | [3598]="(11-4)*514",
471 | [3608]="(1+1)*451*4",
472 | [4112]="(1+1)*4*514",
473 | [4503]="-11+4514",
474 | [4512]="-1-1+4514",
475 | [4513]="-1*1+4514",
476 | [4514]="1-1+4514",
477 | [4515]="1+1*4514",
478 | [4516]="1+1+4514",
479 | [4525]="11+4514",
480 | [4576]="(1145-1)*4",
481 | [4580]="1145*1*4",
482 | [4584]="(1145+1)*4",
483 | [4917]="11*(451-4)",
484 | [4957]="11*451-4",
485 | [4965]="11*451+4",
486 | [5005]="11*(451+4)",
487 | [5358]="114*(51-4)",
488 | [5610]="-11*(4-514)",
489 | [5698]="11*(4+514)",
490 | [5725]="1145*(1+4)",
491 | [5800]="(1-1451)*-4",
492 | [5803]="-1+1451*4",
493 | [5804]="1*1451*4",
494 | [5805]="1+1451*4",
495 | [5808]="(1+1451)*4",
496 | [5810]="114*51-4",
497 | [5818]="114*51+4",
498 | [6270]="114*(51+4)",
499 | [6682]="(1-14)*-514",
500 | [6930]="11*45*14",
501 | [7195]="-1+14*514",
502 | [7196]="1*14*514",
503 | [7197]="1+14*514",
504 | [7710]="(1+14)*514",
505 | [7980]="114*5*14",
506 | [8976]="11*4*51*4",
507 | [9028]="(1+1)*4514",
508 | [11447]="11451-4",
509 | [11455]="11451+4",
510 | [14513]="-1+14514",
511 | [14514]="1*14514",
512 | [14515]="1+14514",
513 | [16030]="1145*14",
514 | [19844]="11*451*4",
515 | [22616]="11*4*514",
516 | [23256]="114*51*4",
517 | [45804]="11451*4",
518 | [49654]="11*4514",
519 | [58596]="114*514",
520 | [114514]="114514",
521 | }
522 |
523 | local function find(n,count)
524 | count = count or 0
525 | if count > 10 then
526 | return "这么恶臭的数字还有论证的必要吗?"
527 | else
528 | count = count + 1
529 | end
530 |
531 | if initial[n] then return initial[n] end
532 | for i,j in pairs(initial) do
533 | if i ~= 0 then
534 | local a = n % i
535 | if a == 0 and initial[n/i] then
536 | return "("..initial[n/i]..")*("..j..")"
537 | elseif initial[math.floor(n/i)] and initial[a] then
538 | return "("..initial[math.floor(n/i)]..")*("..j..")+"..initial[a]
539 | elseif initial[math.floor(n/i)] then
540 | return "("..initial[math.floor(n/i)]..")*("..j..")+"..find(a,count)
541 | end
542 | end
543 | end
544 | return "这么恶臭的数字还有论证的必要吗?"
545 | end
546 |
547 | return {--b站av号解析
548 | check = function (data)
549 | return data.msg:find("数字论证") and tonumber(data.msg:match("(%d+)"))
550 | end,
551 | run = function (data,sendMessage)
552 | local num = tonumber(data.msg:match("(%d+)"))
553 | if num < 1000000000 then
554 | sendMessage(cq.code.at(data.qq)..find(num))
555 | else
556 | sendMessage(cq.code.at(data.qq).."这么恶臭的数字还有必要论证吗?")
557 | end
558 | return true
559 | end,
560 | explain = function ()
561 | return "💩数字论证(正整数)"
562 | end
563 | }
564 |
--------------------------------------------------------------------------------
/require/apps/06almanac.lua:
--------------------------------------------------------------------------------
1 | local says = --哲学之语613句
2 | {
3 | "1000-7",
4 | "70万都没有你还想当吧主",
5 | "「……這個世界就是變態的。」",
6 | "「人生在世数十年,小事不要太计较!」",
7 | "啊哈哈,佐祐理不知道",
8 | "爱的供养,再问自杀",
9 | "矮穷矬",
10 | "哎呀我摔倒了,要亲亲才能起来",
11 | "暗中观察",
12 | "傲娇毁一生",
13 | "奥特oo",
14 | "八点二十发",
15 | "霸气侧漏",
16 | "把我血加住,我有盾墙",
17 | "白富美",
18 | "百合无限好,可惜生不了",
19 | "报复社会",
20 | "保证打不死你",
21 | "脖子以下到脚背以上形成了一个凄惨的平面",
22 | "背后怕是有肮脏的屁眼交易",
23 | "笨蛋是不会感冒的",
24 | "本站立足于美利坚合众国,对全球华人服务,受北美法律保护",
25 | "别人家的oo",
26 | "别说了,我",
27 | "不被发现就不算犯罪哦",
28 | "不得了",
29 | "不服来辩",
30 | "不就是一块石头么,看我用高达把它推回去",
31 | "不明真相的ooxx",
32 | "不能描写的方式",
33 | "不能同意更多",
34 | "不抛弃不放弃",
35 | "不如跳舞",
36 | "不是敌人太强大,只是队友太oo",
37 | "不是很懂你们oo",
38 | "不是萝莉控,是女权主义者",
39 | "不是oo,是x!",
40 | "不要扶他",
41 | "不要和我说什么oo",
42 | "不要靠近我啊",
43 | "不要问我oo是谁",
44 | "不要在意细节",
45 | "不作死就不会死,为什么不明白!",
46 | "不oo不舒服斯基",
47 | "不oo的话不就只能去死了吗",
48 | "操到叫苦连天",
49 | "厕纸",
50 | "蝉在叫人坏掉",
51 | "超高校级的oo",
52 | "车塞卡",
53 | "沉迷学习,日渐消瘦",
54 | "诚哥死得早",
55 | "吃饭睡觉打oo",
56 | "吃我龙神之剑",
57 | "穿山甲到底说了什么",
58 | "纯爷们从不回头看爆炸",
59 | "此处应该有掌声",
60 | "此生无悔入东方,来世愿生幻想乡",
61 | "从小o到大",
62 | "从业二十年,做人做事,无愧于心",
63 | "大葱插菊花治疗感冒",
64 | "大力出奇迹",
65 | "打麻将真开心啊",
66 | "大清亡了",
67 | "打土豪,分手办",
68 | "大丈夫萌大奶",
69 | "带球撞人",
70 | "但是我拒绝",
71 | "单纵就是干",
72 | "当你拥有ooo",
73 | "当然是选择原谅她",
74 | "今天,一个死宅实现了他的梦想",
75 | "德国的科学技术是世界第一",
76 | "地球君又杯具了",
77 | "敌羞吾去脱她衣",
78 | "东京电视台最强传说",
79 | "东吴爱萝莉,曹魏控人妻,蜀汉全是基",
80 | "都是oo的错",
81 | "对方不想和你说话并向你扔了oo",
82 | "多大仇",
83 | "堕落!萌死他卡多!",
84 | "二货,快来条士力架",
85 | "而且没有人爱你",
86 | "而是你要享受这个过程",
87 | "Excuse me???",
88 | "发图不发种,菊花万人捅",
89 | "反射弧太长",
90 | "放铳输一局,缩卵输一生",
91 | "放开那个oo",
92 | "飞龙骑脸怎么输",
93 | "粉红的切开来里面都是黑的",
94 | "风险投资",
95 | "弗拉格综合征",
96 | "父母双亡,有妹有房",
97 | "嘎嘣脆鸡肉味",
98 | "该来的总会来的",
99 | "感觉亏了一个亿",
100 | "干了这碗恒河水",
101 | "刚刚o了一下",
102 | "搞事情",
103 | "告诉oo我还爱她",
104 | "高阻绿",
105 | "各个都是人才,说话又好听,超喜欢在里面",
106 | "哥哥让开这样我杀不了那家伙",
107 | "给您拜年了",
108 | "给dalao递oo",
109 | "根本停不下来",
110 | "根据相关法律法规和政策,部分搜索结果未予显示",
111 | "挂科比不挂柯南",
112 | "官方逼死同人",
113 | "官方吐槽",
114 | "广州宅报",
115 | "国家欠我一个oo",
116 | "过去的oo弱爆了",
117 | "国之将亡,遍地舰娘",
118 | "害怕",
119 | "还是种田比较适合老子",
120 | "还有马桶盖子",
121 | "好多孩子看到这个根本把持不住",
122 | "好平如潮",
123 | "好气啊,但还是要保持微笑",
124 | "好讨厌,眼泪一直停不下来",
125 | "毫无ps痕迹",
126 | "和怪兽战斗是自卫队的传统",
127 | "喝最烈的酒",
128 | "嘿嘿……怎麼說呢,說起來有點下流…我竟然…勃起了",
129 | "很了不起的大象先生吧",
130 | "恨妹不成穹",
131 | "画个圈圈诅咒你",
132 | "画个xx硬说是oo",
133 | "皇上,臣妾做不到啊",
134 | "回老家结婚",
135 | "活久见",
136 | "Interesting",
137 | "基本国情",
138 | "记得关好门",
139 | "计划通",
140 | "技术宅拯救世界",
141 | "简直就是狂欢一样",
142 | "讲道理",
143 | "教练,我想ooo",
144 | "脚只是装饰而已,上面的大人物是不会懂的",
145 | "揭棺而起 起驾回棺",
146 | "进击的oo",
147 | "晋太元中",
148 | "今天的风儿好喧嚣啊",
149 | "警察叔叔,就是这个人",
150 | "净TM扯淡",
151 | "就打德",
152 | "AF可能缺少淡水",
153 | "舅舅党",
154 | "就算不结婚有妹妹不就好了吗",
155 | "就算是神也杀给你看",
156 | "就算是oo,只要有爱就没问题",
157 | "就这样插进去就行了",
158 | "巨乳只有下垂的未来",
159 | "绝望了,我对这个oo的世界绝望了",
160 | "君日本语本当上手",
161 | "卡在了奇怪的地方",
162 | "开局一把刀装备全靠捡",
163 | "开始你的表演",
164 | "看啊,你的死兆星在天上闪耀",
165 | "看见oo我就进来了",
166 | "看来你不懂生命的可贵",
167 | "砍了那只鸭",
168 | "可爱的oo早已",
169 | "可爱即正义",
170 | "克里斯关下门",
171 | "可是那一天,我有了新的想法",
172 | "可喜可贺",
173 | "可惜是个oo",
174 | "可以的,ooo",
175 | "空降",
176 | "恐怕罪魁祸首就是oo",
177 | "空手拆高达",
178 | "Konmai quality",
179 | "快拔网线!",
180 | "快到碗里来",
181 | "快看他画风和我们不一样",
182 | "快闪开我按错了",
183 | "来盘昆特牌吧",
184 | "来相思树下",
185 | "Lame Uncomfortable Laugh",
186 | "蓝瘦,香菇",
187 | "老子有oo你怕不怕",
188 | "理都懂",
189 | "厉害了我的哥",
190 | "历史总是惊人地相似",
191 | "联邦的MS都是怪物吗",
192 | "连我爸爸都没有打过我",
193 | "连自己心爱的人都救不了,我还算什么oo",
194 | "楼主好人一生平安",
195 | "论oo的xxx",
196 | "萝莉有三好,身娇腰柔易推倒",
197 | "妈的智障",
198 | "妈妈再也不用担心我的oo",
199 | "Mad in chine",
200 | "满状态原地复活",
201 | "冒险家翻抽屉有什么不对",
202 | "美国其实并不存在",
203 | "没毛病",
204 | "没图你说个oo",
205 | "萌娘百科收录希望",
206 | "萌音绕梁,三日不绝",
207 | "谜已经全部解开了",
208 | "明天来oo上班",
209 | "魔法少女oo",
210 | "目睹事件全过程的O先生",
211 | "木有鱼丸",
212 | "哪里不会点哪里",
213 | "那万一赢了呢",
214 | "那一天,人类终于想起了oo的恐怖",
215 | "奈何共军有高达",
216 | "奶奶曾经说过",
217 | "男人变态有什么错",
218 | "脑装屎",
219 | "你暴露时间了",
220 | "你不会百度吗",
221 | "你才oo,你们全家都oo",
222 | "你从什么时候开始产生了oooo的错觉",
223 | "你的爱还不够啊",
224 | "你的好友oo已上线",
225 | "你的英勇长存人心",
226 | "你还记得自己是男的",
227 | "你经历过绝望吗",
228 | "你看看你",
229 | "你渴望力量吗",
230 | "你妈逼你结婚了吗",
231 | "你妈喊你回家吃饭",
232 | "你们……有没有oo",
233 | "你们城里人真会玩",
234 | "你们的关系可真好啊",
235 | "你们都是坏人",
236 | "你们都是我的翅膀",
237 | "你们对力量一无所知",
238 | "你们感受一下",
239 | "你们尽管oo,xx了算我输",
240 | "你们两个,干脆交往算啦",
241 | "你们这是自寻死路",
242 | "你傻逼!再见!",
243 | "你是猴子请来的救兵吗",
244 | "你谁啊",
245 | "你为何这么屌",
246 | "你为什么不问问神奇海螺呢",
247 | "你为什么这么叼",
248 | "你行你上啊",
249 | "你胸太小不要说话",
250 | "你已经死了",
251 | "你咋不上天呢",
252 | "你在大声什么啦",
253 | "你这么厉害怎么不去青青草原抓羊",
254 | "你这么oo,你xx知道吗",
255 | "你知道的太多了",
256 | "你制杖吗?不,我贩剑。",
257 | "酿了你哦",
258 | "你tm感动了我",
259 | "牛顿死得早",
260 | "浓浓的超好喝",
261 | "O成狗",
262 | "O分钟惨案",
263 | "O军马鹿",
264 | "O月是xx的oo",
265 | "O在起跑线",
266 | "Oo is watching you",
267 | "Oo,你算计我!oo!",
268 | "Oo,我只服xx",
269 | "Oo必须死",
270 | "Oo大法好",
271 | "Oo的人生不需要解释",
272 | "Oo的笑容由我来守护",
273 | "Oo点击就送",
274 | "Oo多如狗,xx满地走",
275 | "Oo儿女多奇志",
276 | "Oo还能再战xx年",
277 | "Oo还在,xx没了",
278 | "Oo还只是个孩子",
279 | "Oo好可爱啊oo",
280 | "Oo黑丧心病狂",
281 | "Oo很萌的,你们不要黑她",
282 | "Oo救不了xx",
283 | "Oo可绕地球x圈",
284 | "Oo哭晕在厕所",
285 | "Oo了,我不做xx的粉丝了",
286 | "Oo美如画",
287 | "Oo你好,oo再见",
288 | "Oo你突破盲點了",
289 | "Oo让你滚,你就不得不滚",
290 | "Oo人民发来贺电",
291 | "Oo如同大小姐的威严一样伟岸",
292 | "Oo什么的最讨厌了",
293 | "Oo是本体",
294 | "Oo是检验xx的唯一标准",
295 | "Oo是什么,能吃吗",
296 | "Oo是完全没有必要的存在",
297 | "Oo是一种思想,而思想是不怕xx的",
298 | "Oo望着自己贫瘠的胸部说道",
299 | "Oo我老婆",
300 | "Oo五分钟,xx两小时",
301 | "Oo已经阻止不了我了",
302 | "Oo已死",
303 | "Oo有毒",
304 | "Oo又死了真没人性",
305 | "Oo与xx之间的惨烈修罗场",
306 | "Oo在下很大的一盘棋",
307 | "Oo真是天使",
308 | "Oo只能帮你到这儿了",
309 | "Oo只是个oo",
310 | "Ooo,我们走",
311 | "Oooo,av10492",
312 | "配合oo食用风味更佳",
313 | "贫乳是稀有价值",
314 | "普通oo,文艺oo和2boo",
315 | "其实我是你爸爸",
316 | "其他人做得到吗",
317 | "前方高能反应",
318 | "前方oo福利",
319 | "前略,天国的oo",
320 | "千万不要搜索oo",
321 | "枪毙十分钟",
322 | "抢铁集团",
323 | "亲妹妹不如干妹妹",
324 | "请允许我做一个悲伤的表情",
325 | "去死两次",
326 | "然而并没有什么卵用",
327 | "然而oo早就看穿了一切",
328 | "饶罗翔教你截图",
329 | "人被杀就会死",
330 | "人家拿小拳拳捶你胸口",
331 | "人类才勇敢",
332 | "人类已经失去了oo的权利了",
333 | "人数过万,智商减半",
334 | "任性可是女孩子的天性呢",
335 | "认真你就输了",
336 | "日日夜夜",
337 | "如果你是oo你还笑得出来吗",
338 | "如果你ooo我们还是朋友",
339 | "如果奇迹有颜色,那一定是橙色",
340 | "如果oo就是神作了",
341 | "如今又再度变得温顺了",
342 | "萨满,又疯一个",
343 | "三个人结婚吧",
344 | "三秒规则",
345 | "三年起步,最高死刑",
346 | "三索必须死",
347 | "三天三夜",
348 | "上交给国家",
349 | "少女祈祷中",
350 | "烧死那对异性恋",
351 | "射爆",
352 | "社会我oo",
353 | "摄影师你明天不用来上班了",
354 | "神马都是浮云",
355 | "神说你还不能死在这里",
356 | "圣光啊,你有看到那个oo吗",
357 | "声优不要钱",
358 | "声优都是怪物",
359 | "声优怒领工资",
360 | "时代在进步",
361 | "世界上没有什么事是一oxx不能解决的,如果有,那就两o",
362 | "视觉模糊",
363 | "十五字",
364 | "是在下输了",
365 | "是oo的friends呢",
366 | "收了可观的小费后,酒馆老板小声道",
367 | "输出基本靠吼",
368 | "兽娘动物园:属性",
369 | "帅不过三秒",
370 | "谁过来谁先死",
371 | "谁指使你来的",
372 | "瞬间爆炸",
373 | "说鸡不说吧,文明你我他",
374 | "四舍五入就是一个亿",
375 | "死宅真恶心",
376 | "酸甜苦辣咸,ooooo",
377 | "虽不明,但觉厉",
378 | "虽然我可爱又迷人,但我会招来死亡",
379 | "虽然我谦虚又宽容,但是有三种人我无法忍受",
380 | "虽现狗",
381 | "所累哇多卡纳",
382 | "所罗门哟,我又回来了",
383 | "太太我喜欢你啊",
384 | "躺着也中枪",
385 | "天降软妹",
386 | "甜食是装在另一个胃里的",
387 | "天下漫友是一家",
388 | "天诛八尺,还我公图",
389 | "土豪我们做朋友好不好",
390 | "图样图森破",
391 | "挖掘机技术哪家强",
392 | "万物皆可萌",
393 | "万物皆虚,万事皆允",
394 | "未被穿过的胖次是没有价值的",
395 | "为了保护我们心爱的ooo……成为偶像!",
396 | "为什么放弃治疗",
397 | "为什么没有oo?",
398 | "为什么要伤害我们的脖子",
399 | "为什么要说又呢",
400 | "为王的诞生,献上礼炮!",
401 | "我,秦始皇,打钱",
402 | "我不是 我没有",
403 | "我不需要性爱",
404 | "我不要看繁星",
405 | "我不做人了",
406 | "我曾经把你当做过自慰对象",
407 | "我从未见过有如此厚颜无耻之人",
408 | "我的4S笑而不语",
409 | "我的车里有空调",
410 | "我的妹妹不可能这么可爱",
411 | "我的内心毫无波动,甚至还想笑",
412 | "我的字典里没有oo",
413 | "我的oo已经饥渴难耐了",
414 | "我对普通的oo没有兴趣",
415 | "我给你一次重新组织语言的机会",
416 | "我跟你讲,ooㄋㄟㄋㄟ,赞",
417 | "我还没出力,你就倒下了",
418 | "我好兴奋呀",
419 | "我和你将在那个新世界里成为新的夏娃和夏娃",
420 | "我和我的小伙伴们都惊呆了",
421 | "我怀疑你是oo",
422 | "我会到处乱说吗",
423 | "我今天吃药的时候看到一个新闻",
424 | "我敬你是条汉子",
425 | "我就是高达",
426 | "我就是叫紫妈怎么了",
427 | "我居然在oo上看xx",
428 | "我觉得我还能再抢救一下",
429 | "我觉得我优势很大",
430 | "我开始方了",
431 | "我看过报道,这个人后来死了",
432 | "我考虑了一下还是无法接受啊",
433 | "我可能oo了假的xx",
434 | "我裤子都脱了你就让我看这个",
435 | "我们不用很麻烦很累就可以成佛",
436 | "我们成年人看了都感觉不适",
437 | "我们的同志遍布五湖四海,甚至打入了某些组织的内部",
438 | "我们的宇宙充满了质子,中子,电子,还有奶子",
439 | "我们的征途是星辰大海",
440 | "我们来削弱oo吧",
441 | "我们中出了叛徒",
442 | "我能吞下玻璃而不伤身体",
443 | "我平胸我骄傲,我为国家省布料",
444 | "我凭自己本事oo,为什么要xx",
445 | "我去年买了个表",
446 | "我认为H是不对的",
447 | "我日你先人",
448 | "我上电视了",
449 | "我是输给了地球的重力",
450 | "我听了顿时怒火就上来了",
451 | "我为自己代言",
452 | "我下面给你吃",
453 | "我现在内心感到悲痛欲绝",
454 | "我想静静",
455 | "我想起来了",
456 | "我选择死亡",
457 | "我要成为新世界的卡密",
458 | "我已经看到结局了",
459 | "我有一个大胆的想法",
460 | "我有异议",
461 | "我有知识我自豪",
462 | "我真是个罪孽深重的女人",
463 | "我整个人都oo了",
464 | "我只是路过的○○",
465 | "我ooo就算饿死不会吃你一点东西",
466 | "无敌的oo倒下了",
467 | "无敌是多么寂寞",
468 | "无法直视",
469 | "污姬白凤丸",
470 | "吾心吾行澄如明镜,所作所为皆为正义",
471 | "吓得我都oo了",
472 | "下个ID见",
473 | "羡慕嫉妒恨",
474 | "现实就是个垃圾游戏",
475 | "现已加入肯德基豪华午餐",
476 | "咸鱼王,我当定了",
477 | "现在,我的手中抓住了未来",
478 | "现在是你比较强",
479 | "想不到你居然是这种oo",
480 | "乡队员不是在与杰克的搏斗中死了吗",
481 | "向黑恶势力低头",
482 | "想死一次吗",
483 | "相信我,你也可以变成光",
484 | "小火把在闲逛",
485 | "小鸟游家要小心一个叫x太的男人",
486 | "小学生真是太棒了",
487 | "写作oo读作xx",
488 | "心如苍井空似水",
489 | "信息量很大",
490 | "性别不同怎么谈恋爱",
491 | "胸不平何以平天下,乳不巨何以聚人心",
492 | "胸部什么的,明明只是装饰",
493 | "胸刹现场",
494 | "玄不救非,氪不改命",
495 | "亚瑟王不懂人心",
496 | "眼睛,我的眼睛",
497 | "眼睛里进了oo",
498 | "羊角地铁",
499 | "要上了ooo——xx的储备足够吗",
500 | "要优雅,不要污",
501 | "也是蛮拼的",
502 | "一把剑就直接穿过去了",
503 | "一本正经地胡说八道",
504 | "一大波僵尸正在接近",
505 | "一大团广场",
506 | "一代补丁一代神",
507 | "一旦接受了这种设定",
508 | "一定是我打开的方式不对",
509 | "一对百合一对基,剩下一个是苦逼",
510 | "一飞冲天啊,我!",
511 | "一股恋爱喜剧的酸臭味",
512 | "一家人最重要的是整整齐齐",
513 | "已经吃不下了",
514 | "已经没什么好害怕的了",
515 | "已经没有人为我站出来说话,因为他们都被抓走了",
516 | "一脸懵逼",
517 | "以抢钱为宗旨,待旅客如孙子",
518 | "一曲忠诚的赞歌",
519 | "一入oo深似海,从此节操是路人",
520 | "艺术就是爆炸",
521 | "以为是oo吗?残念!是xx!",
522 | "以下省略oo字",
523 | "以牙还牙,加倍奉还",
524 | "一言不合就oo",
525 | "一直被oo,从未被超越",
526 | "因为很重要所以说了两遍",
527 | "因为神圣的F2A链接着我们每一个人",
528 | "因为我是oo",
529 | "樱trick综合征",
530 | "勇士喜欢巨乳有什么错",
531 | "用我一生节操换ooo永不完结",
532 | "又到了交配的季节",
533 | "有个能干的妹妹真好",
534 | "又黑我大oo",
535 | "有家,有爱,有欧派",
536 | "有件事说出来你可能不信",
537 | "友军之围",
538 | "有奇怪的东西混进去了",
539 | "有什么东西要觉醒了",
540 | "有一种杀了他就能升级的感觉",
541 | "远的不是距离,而是次元啊",
542 | "元芳你怎么看",
543 | "远看炮塔吓死人,近看五对负重轮",
544 | "愿天下有情人都是失散多年的亲兄妹",
545 | "在我眼里都是渣",
546 | "暂停学表情",
547 | "怎么办,我也很绝望啊",
548 | "宅男费纸,宅女费电",
549 | "战斗力膨胀",
550 | "战斗力只有5的渣渣",
551 | "战个痛快",
552 | "涨姿势",
553 | "这不科学",
554 | "这点题我给满分",
555 | "这个锅我不背",
556 | "这个男人,有两把刷子",
557 | "这个年纪的男孩子对胸部感兴趣不是理所当然的吗",
558 | "这个时候应该@oo",
559 | "这个oo是会玩儿的",
560 | "这火我不传",
561 | "这就是外国人少的原因",
562 | "这么可爱一定是男孩子",
563 | "这破o吃枣药丸",
564 | "这是何等的灵压啊",
565 | "这是计划的一部分",
566 | "这是禁止事项",
567 | "这是LoveLive",
568 | "这是人干的事吗",
569 | "这是我爸爸在夏威夷教我的",
570 | "这是我最后的波纹",
571 | "这是一道送分题",
572 | "这是一个圈套",
573 | "这是一个神奇的oo",
574 | "这是一个oo的故事",
575 | "这时只要微笑就可以了",
576 | "这首xxx送给oo",
577 | "这虽然是游戏,但可不是闹着玩的",
578 | "这腿我能玩一年",
579 | "这游戏能玩?",
580 | "这种全靠运气的垃圾游戏",
581 | "侦测到在途的聚变打击",
582 | "真当自己大小姐",
583 | "真当oo不上xx",
584 | "真是肤浅",
585 | "真是HIGH到不行",
586 | "真相并非永远只有一个",
587 | "真相永远只有一个",
588 | "正面上我啊",
589 | "之后干了个爽",
590 | "只要出问题C4都能搞定",
591 | "只要打不中就没有什么大不了",
592 | "只要可爱就算是男孩子也没关系",
593 | "只要杀了oo我随便你搞",
594 | "只有oo知道的世界",
595 | "主角胜于嘴炮,反派死于话多",
596 | "诸君,我喜欢oo",
597 | "抓住一只野生的oo",
598 | "专注oo三十年",
599 | "自带BGM",
600 | "自带oo",
601 | "自古二楼出oo",
602 | "自古红蓝出CP",
603 | "自古蓝毛多苦逼",
604 | "自古OP多剧透",
605 | "自古肉番出燃曲",
606 | "自挂东南枝",
607 | "梓喵打酱油",
608 | "字幕组调皮了",
609 | "总有刁民想害朕",
610 | "总有一天你们会看着我画的东西撸",
611 | "总有一天我的生命将抵达终点,而你,将加冕为王",
612 | "走错片场了",
613 | "钻头是男人的浪漫",
614 | "最强的ooo一切都是必然的",
615 | "最上川"
616 | }
617 |
618 | local goodthings =
619 | {
620 | "补番:现在不补,更待何时?",
621 | "逛B站:各种涨姿势",
622 | "抽卡开箱子:哇都是宝贝",
623 | "早起:新的一天干劲满满",
624 | "时间众筹:移动速度变快",
625 | "啪啪啪:啪啪啪啪啪",
626 | "吃鸡:大吉大利,晚上吃鸡!",
627 | "调戏群主:群主害羞地发了张女装照",
628 | "抚摸喵星人:喵?",
629 | "追番:更新好及时啊",
630 | "看书:知识是人类进步的阶梯",
631 | "下馆子:今天餐馆优惠啦",
632 | "看电视:都是喜欢的节目",
633 | "告白:被FFF烧死",
634 | "戴帽子:白色象征权力,绿色代表力量",
635 | "逛H站:硬盘要满了啦",
636 | "立FLAG:做事要靠自己的努力了啦",
637 | "吃馒头:吃米饭是异端",
638 | "出去玩:一天好心情",
639 | "带上伞:没准会下雨",
640 | "逛知乎:各种涨姿势,轮带逛",
641 | "敲代码:虽然不知道写了什么,但是总觉得一定没有bug",
642 | "网购:好多便宜的东西",
643 | "早睡:今晚没有人陪你哦",
644 | "听音乐:和我一起学猫叫~"
645 | }
646 |
647 | local badthings =
648 | {
649 | "补番:各种被剧透",
650 | "逛B站:遇见小学生撕逼",
651 | "抽卡开箱子:都是些什么鬼",
652 | "早起:一整天都想睡",
653 | "时间众筹:-1year",
654 | "啪啪啪:会卡在里面",
655 | "吃鸡:以掉下来就被打死",
656 | "调戏群主:被禁言一个月",
657 | "抚摸喵星人:一嘴毛",
658 | "追番:怎么还没更新",
659 | "看书:看不懂",
660 | "下馆子:又浪费钱出去吃",
661 | "看电视:这节目好假啊",
662 | "告白:好人卡get√",
663 | "戴帽子:被嘲笑",
664 | "逛H站:都是重口味",
665 | "立FLAG:你一定会成功",
666 | "吃馒头:米饭才是王道",
667 | "出去玩:共享单车全都是坏的",
668 | "带上伞:没下雨,被嘲笑",
669 | "逛知乎:知乎小管家把你封了",
670 | "敲代码:知道写了什么,但是就是找不出bug的原因",
671 | "网购:会被坑",
672 | "早睡:会在半夜醒来,然后失眠",
673 | "听音乐:软件卡主,文件丢失"
674 | }
675 | --随机数表代码来自http://www.cnblogs.com/slysky/p/5954053.html
676 | --产生1~~m,若有n的则m~~n的数字表
677 | function table.fillNum(m,n)
678 | local j,k
679 | if n then
680 | j=m
681 | k=n
682 | else
683 | j=1
684 | k=m
685 | end
686 | local t={}
687 | for i=j,k do
688 | table.insert(t,i)
689 | end
690 | return t
691 | end
692 | --产生不相同的从m到n,一共cnt个随机数表
693 | function math.randomx(m,n,cnt,seed)
694 | local tmp=table.fillNum(m,n)
695 | math.randomseed(seed)
696 | local t={}
697 | local x
698 | while cnt>0 do
699 | x = math.random(1,n-m+1)
700 | table.insert(t,tmp[x])
701 | table.remove(tmp,x)
702 | cnt=cnt-1
703 | m=m+1
704 | end
705 | return t
706 | end
707 |
708 | --获取运势结果
709 | function getAlmanac(time,fromqq)
710 | local day = math.floor(time/(3600*24))--取整,唯一的某一天
711 | local seed = fromqq..tostring(day)--今日唯一的随机数种子
712 | local ran = math.randomx(1,#goodthings,6,seed)
713 | local saysTemp = says[math.random(1,#says)]
714 | --恢复随机数种子为随机值
715 | math.randomseed(tostring(os.time()):reverse():sub(1, 6))
716 | return("你的运势如下~\r\n"..
717 | "💡宜:\r\n"..goodthings[ran[1]]..
718 | "\r\n"..goodthings[ran[2]]..
719 | "\r\n"..goodthings[ran[3]]..
720 | "\r\n"..goodthings[ran[4]]..
721 | "\r\n"..
722 | "⛑️忌:\r\n"..badthings[ran[5]]..
723 | "\r\n"..badthings[ran[6]]..
724 | "\r\n"..
725 | "📆日期:"..os.date("%Y年%m月%d日",time).."\r\n"..
726 | "🔋综合幸运指数:"..tostring(math.random(0,100)).."%\r\n"..
727 | "🔖当日吉言:"..saysTemp)
728 | end
729 |
730 | local function almanac(data)
731 | if data.msg == "今日运势" then
732 | return getAlmanac(os.time(),data.qq)
733 | elseif data.msg == "明日运势" then
734 | return getAlmanac(os.time()+3600*24,data.qq)
735 | elseif data.msg == "昨日运势" then
736 | return getAlmanac(os.time()-3600*24,data.qq)
737 | end
738 | end
739 |
740 |
741 | return {--今日运势
742 | check = function (data)
743 | return data.msg=="今日运势" or data.msg=="明日运势" or data.msg=="昨日运势"
744 | end,
745 | run = function (data,sendMessage)
746 | sendMessage(cq.code.at(data.qq)..almanac(data))
747 | return true
748 | end,
749 | explain = function ()
750 | return "🌕昨日/今日/明日运势"
751 | end
752 | }
753 |
--------------------------------------------------------------------------------
/sandbox/bit.lua:
--------------------------------------------------------------------------------
1 | --[[
2 |
3 | LUA MODULE
4 |
5 | bit.numberlua - Bitwise operations implemented in pure Lua as numbers,
6 | with Lua 5.2 'bit32' and (LuaJIT) LuaBitOp 'bit' compatibility interfaces.
7 |
8 | SYNOPSIS
9 |
10 | local bit = require 'bit.numberlua'
11 | print(bit.band(0xff00ff00, 0x00ff00ff)) --> 0xffffffff
12 |
13 | -- Interface providing strong Lua 5.2 'bit32' compatibility
14 | local bit32 = require 'bit.numberlua'.bit32
15 | assert(bit32.band(-1) == 0xffffffff)
16 |
17 | -- Interface providing strong (LuaJIT) LuaBitOp 'bit' compatibility
18 | local bit = require 'bit.numberlua'.bit
19 | assert(bit.tobit(0xffffffff) == -1)
20 |
21 | DESCRIPTION
22 |
23 | This library implements bitwise operations entirely in Lua.
24 | This module is typically intended if for some reasons you don't want
25 | to or cannot install a popular C based bit library like BitOp 'bit' [1]
26 | (which comes pre-installed with LuaJIT) or 'bit32' (which comes
27 | pre-installed with Lua 5.2) but want a similar interface.
28 |
29 | This modules represents bit arrays as non-negative Lua numbers. [1]
30 | It can represent 32-bit bit arrays when Lua is compiled
31 | with lua_Number as double-precision IEEE 754 floating point.
32 |
33 | The module is nearly the most efficient it can be but may be a few times
34 | slower than the C based bit libraries and is orders or magnitude
35 | slower than LuaJIT bit operations, which compile to native code. Therefore,
36 | this library is inferior in performane to the other modules.
37 |
38 | The `xor` function in this module is based partly on Roberto Ierusalimschy's
39 | post in http://lua-users.org/lists/lua-l/2002-09/msg00134.html .
40 |
41 | The included BIT.bit32 and BIT.bit sublibraries aims to provide 100%
42 | compatibility with the Lua 5.2 "bit32" and (LuaJIT) LuaBitOp "bit" library.
43 | This compatbility is at the cost of some efficiency since inputted
44 | numbers are normalized and more general forms (e.g. multi-argument
45 | bitwise operators) are supported.
46 |
47 | STATUS
48 |
49 | WARNING: Not all corner cases have been tested and documented.
50 | Some attempt was made to make these similar to the Lua 5.2 [2]
51 | and LuaJit BitOp [3] libraries, but this is not fully tested and there
52 | are currently some differences. Addressing these differences may
53 | be improved in the future but it is not yet fully determined how to
54 | resolve these differences.
55 |
56 | The BIT.bit32 library passes the Lua 5.2 test suite (bitwise.lua)
57 | http://www.lua.org/tests/5.2/ . The BIT.bit library passes the LuaBitOp
58 | test suite (bittest.lua). However, these have not been tested on
59 | platforms with Lua compiled with 32-bit integer numbers.
60 |
61 | API
62 |
63 | BIT.tobit(x) --> z
64 |
65 | Similar to function in BitOp.
66 |
67 | BIT.tohex(x, n)
68 |
69 | Similar to function in BitOp.
70 |
71 | BIT.band(x, y) --> z
72 |
73 | Similar to function in Lua 5.2 and BitOp but requires two arguments.
74 |
75 | BIT.bor(x, y) --> z
76 |
77 | Similar to function in Lua 5.2 and BitOp but requires two arguments.
78 |
79 | BIT.bxor(x, y) --> z
80 |
81 | Similar to function in Lua 5.2 and BitOp but requires two arguments.
82 |
83 | BIT.bnot(x) --> z
84 |
85 | Similar to function in Lua 5.2 and BitOp.
86 |
87 | BIT.lshift(x, disp) --> z
88 |
89 | Similar to function in Lua 5.2 (warning: BitOp uses unsigned lower 5 bits of shift),
90 |
91 | BIT.rshift(x, disp) --> z
92 |
93 | Similar to function in Lua 5.2 (warning: BitOp uses unsigned lower 5 bits of shift),
94 |
95 | BIT.extract(x, field [, width]) --> z
96 |
97 | Similar to function in Lua 5.2.
98 |
99 | BIT.replace(x, v, field, width) --> z
100 |
101 | Similar to function in Lua 5.2.
102 |
103 | BIT.bswap(x) --> z
104 |
105 | Similar to function in Lua 5.2.
106 |
107 | BIT.rrotate(x, disp) --> z
108 | BIT.ror(x, disp) --> z
109 |
110 | Similar to function in Lua 5.2 and BitOp.
111 |
112 | BIT.lrotate(x, disp) --> z
113 | BIT.rol(x, disp) --> z
114 |
115 | Similar to function in Lua 5.2 and BitOp.
116 |
117 | BIT.arshift
118 |
119 | Similar to function in Lua 5.2 and BitOp.
120 |
121 | BIT.btest
122 |
123 | Similar to function in Lua 5.2 with requires two arguments.
124 |
125 | BIT.bit32
126 |
127 | This table contains functions that aim to provide 100% compatibility
128 | with the Lua 5.2 "bit32" library.
129 |
130 | bit32.arshift (x, disp) --> z
131 | bit32.band (...) --> z
132 | bit32.bnot (x) --> z
133 | bit32.bor (...) --> z
134 | bit32.btest (...) --> true | false
135 | bit32.bxor (...) --> z
136 | bit32.extract (x, field [, width]) --> z
137 | bit32.replace (x, v, field [, width]) --> z
138 | bit32.lrotate (x, disp) --> z
139 | bit32.lshift (x, disp) --> z
140 | bit32.rrotate (x, disp) --> z
141 | bit32.rshift (x, disp) --> z
142 |
143 | BIT.bit
144 |
145 | This table contains functions that aim to provide 100% compatibility
146 | with the LuaBitOp "bit" library (from LuaJIT).
147 |
148 | bit.tobit(x) --> y
149 | bit.tohex(x [,n]) --> y
150 | bit.bnot(x) --> y
151 | bit.bor(x1 [,x2...]) --> y
152 | bit.band(x1 [,x2...]) --> y
153 | bit.bxor(x1 [,x2...]) --> y
154 | bit.lshift(x, n) --> y
155 | bit.rshift(x, n) --> y
156 | bit.arshift(x, n) --> y
157 | bit.rol(x, n) --> y
158 | bit.ror(x, n) --> y
159 | bit.bswap(x) --> y
160 |
161 | DEPENDENCIES
162 |
163 | None (other than Lua 5.1 or 5.2).
164 |
165 | DOWNLOAD/INSTALLATION
166 |
167 | If using LuaRocks:
168 | luarocks install lua-bit-numberlua
169 |
170 | Otherwise, download .
171 | Alternately, if using git:
172 | git clone git://github.com/davidm/lua-bit-numberlua.git
173 | cd lua-bit-numberlua
174 | Optionally unpack:
175 | ./util.mk
176 | or unpack and install in LuaRocks:
177 | ./util.mk install
178 |
179 | REFERENCES
180 |
181 | [1] http://lua-users.org/wiki/FloatingPoint
182 | [2] http://www.lua.org/manual/5.2/
183 | [3] http://bitop.luajit.org/
184 |
185 | LICENSE
186 |
187 | (c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
188 |
189 | Permission is hereby granted, free of charge, to any person obtaining a copy
190 | of this software and associated documentation files (the "Software"), to deal
191 | in the Software without restriction, including without limitation the rights
192 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
193 | copies of the Software, and to permit persons to whom the Software is
194 | furnished to do so, subject to the following conditions:
195 |
196 | The above copyright notice and this permission notice shall be included in
197 | all copies or substantial portions of the Software.
198 |
199 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
200 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
201 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
202 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
203 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
204 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
205 | THE SOFTWARE.
206 | (end license)
207 |
208 | --]]
209 |
210 | local M = {_TYPE='module', _NAME='bit.numberlua', _VERSION='0.3.1.20120131'}
211 |
212 | local floor = math.floor
213 |
214 | local MOD = 2^32
215 | local MODM = MOD-1
216 |
217 | local function memoize(f)
218 | local mt = {}
219 | local t = setmetatable({}, mt)
220 | function mt:__index(k)
221 | local v = f(k); t[k] = v
222 | return v
223 | end
224 | return t
225 | end
226 |
227 | local function make_bitop_uncached(t, m)
228 | local function bitop(a, b)
229 | local res,p = 0,1
230 | while a ~= 0 and b ~= 0 do
231 | local am, bm = a%m, b%m
232 | res = res + t[am][bm]*p
233 | a = (a - am) / m
234 | b = (b - bm) / m
235 | p = p*m
236 | end
237 | res = res + (a+b)*p
238 | return res
239 | end
240 | return bitop
241 | end
242 |
243 | local function make_bitop(t)
244 | local op1 = make_bitop_uncached(t,2^1)
245 | local op2 = memoize(function(a)
246 | return memoize(function(b)
247 | return op1(a, b)
248 | end)
249 | end)
250 | return make_bitop_uncached(op2, 2^(t.n or 1))
251 | end
252 |
253 | -- ok? probably not if running on a 32-bit int Lua number type platform
254 | function M.tobit(x)
255 | return x % 2^32
256 | end
257 |
258 | M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4}
259 | local bxor = M.bxor
260 |
261 | function M.bnot(a) return MODM - a end
262 | local bnot = M.bnot
263 |
264 | function M.band(a,b) return ((a+b) - bxor(a,b))/2 end
265 | local band = M.band
266 |
267 | function M.bor(a,b) return MODM - band(MODM - a, MODM - b) end
268 | local bor = M.bor
269 |
270 | local lshift, rshift -- forward declare
271 |
272 | function M.rshift(a,disp) -- Lua5.2 insipred
273 | if disp < 0 then return lshift(a,-disp) end
274 | return floor(a % 2^32 / 2^disp)
275 | end
276 | rshift = M.rshift
277 |
278 | function M.lshift(a,disp) -- Lua5.2 inspired
279 | if disp < 0 then return rshift(a,-disp) end
280 | return (a * 2^disp) % 2^32
281 | end
282 | lshift = M.lshift
283 |
284 | function M.tohex(x, n) -- BitOp style
285 | n = n or 8
286 | local up
287 | if n <= 0 then
288 | if n == 0 then return '' end
289 | up = true
290 | n = - n
291 | end
292 | x = band(x, 16^n-1)
293 | return ('%0'..n..(up and 'X' or 'x')):format(x)
294 | end
295 | local tohex = M.tohex
296 |
297 | function M.extract(n, field, width) -- Lua5.2 inspired
298 | width = width or 1
299 | return band(rshift(n, field), 2^width-1)
300 | end
301 | local extract = M.extract
302 |
303 | function M.replace(n, v, field, width) -- Lua5.2 inspired
304 | width = width or 1
305 | local mask1 = 2^width-1
306 | v = band(v, mask1) -- required by spec?
307 | local mask = bnot(lshift(mask1, field))
308 | return band(n, mask) + lshift(v, field)
309 | end
310 | local replace = M.replace
311 |
312 | function M.bswap(x) -- BitOp style
313 | local a = band(x, 0xff); x = rshift(x, 8)
314 | local b = band(x, 0xff); x = rshift(x, 8)
315 | local c = band(x, 0xff); x = rshift(x, 8)
316 | local d = band(x, 0xff)
317 | return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
318 | end
319 | local bswap = M.bswap
320 |
321 | function M.rrotate(x, disp) -- Lua5.2 inspired
322 | disp = disp % 32
323 | local low = band(x, 2^disp-1)
324 | return rshift(x, disp) + lshift(low, 32-disp)
325 | end
326 | local rrotate = M.rrotate
327 |
328 | function M.lrotate(x, disp) -- Lua5.2 inspired
329 | return rrotate(x, -disp)
330 | end
331 | local lrotate = M.lrotate
332 |
333 | M.rol = M.lrotate -- LuaOp inspired
334 | M.ror = M.rrotate -- LuaOp insipred
335 |
336 |
337 | function M.arshift(x, disp) -- Lua5.2 inspired
338 | local z = rshift(x, disp)
339 | if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
340 | return z
341 | end
342 | local arshift = M.arshift
343 |
344 | function M.btest(x, y) -- Lua5.2 inspired
345 | return band(x, y) ~= 0
346 | end
347 |
348 | --
349 | -- Start Lua 5.2 "bit32" compat section.
350 | --
351 |
352 | M.bit32 = {} -- Lua 5.2 'bit32' compatibility
353 |
354 |
355 | local function bit32_bnot(x)
356 | return (-1 - x) % MOD
357 | end
358 | M.bit32.bnot = bit32_bnot
359 |
360 | local function bit32_bxor(a, b, c, ...)
361 | local z
362 | if b then
363 | a = a % MOD
364 | b = b % MOD
365 | z = bxor(a, b)
366 | if c then
367 | z = bit32_bxor(z, c, ...)
368 | end
369 | return z
370 | elseif a then
371 | return a % MOD
372 | else
373 | return 0
374 | end
375 | end
376 | M.bit32.bxor = bit32_bxor
377 |
378 | local function bit32_band(a, b, c, ...)
379 | local z
380 | if b then
381 | a = a % MOD
382 | b = b % MOD
383 | z = ((a+b) - bxor(a,b)) / 2
384 | if c then
385 | z = bit32_band(z, c, ...)
386 | end
387 | return z
388 | elseif a then
389 | return a % MOD
390 | else
391 | return MODM
392 | end
393 | end
394 | M.bit32.band = bit32_band
395 |
396 | local function bit32_bor(a, b, c, ...)
397 | local z
398 | if b then
399 | a = a % MOD
400 | b = b % MOD
401 | z = MODM - band(MODM - a, MODM - b)
402 | if c then
403 | z = bit32_bor(z, c, ...)
404 | end
405 | return z
406 | elseif a then
407 | return a % MOD
408 | else
409 | return 0
410 | end
411 | end
412 | M.bit32.bor = bit32_bor
413 |
414 | function M.bit32.btest(...)
415 | return bit32_band(...) ~= 0
416 | end
417 |
418 | function M.bit32.lrotate(x, disp)
419 | return lrotate(x % MOD, disp)
420 | end
421 |
422 | function M.bit32.rrotate(x, disp)
423 | return rrotate(x % MOD, disp)
424 | end
425 |
426 | function M.bit32.lshift(x,disp)
427 | if disp > 31 or disp < -31 then return 0 end
428 | return lshift(x % MOD, disp)
429 | end
430 |
431 | function M.bit32.rshift(x,disp)
432 | if disp > 31 or disp < -31 then return 0 end
433 | return rshift(x % MOD, disp)
434 | end
435 |
436 | function M.bit32.arshift(x,disp)
437 | x = x % MOD
438 | if disp >= 0 then
439 | if disp > 31 then
440 | return (x >= 0x80000000) and MODM or 0
441 | else
442 | local z = rshift(x, disp)
443 | if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
444 | return z
445 | end
446 | else
447 | return lshift(x, -disp)
448 | end
449 | end
450 |
451 | function M.bit32.extract(x, field, ...)
452 | local width = ... or 1
453 | if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
454 | x = x % MOD
455 | return extract(x, field, ...)
456 | end
457 |
458 | function M.bit32.replace(x, v, field, ...)
459 | local width = ... or 1
460 | if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
461 | x = x % MOD
462 | v = v % MOD
463 | return replace(x, v, field, ...)
464 | end
465 |
466 |
467 | --
468 | -- Start LuaBitOp "bit" compat section.
469 | --
470 |
471 | M.bit = {} -- LuaBitOp "bit" compatibility
472 |
473 | function M.bit.tobit(x)
474 | x = x % MOD
475 | if x >= 0x80000000 then x = x - MOD end
476 | return x
477 | end
478 | local bit_tobit = M.bit.tobit
479 |
480 | function M.bit.tohex(x, ...)
481 | return tohex(x % MOD, ...)
482 | end
483 |
484 | function M.bit.bnot(x)
485 | return bit_tobit(bnot(x % MOD))
486 | end
487 |
488 | local function bit_bor(a, b, c, ...)
489 | if c then
490 | return bit_bor(bit_bor(a, b), c, ...)
491 | elseif b then
492 | return bit_tobit(bor(a % MOD, b % MOD))
493 | else
494 | return bit_tobit(a)
495 | end
496 | end
497 | M.bit.bor = bit_bor
498 |
499 | local function bit_band(a, b, c, ...)
500 | if c then
501 | return bit_band(bit_band(a, b), c, ...)
502 | elseif b then
503 | return bit_tobit(band(a % MOD, b % MOD))
504 | else
505 | return bit_tobit(a)
506 | end
507 | end
508 | M.bit.band = bit_band
509 |
510 | local function bit_bxor(a, b, c, ...)
511 | if c then
512 | return bit_bxor(bit_bxor(a, b), c, ...)
513 | elseif b then
514 | return bit_tobit(bxor(a % MOD, b % MOD))
515 | else
516 | return bit_tobit(a)
517 | end
518 | end
519 | M.bit.bxor = bit_bxor
520 |
521 | function M.bit.lshift(x, n)
522 | return bit_tobit(lshift(x % MOD, n % 32))
523 | end
524 |
525 | function M.bit.rshift(x, n)
526 | return bit_tobit(rshift(x % MOD, n % 32))
527 | end
528 |
529 | function M.bit.arshift(x, n)
530 | return bit_tobit(arshift(x % MOD, n % 32))
531 | end
532 |
533 | function M.bit.rol(x, n)
534 | return bit_tobit(lrotate(x % MOD, n % 32))
535 | end
536 |
537 | function M.bit.ror(x, n)
538 | return bit_tobit(rrotate(x % MOD, n % 32))
539 | end
540 |
541 | function M.bit.bswap(x)
542 | return bit_tobit(bswap(x % MOD))
543 | end
544 |
545 | return M
546 |
--------------------------------------------------------------------------------
/require/XmlParser.lua:
--------------------------------------------------------------------------------
1 | --- @module Class providing the actual XML parser.
2 | -- Available options are:
3 | -- * stripWS
4 | -- Strip non-significant whitespace (leading/trailing)
5 | -- and do not generate events for empty text elements
6 | --
7 | -- * expandEntities
8 | -- Expand entities (standard entities + single char
9 | -- numeric entities only currently - could be extended
10 | -- at runtime if suitable DTD parser added elements
11 | -- to table (see obj._ENTITIES). May also be possible
12 | -- to expand multibyre entities for UTF-8 only
13 | --
14 | -- * errorHandler
15 | -- Custom error handler function
16 | --
17 | -- NOTE: Boolean options must be set to 'nil' not '0'
18 |
19 | ---Converts the decimal code of a character to its corresponding char
20 | --if it's a graphical char, otherwise, returns the HTML ISO code
21 | --for that decimal value in the format code
22 | --@param code the decimal value to convert to its respective character
23 | local function decimalToHtmlChar(code)
24 | local n = tonumber(code)
25 | if n >= 0 and n < 256 then
26 | return string.char(n)
27 | else
28 | return ""..code..";"
29 | end
30 | end
31 |
32 | ---Converts the hexadecimal code of a character to its corresponding char
33 | --if it's a graphical char, otherwise, returns the HTML ISO code
34 | --for that hexadecimal value in the format ode
35 | --@param code the hexadecimal value to convert to its respective character
36 | local function hexadecimalToHtmlChar(code)
37 | local n = tonumber(code, 16)
38 | if n >= 0 and n < 256 then
39 | return string.char(n)
40 | else
41 | return ""..code..";"
42 | end
43 | end
44 |
45 | local XmlParser = {
46 | -- Private attribures/functions
47 | _XML = '^([^<]*)<(%/?)([^>]-)(%/?)>',
48 | _ATTR1 = '([%w-:_]+)%s*=%s*"(.-)"',
49 | _ATTR2 = '([%w-:_]+)%s*=%s*\'(.-)\'',
50 | _CDATA = '<%!%[CDATA%[(.-)%]%]>',
51 | _PI = '<%?(.-)%?>',
52 | _COMMENT = '',
53 | _TAG = '^(.-)%s.*',
54 | _LEADINGWS = '^%s+',
55 | _TRAILINGWS = '%s+$',
56 | _WS = '^%s*$',
57 | _DTD1 = '',
58 | _DTD2 = '',
59 | _DTD3 = '',
60 | _DTD4 = '',
61 | _DTD5 = '',
62 |
63 | --Matches an attribute with non-closing double quotes (The equal sign is matched non-greedly by using =+?)
64 | _ATTRERR1 = '=+?%s*"[^"]*$',
65 | --Matches an attribute with non-closing single quotes (The equal sign is matched non-greedly by using =+?)
66 | _ATTRERR2 = '=+?%s*\'[^\']*$',
67 | --Matches a closing tag such as or the end of a openning tag such as
68 | _TAGEXT = '(%/?)>',
69 |
70 | _errstr = {
71 | xmlErr = "Error Parsing XML",
72 | declErr = "Error Parsing XMLDecl",
73 | declStartErr = "XMLDecl not at start of document",
74 | declAttrErr = "Invalid XMLDecl attributes",
75 | piErr = "Error Parsing Processing Instruction",
76 | commentErr = "Error Parsing Comment",
77 | cdataErr = "Error Parsing CDATA",
78 | dtdErr = "Error Parsing DTD",
79 | endTagErr = "End Tag Attributes Invalid",
80 | unmatchedTagErr = "Unbalanced Tag",
81 | incompleteXmlErr = "Incomplete XML Document",
82 | },
83 |
84 | _ENTITIES = {
85 | ["<"] = "<",
86 | [">"] = ">",
87 | ["&"] = "&",
88 | ["""] = '"',
89 | ["'"] = "'",
90 | ["(%d+);"] = decimalToHtmlChar,
91 | ["(%x+);"] = hexadecimalToHtmlChar,
92 | },
93 | }
94 |
95 | --- Instantiates a XmlParser object.
96 | --@param _handler Handler module to be used to convert the XML string
97 | -- to another formats. See the available handlers at the handler directory.
98 | -- Usually you get an instance to a handler module using, for instance:
99 | -- local handler = require("xmlhandler/tree").
100 | --@param _options Options for this XmlParser instance.
101 | --@see XmlParser.options
102 | function XmlParser.new(_handler, _options)
103 | local obj = {
104 | handler = _handler,
105 | options = _options,
106 | _stack = {}
107 | }
108 |
109 | setmetatable(obj, XmlParser)
110 | obj.__index = XmlParser
111 | return obj;
112 | end
113 |
114 | ---Checks if a function/field exists in a table or in its metatable
115 | --@param table the table to check if it has a given function
116 | --@param elementName the name of the function/field to check if exists
117 | --@return true if the function/field exists, false otherwise
118 | local function fexists(table, elementName)
119 | if table == nil then
120 | return false
121 | end
122 |
123 | if table[elementName] ~= nil then
124 | return true
125 | else
126 | return fexists(getmetatable(table), elementName)
127 | end
128 | end
129 |
130 | local function err(self, err, pos)
131 | if self.options.errorHandler then
132 | self.options.errorHandler(err,pos)
133 | end
134 | end
135 |
136 | --- Removes whitespaces
137 | local function stripWS(self, s)
138 | if self.options.stripWS then
139 | s = string.gsub(s,'^%s+','')
140 | s = string.gsub(s,'%s+$','')
141 | end
142 | return s
143 | end
144 |
145 | local function parseEntities(self, s)
146 | if self.options.expandEntities then
147 | for k,v in pairs(self._ENTITIES) do
148 | s = string.gsub(s,k,v)
149 | end
150 | end
151 |
152 | return s
153 | end
154 |
155 | --- Parses a string representing a tag.
156 | --@param s String containing tag text
157 | --@return a {name, attrs} table
158 | -- where name is the name of the tag and attrs
159 | -- is a table containing the atributtes of the tag
160 | local function parseTag(self, s)
161 | local tag = {
162 | name = string.gsub(s, self._TAG, '%1'),
163 | attrs = {}
164 | }
165 |
166 | local parseFunction = function (k, v)
167 | tag.attrs[k] = parseEntities(self, v)
168 | tag.attrs._ = 1
169 | end
170 |
171 | string.gsub(s, self._ATTR1, parseFunction)
172 | string.gsub(s, self._ATTR2, parseFunction)
173 |
174 | if tag.attrs._ then
175 | tag.attrs._ = nil
176 | else
177 | tag.attrs = nil
178 | end
179 |
180 | return tag
181 | end
182 |
183 | local function parseXmlDeclaration(self, xml, f)
184 | -- XML Declaration
185 | f.match, f.endMatch, f.text = string.find(xml, self._PI, f.pos)
186 | if not f.match then
187 | err(self, self._errstr.declErr, f.pos)
188 | end
189 |
190 | if f.match ~= 1 then
191 | -- Must be at start of doc if present
192 | err(self, self._errstr.declStartErr, f.pos)
193 | end
194 |
195 | local tag = parseTag(self, f.text)
196 | -- TODO: Check if attributes are valid
197 | -- Check for version (mandatory)
198 | if tag.attrs and tag.attrs.version == nil then
199 | err(self, self._errstr.declAttrErr, f.pos)
200 | end
201 |
202 | if fexists(self.handler, 'decl') then
203 | self.handler:decl(tag, f.match, f.endMatch)
204 | end
205 |
206 | return tag
207 | end
208 |
209 | local function parseXmlProcessingInstruction(self, xml, f)
210 | local tag = {}
211 |
212 | -- XML Processing Instruction (PI)
213 | f.match, f.endMatch, f.text = string.find(xml, self._PI, f.pos)
214 | if not f.match then
215 | err(self, self._errstr.piErr, f.pos)
216 | end
217 | if fexists(self.handler, 'pi') then
218 | -- Parse PI attributes & text
219 | tag = parseTag(self, f.text)
220 | local pi = string.sub(f.text, string.len(tag.name)+1)
221 | if pi ~= "" then
222 | if tag.attrs then
223 | tag.attrs._text = pi
224 | else
225 | tag.attrs = { _text = pi }
226 | end
227 | end
228 | self.handler:pi(tag, f.match, f.endMatch)
229 | end
230 |
231 | return tag
232 | end
233 |
234 | local function parseComment(self, xml, f)
235 | f.match, f.endMatch, f.text = string.find(xml, self._COMMENT, f.pos)
236 | if not f.match then
237 | err(self, self._errstr.commentErr, f.pos)
238 | end
239 |
240 | if fexists(self.handler, 'comment') then
241 | f.text = parseEntities(self, stripWS(self, f.text))
242 | self.handler:comment(f.text, next, f.match, f.endMatch)
243 | end
244 | end
245 |
246 | local function _parseDtd(self, xml, pos)
247 | -- match,endMatch,root,type,name,uri,internal
248 | local m,e,r,t,n,u,i
249 |
250 | m,e,r,t,u,i = string.find(xml, self._DTD1,pos)
251 | if m then
252 | return m, e, {_root=r,_type=t,_uri=u,_internal=i}
253 | end
254 |
255 | m,e,r,t,n,u,i = string.find(xml, self._DTD2,pos)
256 | if m then
257 | return m, e, {_root=r,_type=t,_name=n,_uri=u,_internal=i}
258 | end
259 |
260 | m,e,r,i = string.find(xml, self._DTD3,pos)
261 | if m then
262 | return m, e, {_root=r,_internal=i}
263 | end
264 |
265 | m,e,r,t,u = string.find(s,self._DTD4,pos)
266 | if m then
267 | return m,e,{_root=r,_type=t,_uri=u}
268 | end
269 |
270 | m,e,r,t,n,u = string.find(s,self._DTD5,pos)
271 | if m then
272 | return m,e,{_root=r,_type=t,_name=n,_uri=u}
273 | end
274 |
275 | return nil
276 | end
277 |
278 | local function parseDtd(self, xml, f)
279 | f.match, f.endMatch, attrs = self:_parseDtd(xml, f.pos)
280 | if not f.match then
281 | err(self, self._errstr.dtdErr, f.pos)
282 | end
283 |
284 | if fexists(self.handler, 'dtd') then
285 | self.handler:dtd(attrs._root, attrs, f.match, f.endMatch)
286 | end
287 | end
288 |
289 | local function parseCdata(self, xml, f)
290 | f.match, f.endMatch, f.text = string.find(xml, self._CDATA, f.pos)
291 | if not f.match then
292 | err(self, self._errstr.cdataErr, f.pos)
293 | end
294 |
295 | if fexists(self.handler, 'cdata') then
296 | self.handler:cdata(f.text, nil, f.match, f.endMatch)
297 | end
298 | end
299 |
300 | --- Parse a Normal tag
301 | -- Need check for embedded '>' in attribute value and extend
302 | -- match recursively if necessary eg.
303 | local function parseNormalTag(self, xml, f)
304 | --Check for errors
305 | while 1 do
306 | --If there isn't an attribute without closing quotes (single or double quotes)
307 | --then breaks to follow the normal processing of the tag.
308 | --Otherwise, try to find where the quotes close.
309 | f.errStart, f.errEnd = string.find(f.tagstr, self._ATTRERR1)
310 |
311 | if f.errEnd == nil then
312 | f.errStart, f.errEnd = string.find(f.tagstr, self._ATTRERR2)
313 | if f.errEnd == nil then
314 | break
315 | end
316 | end
317 |
318 | f.extStart, f.extEnd, f.endt2 = string.find(xml, self._TAGEXT, f.endMatch+1)
319 | f.tagstr = f.tagstr .. string.sub(xml, f.endMatch, f.extEnd-1)
320 | if not f.match then
321 | err(self, self._errstr.xmlErr, f.pos)
322 | end
323 | f.endMatch = f.extEnd
324 | end
325 |
326 | -- Extract tag name and attrs
327 | local tag = parseTag(self, f.tagstr)
328 |
329 | if (f.endt1=="/") then
330 | if fexists(self.handler, 'endtag') then
331 | if tag.attrs then
332 | -- Shouldn't have any attributes in endtag
333 | err(self, string.format("%s (/%s)", self._errstr.endTagErr, tag.name), f.pos)
334 | end
335 | if table.remove(self._stack) ~= tag.name then
336 | err(self, string.format("%s (/%s)", self._errstr.unmatchedTagErr, tag.name), f.pos)
337 | end
338 | self.handler:endtag(tag, f.match, f.endMatch)
339 | end
340 | else
341 | table.insert(self._stack, tag.name)
342 | if fexists(self.handler, 'starttag') then
343 | self.handler:starttag(tag, f.match, f.endMatch)
344 | end
345 | --TODO: Tags com fechamento automático estão sendo
346 | --retornadas como uma tabela, o que complica
347 | --para a app NCLua tratar isso. É preciso
348 | --fazer com que seja retornado um campo string vazio.
349 |
350 | -- Self-Closing Tag
351 | if (f.endt2=="/") then
352 | table.remove(self._stack)
353 | if fexists(self.handler, 'endtag') then
354 | self.handler:endtag(tag, f.match, f.endMatch)
355 | end
356 | end
357 | end
358 |
359 | return tag
360 | end
361 |
362 | local function parseTagType(self, xml, f)
363 | -- Test for tag type
364 | if string.find(string.sub(f.tagstr, 1, 5), "?xml%s") then
365 | parseXmlDeclaration(self, xml, f)
366 | elseif string.sub(f.tagstr, 1, 1) == "?" then
367 | parseXmlProcessingInstruction(self, xml, f)
368 | elseif string.sub(f.tagstr, 1, 3) == "!--" then
369 | parseComment(self, xml, f)
370 | elseif string.sub(f.tagstr, 1, 8) == "!DOCTYPE" then
371 | parseDtd(self, xml, f)
372 | elseif string.sub(f.tagstr, 1, 8) == "![CDATA[" then
373 | parseCdata(self, xml, f)
374 | else
375 | parseNormalTag(self, xml, f)
376 | end
377 | end
378 |
379 | --- Get next tag (first pass - fix exceptions below).
380 | --@return true if the next tag could be got, false otherwise
381 | local function getNextTag(self, xml, f)
382 | f.match, f.endMatch, f.text, f.endt1, f.tagstr, f.endt2 = string.find(xml, self._XML, f.pos)
383 | if not f.match then
384 | if string.find(xml, self._WS, f.pos) then
385 | -- No more text - check document complete
386 | if #self._stack ~= 0 then
387 | err(self, self._errstr.incompleteXmlErr, f.pos)
388 | else
389 | return false
390 | end
391 | else
392 | -- Unparsable text
393 | err(self, self._errstr.xmlErr, f.pos)
394 | end
395 | end
396 |
397 | f.text = f.text or ''
398 | f.tagstr = f.tagstr or ''
399 | f.match = f.match or 0
400 |
401 | return f.endMatch ~= nil
402 | end
403 |
404 | --Main function which starts the XML parsing process
405 | --@param xml the XML string to parse
406 | --@param parseAttributes indicates if tag attributes should be parsed or not.
407 | -- If omitted, the default value is true.
408 | function XmlParser:parse(xml, parseAttributes)
409 | if type(self) ~= "table" or getmetatable(self) ~= XmlParser then
410 | error("You must call xmlparser:parse(parameters) instead of xmlparser.parse(parameters)")
411 | end
412 |
413 | if parseAttributes == nil then
414 | parseAttributes = true
415 | end
416 |
417 | self.handler.parseAttributes = parseAttributes
418 |
419 | --Stores string.find results and parameters
420 | --and other auxiliar variables
421 | local f = {
422 | --string.find return
423 | match = 0,
424 | endMatch = 0,
425 | -- text, end1, tagstr, end2,
426 |
427 | --string.find parameters and auxiliar variables
428 | pos = 1,
429 | -- startText, endText,
430 | -- errStart, errEnd, extStart, extEnd,
431 | }
432 |
433 | while f.match do
434 | if not getNextTag(self, xml, f) then
435 | break
436 | end
437 |
438 | -- Handle leading text
439 | f.startText = f.match
440 | f.endText = f.match + string.len(f.text) - 1
441 | f.match = f.match + string.len(f.text)
442 | f.text = parseEntities(self, stripWS(self, f.text))
443 | if f.text ~= "" and fexists(self.handler, 'text') then
444 | self.handler:text(f.text, nil, f.match, f.endText)
445 | end
446 |
447 | parseTagType(self, xml, f)
448 | f.pos = f.endMatch + 1
449 | end
450 | end
451 |
452 | XmlParser.__index = XmlParser
453 | return XmlParser
454 |
--------------------------------------------------------------------------------
|