YumV/main_server.lua

669 lines
20 KiB
Lua

-- 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 <command> [args]")
print("")
print("Commands:")
print(" install <plugin> [version] Install a new plugin to server")
print(" remove <plugin> Delete the plugin from server")
print(" update <plugin> Update a plugin to new version")
print(" check <plugin> Check whether a plugin has a new version")
print(" search <name> 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 <name>")
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 <name>")
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 <name>")
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 <name>")
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 <name>")
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()