-- 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.3" yum.versionnum = 103 -- 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 <= 32 then padding = string.rep(" ", 32 - 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(" ", 51 - 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 getPluginPath(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 if value.path == nil then value.path = "/[YumV-plugins]/" end return value.path 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, path) 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, path = path}) file_put_contents(current_dir .. "/list.json", json.encode(data)) end -- 检查 YumV 更新 function checkUpdate() print("[YumV] Checking for YumV new version...") Citizen.CreateThread(function() local url = yum.mirror .. "?s=check_update&yum_version=" .. urlencode(yum.versionnum) local rs = curl(url, 'GET') if rs.status == 200 then print(rs.body) else print("[YumV] Failed check plugin update, please check your network.") end end) end function updateSelf() print("[YumV] Updating YumV to new version...") Citizen.CreateThread(function() local url = yum.mirror .. "?s=get_update&yum_version=" .. urlencode(yum.versionnum) local rs = curl(url, 'GET') if rs.status == 200 then local new_version = tonumber(rs.body) if yum.versionnum == new_version then print("[YumV] Your YumV is newest version, not need to update.") else url = yum.mirror .. "?s=get_update_download&yum_version=" .. urlencode(rs.body) rs = curl(url, 'GET') if rs.status == 200 then print("[YumV] Downloading files, please don't stop the server.") local cmd = "wget -q -4 \"" .. rs.body .. "\" -O \"" .. current_dir .. "/update.zip\"" -- print(cmd) file_put_contents(current_dir .. "/update.zip", "") -- 开始下载 os.execute(cmd) print("[YumV] Download finished, decompressing... ") unzip(current_dir .. "/update.zip", current_dir .. "/") os.remove(current_dir .. "/update.zip"); print("[YumV] Update finished, please execute command: \"restart yum\".") else print("[YumV] Failed check plugin update, server return: " .. tostring(rs.status)) end end else print("[YumV] Failed check plugin update, server return: " .. tostring(rs.status)) end end) end -- 安装插件 function installPlugin(name, version) local url = "" if version == nil then url = yum.mirror .. "?s=download&name=" .. urlencode(name) .. "&yum_version=" .. urlencode(yum.versionnum) else url = yum.mirror .. "?s=download&name=" .. urlencode(name) .. "&version=" .. urlencode(version) .. "&yum_version=" .. urlencode(yum.versionnum) 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 local plugin_dir = rs.header.installdir 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 plugin_dir == nil or plugin_dir == "" then plugin_dir = "/[YumV-plugins]/" end if checkPluginExist(plugin_name) == false then print("[YumV] Found plugin: " .. plugin_name) if not file_exists(current_dir .. "/.." .. plugin_dir .. plugin_name .. "/") then os.execute("mkdir -p '" .. current_dir .. "/.." .. plugin_dir .. 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 .. "/.." .. plugin_dir .. rs.header.plugin .. "/") ExecuteCommand("refresh") io.write("[YumV] ") if StartResource(plugin_name) then addNewPlugin(plugin_name, tonumber(plugin_version), plugin_dir) 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") print(" checkyumv Check if YumV has new version") print(" updateself Update YumV to newest version") end -- 注册命令 RegisterCommand("yum", function(source, args, rawCommand) -- 默认的帮助 if args[1] == nil or args[1] == "help" then printHelp() else if args[1] == "test" then ExecuteCommand("restart yum") -- 删除一个插件 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]) local rmdir = getPluginPath(args[2]) os.execute("rm -rf '" .. current_dir .. "/.." .. rmdir .. 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)) local plugin_dir = rs.header.installdir 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 plugin_dir == nil or plugin_dir == "" then plugin_dir = "/[YumV-plugins]/" end if not file_exists(current_dir .. "/.." .. plugin_dir .. plugin_name .. "/") then os.execute("mkdir -p '" .. current_dir .. "/.." .. plugin_dir .. 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 .. "/.." .. plugin_dir .. args[2] .. "/'") removePluginFromList(plugin_name) print("[YumV] Decompressing file... ") unzip('/tmp/fivem-yum-temp.zip', current_dir .. "/.." .. plugin_dir .. rs.header.plugin .. "/") ExecuteCommand("refresh") if StartResource(plugin_name) then addNewPlugin(plugin_name, plugin_version, plugin_dir) 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) -- 检查 YumV 新版本 elseif args[1] == "checkyumv" then checkUpdate() -- 自动更新到新版本 elseif args[1] == "updateself" then updateSelf() -- 默认输出 else print("Command not found: " .. args[1] .. ", use \"yum help\" to get help.") end end end, true) -- Load all installed plugins loadPluginList() checkUpdate()