From 3789a3522bec1fcc6b52e326fde61f98a5b27499 Mon Sep 17 00:00:00 2001 From: Akkariin Meiko Date: Sat, 3 Aug 2019 11:26:26 +0800 Subject: [PATCH] Create main_server.lua --- main_server.lua | 581 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 581 insertions(+) create mode 100644 main_server.lua diff --git a/main_server.lua b/main_server.lua new file mode 100644 index 0000000..4d9b812 --- /dev/null +++ b/main_server.lua @@ -0,0 +1,581 @@ +-- FiveM YumV plugin by Akkariin +-- This plugin is an open-source project +-- Use GPL v3 License +-- https://github.com/kasuganosoras/yumv + +local yum = {} + +-- FiveM YumV config +yum.mirror = "https://yumv.net/" +yum.version = "1.0" +yum.versionnum = 1 +-- End + +local downloading = 0 +local current_dir = string.gsub(GetResourcePath(GetCurrentResourceName()), "//", "/") + +-- 解压文件 +function unzip(s, d) + os.execute("unzip -q -o '" .. s .. "' -d '" .. d .. "'") +end + +-- 网络请求 +function curl(url, method, data, headers, timeout) + + if url == nil then + return 'url undefined' + end + + if method == nil then + method = 'GET' + end + + if data == nil then + data = '' + end + + if headers == nil then + headers = {} + end + + if timeout == nil then + timeout = 5000 + end + + local curl_result = {} + + if string.lower(method) == 'post' then + local postString = '' + for i, v in pairs(data) do + postString = postString .. i .. "=" .. urlencode(v) .. "&" + end + postString = string.sub(postString, 1, string.len(postString) - 1) + headers["Content-Type"] = 'application/x-www-form-urlencoded' + PerformHttpRequest(url, function (errorCode, resultData, resultHeaders) + curl_result.status = errorCode + curl_result.body = resultData + curl_result.header = resultHeaders + end, method, postString, headers) + else + PerformHttpRequest(url, function (errorCode, resultData, resultHeaders) + curl_result.status = errorCode + curl_result.body = resultData + curl_result.header = resultHeaders + end, method, data, headers) + end + whilewait = 0 + while curl_result.status == nil do + Wait(1) + if whilewait > timeout then + break + else + whilewait = whilewait + 1 + end + end + return curl_result +end + +-- URL 编码器 +function urlencode(str) + if (str) then + str = string.gsub (str, "\n", "\r\n") + str = string.gsub (str, "([^%w ])", + function (c) return string.format ("%%%02X", string.byte(c)) end) + str = string.gsub (str, " ", "+") + end + return str +end + +-- URL 解码器 +function urldecode(s) + s = string.gsub(s, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) + return s +end + +-- 读取文件 +function file_get_contents(file) + local f = assert(io.open(file, "rb")) + local content = f:read("*all") + f:close() + return content +end + +-- 执行命令 +function shell_exec(command) + os.execute(command .. " > /tmp/fivem-yum-shell-output.log") + result = file_get_contents('/tmp/fivem-yum-shell-output.log') + os.remove('/tmp/fivem-yum-shell-output.log') + return result +end + +-- 实时输出的 shell-output +function realtimeShell(cmd) + f = assert(io.popen(cmd)) + for line in f:lines() do + print(line) + end + f:close() +end + +-- 检测文件是否存在 +function file_exists(name) + if type(name)~="string" then return false end + return os.rename(name,name) and true or false +end + +-- 写入文件 +function file_put_contents(name, data, append) + if append == true then + writemode = "a" + else + writemode = "w" + end + file = io.open(name, writemode) + file:write(data) + file:close() +end + +-- 遍历 table +function forEach(tb) + for key, value in pairs(tb) do + print(key .. " => " .. value) + end +end + +-- 取字符串长度 +function strlen(str) + local _,n = str:gsub('[\128-\255]', '') + return #str - n / 2 +end + +-- 列出所有插件 +function listAllPlugin(tb) + print("+------------------+------------------+") + print("| Name | Version |") + print("+------------------+------------------+") + local i = 0 + for key, value in pairs(tb) do + i = i + 1 + local padding = " " + local padding2 = " " + local length = strlen(value.name) + local length2 = strlen(tostring(value.version)) + if length <= 16 then + padding = string.rep(" ", 16 - length) + end + if length2 <= 16 then + padding2 = string.rep(" ", 16 - length2) + end + print("| " .. value.name .. padding .. " | " .. tostring(value.version) .. padding2 .. " |") + end + local length3 = strlen(tostring(i)) + padding3 = string.rep(" ", 35 - length3 - 19) + print("+------------------+------------------+") + print("| Total: " .. tostring(i) .. " resource(s)" .. padding3 .. " |") + print("+------------------+------------------+") +end + +-- 加载所有插件 +function loadPluginList() + if file_exists(current_dir .. "/list.json") then + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + print("[YumV] No plugin installed") + else + for key, value in pairs(data.list) do + print("[YumV] Loading plugin: " .. value.name) + StartResource(value.name) + end + end + else + print("[YumV] Cannot found resources list! Please use \"yum fix-list\" to fix it!") + end +end + +-- 检查插件是否已安装(包括非 yum 安装的插件) +function checkPluginExist(name) + if file_exists(current_dir .. "/list.json") then + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + print("[YumV] No plugin installed") + else + for key, value in pairs(data.list) do + if value.name == name then + return true + end + end + end + else + print("[YumV] Cannot found resources list! Please use \"yum fix-list\" to fix it!") + end + local resource_status = GetResourceState(name) + if resource_status == "missing" or resource_status == "stopped" then + return false + else + return true + end +end + +-- 检查插件是否已安装(仅限 yum 安装的插件) +function checkPluginInList(name) + if file_exists(current_dir .. "/list.json") then + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + print("[YumV] No plugin installed") + else + for key, value in pairs(data.list) do + if value.name == name then + return true + end + end + end + else + print("[YumV] Cannot found resources list! Please use \"yum fix-list\" to fix it!") + end + return false +end + +-- 获取插件版本号 +function getPluginVersion(name) + if file_exists(current_dir .. "/list.json") then + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + return false + else + for key, value in pairs(data.list) do + if value.name == name then + return value.version + end + end + end + else + print("[YumV] Cannot found resources list! Please use \"yum fix-list\" to fix it!") + end + return false +end + +-- 从列表中删除一个插件 +function removePluginFromList(name) + if file_exists(current_dir .. "/list.json") then + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + print("[YumV] No plugin installed") + else + for key, value in pairs(data.list) do + if value.name == name then + table.remove(data.list, key) + file_put_contents(current_dir .. "/list.json", json.encode(data)) + return true + end + end + end + else + print("[YumV] Cannot found resources list! Please use \"yum fix-list\" to fix it!") + end + return false +end + +-- 增加一个新插件到列表 +function addNewPlugin(name, version) + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + data.list = {} + end + table.insert(data.list, {name = name, version = version}) + file_put_contents(current_dir .. "/list.json", json.encode(data)) +end + +-- 安装插件 +function installPlugin(name, version) + local url = "" + if version == nil then + url = yum.mirror .. "?s=download&name=" .. urlencode(name) + else + url = yum.mirror .. "?s=download&name=" .. urlencode(name) .. "&version=" .. urlencode(version) + end + local rs = curl(url, 'GET') + if rs.status == 200 then + local plugin_name = rs.header.plugin + local plugin_version = rs.header.version + local plugin_size = rs.header.size + local plugin_rsize = rs.header.realsize + downloading = plugin_rsize + if (rs.header.depend == nil) == false then + depend = json.decode(rs.header.depend) + for key, value in pairs(depend) do + if checkPluginExist(value.name) == false then + print("[YumV] Plugin " .. name .. " has depend " .. value.name .. " need to install") + local result = installPlugin(value.name, value.version) + if result == false then + print("[YumV] Depend " .. value.name .. " install failed!") + end + end + end + end + if plugin_name == nil or plugin_version == nil then + print("[YumV] An error occurred when fetch the command name") + return false + else + if checkPluginExist(plugin_name) == false then + print("[YumV] Found plugin: " .. plugin_name) + if not file_exists(current_dir .. "/../[YumV-plugins]/" .. plugin_name .. "/") then + os.execute("mkdir -p '" .. current_dir .. "/../[YumV-plugins]/" .. plugin_name .. "/'") + end + print("[YumV] Downloading: " .. rs.body .. " => /tmp/fivem-yum-temp.zip (" .. plugin_size .. ")") + local cmd = "wget -q -4 \"" .. rs.body .. "\" -O \"/tmp/fivem-yum-temp.zip\" &" + -- print(cmd) + file_put_contents("/tmp/fivem-yum-temp.zip", "") + -- 开始下载 + os.execute(cmd) + local finished = false + local last = 0 + local speed = 0 + local dspeed = "" + while finished == false do + local f = assert(io.open("/tmp/fivem-yum-temp.zip", "rb")) + local size = f:seek("end") + f:close() + if size >= tonumber(plugin_rsize) then + finished = true + end + speed = size - last + last = size + if speed < 1048576 then + dspeed = string.format("%.2f", speed / 1024) .. "KB/s" + else + dspeed = string.format("%.2f", speed / 1048576) .. "MB/s" + end + finish = tostring((size / tonumber(plugin_rsize)) * 100) + finish = string.format("%.2f", finish) + io.write("\r[YumV] Download status: " .. tostring(finish) .. "% - " .. dspeed .. " ") + Wait(1000) + end + print("") + Wait(1000) + print("[YumV] Download finished, decompressing... ") + unzip('/tmp/fivem-yum-temp.zip', current_dir .. "/../[YumV-plugins]/" .. rs.header.plugin .. "/") + ExecuteCommand("refresh") + io.write("[YumV] ") + if StartResource(plugin_name) then + addNewPlugin(plugin_name, tonumber(plugin_version)) + print("[YumV] Plugin " .. plugin_name .. " install successful!") + return true + else + print("[YumV] Failed to start resource! please check your console output to see more info.") + return false + end + else + print("[YumV] Plugin already installed! please use \"yum update " .. plugin_name .. "\" to update it, or use \"yum remove " .. plugin_name .. "\" to remove it!") + print("[YumV] Current resource status: " .. GetResourceState(plugin_name)) + return true + end + end + else + print("[YumV] Cannot install '" .. name .. "', server return error: " .. rs.status) + return false + end +end + +-- 输出帮助信息 +function printHelp() + print("FiveM YumV plugin by Akkariin") + print("Usage: yum [args]") + print("") + print("Commands:") + print(" install [version] Install a new plugin to server") + print(" remove Delete the plugin from server") + print(" update Update a plugin to new version") + print(" check Check whether a plugin has a new version") + print(" search Search a plugin in mirror database") + print(" list List all installed plugin") + print(" version Show the yum plugin version") +end + +-- 注册命令 +RegisterCommand("yum", function(source, args, rawCommand) + -- 默认的帮助 + if args[1] == nil or args[1] == "help" then + printHelp() + else + if args[1] == "test" then + local f = assert(io.open("/tmp/fivem-yum-temp.zip", "rb")) + local size = f:seek("end") + f:close() + print(size) + + -- 删除一个插件 + elseif args[1] == "remove" then + if args[2] == nil then + print("[YumV] Please provide the plugin name you want to remove: yum remove ") + else + if checkPluginInList(args[2]) then + StopResource(args[2]) + os.execute("rm -rf '" .. current_dir .. "/../[YumV-plugins]/" .. args[2] .. "/'") + if removePluginFromList(args[2]) then + print("[YumV] Plugin delete successful!") + else + print("[YumV] Failed to delete this plugin!") + end + else + print("[YumV] Cannot found this plugin, maybe it is not install by YumV?") + end + end + + -- 修复列表错误 + elseif args[1] == "fix-list" then + if file_exists(current_dir .. "/list.json") then + print("[YumV] The resource list already exist, not need to fix!") + else + file_put_contents(current_dir .. "/list.json", json.encode( + { + version = "1.0", list = {} + } + )) + print("[YumV] Successful fix the plugin list") + end + + -- 列出已安装的插件 + elseif args[1] == "list" then + if file_exists(current_dir .. "/list.json") then + local data = file_get_contents(current_dir .. "/list.json") + data = json.decode(data) + if data.list == nil then + print("[YumV] No plugin installed") + else + listAllPlugin(data.list) + end + else + print("[YumV] Cannot found resources list! Please use \"yum fix-list\" to fix it!") + end + + -- 搜索一个插件 + elseif args[1] == "search" then + if args[2] == nil then + print("[YumV] Please provide the plugin name you want to search: yum search ") + else + print("Loading data from mirror server...") + local url = yum.mirror .. "?s=search&name=" .. urlencode(args[2]) + local rs = curl(url, 'GET') + print("") + print(rs.body) + end + + -- 安装一个插件 + elseif args[1] == "install" then + if args[2] == nil then + print("[YumV] Please provide the plugin name you want to install: yum install ") + else + CreateThread(function() + print("") + if args[3] == nil then + local result = installPlugin(args[2]) + else + local result = installPlugin(args[2], args[3]) + end + if result == false then + print("[YumV] One or more plugin(s) install failed, please check your console output for more info.") + else + print("[YumV] All plugin(s) install successful.") + end + end) + end + + -- 更新一个插件 + elseif args[1] == "update" then + if args[2] == nil then + print("[YumV] Please provide the plugin name you want to install: yum install ") + else + if checkPluginInList(args[2]) then + local updateurl = yum.mirror .. "?s=download&name=" .. urlencode(args[2]) + local rs = curl(updateurl, 'GET') + print("") + if rs.status == 200 then + local plugin_name = rs.header.plugin + local plugin_version = tonumber(rs.header.version) + local local_version = tonumber(getPluginVersion(plugin_name)) + if local_version == false then + print("[YumV] Cannot update '" .. args[2] .. "', failed to get local version, please check your list.json!") + else + if plugin_version > local_version then + if not file_exists(current_dir .. "/../[YumV-plugins]/" .. plugin_name .. "/") then + os.execute("mkdir -p '" .. current_dir .. "/../[YumV-plugins]/" .. plugin_name .. "/'") + end + print("[YumV] Downloading: " .. rs.body) + local cmd = "wget -q -4 \"" .. rs.body .. "\" -O \"/tmp/fivem-yum-temp.zip\"" + -- print(cmd) + os.execute(cmd) + print("[YumV] Download finished, deleting old version... ") + StopResource(args[2]) + os.execute("rm -rf '" .. current_dir .. "/../[YumV-plugins]/" .. args[2] .. "/'") + removePluginFromList(plugin_name) + print("[YumV] Decompressing file... ") + unzip('/tmp/fivem-yum-temp.zip', current_dir .. "/../[YumV-plugins]/" .. rs.header.plugin .. "/") + ExecuteCommand("refresh") + if StartResource(plugin_name) then + addNewPlugin(plugin_name, plugin_version) + print("[YumV] Plugin update successful!") + else + print("[YumV] Failed to start resource! please check your console output to see more info.") + end + else + print("[YumV] Your plugin is already up to date!") + end + end + else + print("[YumV] Cannot update '" .. args[2] .. "', server return error: " .. rs.status) + end + else + print("[YumV] Cannot update '" .. args[2] .. "', plugin not installed.") + end + end + + -- 检查插件是否有更新 + elseif args[1] == "check" then + if args[2] == nil then + print("[YumV] Please provide the plugin name you want to check: yum check ") + else + if checkPluginInList(args[2]) then + local updateurl = yum.mirror .. "?s=download&name=" .. urlencode(args[2]) + local rs = curl(updateurl, 'GET') + print("") + if rs.status == 200 then + local plugin_name = rs.header.plugin + local plugin_version = tonumber(rs.header.version) + local local_version = tonumber(getPluginVersion(plugin_name)) + if local_version == false then + print("[YumV] Cannot update '" .. args[2] .. "', failed to get local version, please check your list.json!") + else + if plugin_version > local_version then + print("[YumV] This plugin has a new version: " .. tostring(plugin_version) .. ". The version you have installed is: " .. tostring(local_version)) + else + print("[YumV] Your plugin is already up to date!") + end + end + else + print("[YumV] Cannot check update for '" .. args[2] .. "', server return error: " .. rs.status) + end + else + print("[YumV] Cannot check update for '" .. args[2] .. "', plugin not installed.") + end + end + + -- 获取 yum 版本号 + elseif args[1] == "version" then + print("FiveM YumV plugin by Akkariin") + print("Version: " .. yum.version) + + -- 默认输出 + else + print("Command not found: " .. args[1] .. ", use \"yum help\" to get help.") + end + end +end, true) + +-- Load all installed plugins +loadPluginList()