-
Notifications
You must be signed in to change notification settings - Fork 2
/
main_server.lua
668 lines (622 loc) · 20.3 KB
/
main_server.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
-- 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()