├── .vscode └── settings.json ├── LICENSE ├── README.md ├── events ├── AppEnable.lua ├── GroupAddInvite.lua ├── GroupAddRequest.lua ├── GroupFileUpload.lua ├── GroupManageRemove.lua ├── GroupManageSet.lua ├── GroupMemberJoin.lua ├── GroupMemberLeave.lua ├── MQTT.lua ├── Message.lua └── ReceiveTcp.lua ├── main.lua ├── require ├── JSON.lua ├── XmlParser.lua ├── apps │ ├── 00add.lua │ ├── 01delall.lua │ ├── 02del.lua │ ├── 03list.lua │ ├── 04addadmin.lua │ ├── 05deladmin.lua │ ├── 06almanac.lua │ ├── 07air.lua │ ├── 08qqmusic.lua │ ├── 09animeSearch.lua │ ├── 10chess.lua │ ├── 11banPlay.lua │ ├── 12sign.lua │ ├── 13av.lua │ ├── 14hitokoto.lua │ ├── 15bing.lua │ ├── 16rust.lua │ ├── 17homo.lua │ ├── 18car.lua │ ├── 19sese.lua │ ├── 20say.lua │ ├── 95poweron.lua │ ├── 96minecraft.lua │ ├── 97code.lua │ ├── 98robot.lua │ └── 99common.lua ├── chess │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── a.png │ ├── b.png │ ├── bg.png │ ├── box.png │ ├── c.png │ ├── d.png │ ├── e.png │ ├── f.png │ └── g.png ├── cq.lua ├── minecraft.lua ├── say │ ├── e.png │ ├── head_cover.png │ ├── m.png │ └── s.png ├── sese.lua ├── strings.lua ├── xml2lua.lua └── xmlhandler │ ├── README.md │ ├── dom.lua │ ├── print.lua │ └── tree.lua └── sandbox ├── JSON.lua ├── bit.lua ├── head.lua ├── misc.lua ├── nvm.lua └── utils.lua /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # receiver-meow-lua 2 | 3 | [![license](https://img.shields.io/github/license/chenxuuu/receiver-meow-lua)](https://github.com/chenxuuu/receiver-meow-lua/blob/master/LICENSE) 4 | [![receiver-meow](https://img.shields.io/badge/dependencies-receiver_meow-blueviolet.svg)](https://github.com/chenxuuu/receiver-meow) 5 | [![code-size](https://img.shields.io/github/languages/code-size/chenxuuu/receiver-meow-lua.svg)](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 | -------------------------------------------------------------------------------- /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/GroupAddInvite.lua: -------------------------------------------------------------------------------- 1 | return function (data) 2 | 3 | end 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/GroupManageRemove.lua: -------------------------------------------------------------------------------- 1 | return function (data) 2 | cq.sendGroupMsg(data.group,"群成员"..cq.code.at(data.qq).."变回了人类!") 3 | end 4 | -------------------------------------------------------------------------------- /events/GroupManageSet.lua: -------------------------------------------------------------------------------- 1 | return function (data) 2 | cq.sendGroupMsg(data.group,"群成员"..cq.code.at(data.qq).."成为了狗管理!") 3 | end 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 "&#x"..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(%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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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/chess/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/1.png -------------------------------------------------------------------------------- /require/chess/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/2.png -------------------------------------------------------------------------------- /require/chess/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/3.png -------------------------------------------------------------------------------- /require/chess/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/4.png -------------------------------------------------------------------------------- /require/chess/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/5.png -------------------------------------------------------------------------------- /require/chess/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/6.png -------------------------------------------------------------------------------- /require/chess/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/7.png -------------------------------------------------------------------------------- /require/chess/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/a.png -------------------------------------------------------------------------------- /require/chess/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/b.png -------------------------------------------------------------------------------- /require/chess/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/bg.png -------------------------------------------------------------------------------- /require/chess/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/box.png -------------------------------------------------------------------------------- /require/chess/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/c.png -------------------------------------------------------------------------------- /require/chess/d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/d.png -------------------------------------------------------------------------------- /require/chess/e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/e.png -------------------------------------------------------------------------------- /require/chess/f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/f.png -------------------------------------------------------------------------------- /require/chess/g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/chess/g.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/say/e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/say/e.png -------------------------------------------------------------------------------- /require/say/head_cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/say/head_cover.png -------------------------------------------------------------------------------- /require/say/m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/say/m.png -------------------------------------------------------------------------------- /require/say/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenxuuu/receiver-meow-lua/f6d7f1db024bf02cd78b847aa9e5f9d7b731ae87/require/say/s.png -------------------------------------------------------------------------------- /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/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/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/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. -------------------------------------------------------------------------------- /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/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 -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------