· 5 years ago · May 19, 2020, 03:36 PM
1MySQL = module("vrp_mysql", "MySQL")
2
3local Proxy = module("lib/Proxy")
4local Tunnel = module("lib/Tunnel")
5local Lang = module("lib/Lang")
6Debug = module("lib/Debug")
7
8local config = module("cfg/base")
9local version = module("version")
10Debug.active = config.debug
11MySQL.debug = config.debug
12
13-- open MySQL connection
14MySQL.createConnection("vRP", config.db.host,config.db.user,config.db.password,config.db.database)
15
16-- versioning
17print("[vRP] launch version "..version)
18--[[
19PerformHttpRequest("https://raw.githubusercontent.com/ImagicTheCat/vRP/master/vrp/version.lua",function(err,text,headers)
20 if err == 0 then
21 text = string.gsub(text,"return ","")
22 local r_version = tonumber(text)
23 if version ~= r_version then
24 print("[vRP] WARNING: A new version of vRP is available here https://github.com/ImagicTheCat/vRP, update to benefit from the last features and to fix exploits/bugs.")
25 end
26 else
27 print("[vRP] unable to check the remote version")
28 end
29end, "GET", "")
30--]]
31
32vRP = {}
33Proxy.addInterface("vRP",vRP)
34
35tvRP = {}
36Tunnel.bindInterface("vRP",tvRP) -- listening for client tunnel
37
38-- load language
39local dict = module("cfg/lang/"..config.lang) or {}
40vRP.lang = Lang.new(dict)
41
42-- init
43vRPclient = Tunnel.getInterface("vRP","vRP") -- server -> client tunnel
44
45vRP.users = {} -- will store logged users (id) by first identifier
46vRP.rusers = {} -- store the opposite of users
47vRP.user_tables = {} -- user data tables (logger storage, saved to database)
48vRP.user_tmp_tables = {} -- user tmp data tables (logger storage, not saved)
49vRP.user_sources = {} -- user sources
50
51-- queries
52MySQL.createCommand("vRP/base_tables",[[
53CREATE TABLE IF NOT EXISTS vrp_users(
54 id INTEGER AUTO_INCREMENT,
55 last_login VARCHAR(255),
56 whitelisted BOOLEAN,
57 banned BOOLEAN,
58 CONSTRAINT pk_user PRIMARY KEY(id)
59);
60CREATE TABLE IF NOT EXISTS vrp_user_ids(
61 identifier VARCHAR(255),
62 user_id INTEGER,
63 CONSTRAINT pk_user_ids PRIMARY KEY(identifier),
64 CONSTRAINT fk_user_ids_users FOREIGN KEY(user_id) REFERENCES vrp_users(id) ON DELETE CASCADE
65);
66CREATE TABLE IF NOT EXISTS vrp_user_data(
67 user_id INTEGER,
68 dkey VARCHAR(255),
69 dvalue TEXT,
70 CONSTRAINT pk_user_data PRIMARY KEY(user_id,dkey),
71 CONSTRAINT fk_user_data_users FOREIGN KEY(user_id) REFERENCES vrp_users(id) ON DELETE CASCADE
72);
73CREATE TABLE IF NOT EXISTS vrp_srv_data(
74 dkey VARCHAR(255),
75 dvalue TEXT,
76 CONSTRAINT pk_srv_data PRIMARY KEY(dkey)
77);
78]])
79
80MySQL.createCommand("vRP/create_user","INSERT INTO vrp_users(whitelisted,banned) VALUES(false,false); SELECT LAST_INSERT_ID() AS id")
81MySQL.createCommand("vRP/add_identifier","INSERT INTO vrp_user_ids(identifier,user_id) VALUES(@identifier,@user_id)")
82MySQL.createCommand("vRP/userid_byidentifier","SELECT user_id FROM vrp_user_ids WHERE identifier = @identifier")
83
84MySQL.createCommand("vRP/set_userdata","REPLACE INTO vrp_user_data(user_id,dkey,dvalue) VALUES(@user_id,@key,@value)")
85MySQL.createCommand("vRP/get_userdata","SELECT dvalue FROM vrp_user_data WHERE user_id = @user_id AND dkey = @key")
86
87MySQL.createCommand("vRP/set_srvdata","REPLACE INTO vrp_srv_data(dkey,dvalue) VALUES(@key,@value)")
88MySQL.createCommand("vRP/get_srvdata","SELECT dvalue FROM vrp_srv_data WHERE dkey = @key")
89
90MySQL.createCommand("vRP/get_banned","SELECT * FROM vrp_users WHERE id = @user_id")
91MySQL.createCommand("vRP/banned","UPDATE vrp_users SET banned=@banned,ban_reason=@reason WHERE id = @user_id")
92MySQL.createCommand("vRP/unban","UPDATE vrp_users SET banned = '0' WHERE id = @user_id")
93MySQL.createCommand("vRP/get_whitelisted","SELECT whitelisted FROM vrp_users WHERE id = @user_id")
94MySQL.createCommand("vRP/set_whitelisted","UPDATE vrp_users SET whitelisted = @whitelisted WHERE id = @user_id")
95MySQL.createCommand("vRP/set_last_login","UPDATE vrp_users SET last_login = @last_login WHERE id = @user_id")
96MySQL.createCommand("vRP/get_last_login","SELECT last_login FROM vrp_users WHERE id = @user_id")
97
98-- init tables
99print("[vRP] init base tables")
100MySQL.query("vRP/base_tables")
101
102-- identification system
103local webhooklink1 = 'Supporter'
104local botusername = "DownTownRP - Server Logging"
105
106--- sql.
107-- cbreturn user id or nil in case of error (if not found, will create it)
108function vRP.getUserIdByIdentifiers(ids, cbr)
109 local task = Task(cbr)
110
111 if ids ~= nil and #ids then
112 local i = 0
113 local validids = 0
114
115 -- search identifiers
116 local function search()
117 i = i+1
118 print(ids[i])
119 if i <= #ids then
120 if (not config.ignore_ip_identifier or (string.find(ids[i], "ip:") == nil)) and
121
122 (not config.ignore_license_identifier or (string.find(ids[i], "license:") == nil)) and
123
124 (not config.ignore_xbox_identifier or (string.find(ids[i], "xbl:") == nil)) and
125
126 (not config.ignore_discord_identifier or (string.find(ids[i], "discord:") == nil)) and
127
128 (not config.ignore_live_identifier or (string.find(ids[i], "live:") == nil))
129
130 then
131 validids = validids + 1
132 MySQL.query("vRP/userid_byidentifier", {identifier = ids[i]}, function(rows, affected)
133 if #rows > 0 then -- found
134 task({rows[1].user_id})
135 else -- not found
136 search()
137 end
138 end)
139 else
140 search()
141 end
142 elseif validids > 0 then -- no ids found, create user
143 MySQL.query("vRP/create_user", {}, function(rows, affected)
144 if #rows > 0 then
145 local user_id = rows[1].id
146 -- add identifiers
147 for l,w in pairs(ids) do
148 if (not config.ignore_ip_identifier or (string.find(w, "ip:") == nil)) and
149
150 (not config.ignore_license_identifier or (string.find(w, "license:") == nil)) and
151
152 (not config.ignore_xbox_identifier or (string.find(w, "xbl:") == nil)) and
153
154 (not config.ignore_discord_identifier or (string.find(w, "discord:") == nil)) and
155
156 (not config.ignore_live_identifier or (string.find(w, "live:") == nil)) then -- ignore ip & license identifier
157
158 MySQL.execute("vRP/add_identifier", {user_id = user_id, identifier = w})
159 end
160 end
161 task({user_id})
162 else
163 task()
164 end
165 end)
166 end
167 end
168
169 search()
170 else
171 task()
172 end
173end
174
175
176-- return identification string for the source (used for non vRP identifications, for rejected players)
177function vRP.getSourceIdKey(source)
178 local ids = GetPlayerIdentifiers(source)
179 local idk = "idk_"
180 for k,v in pairs(ids) do
181 idk = idk..v
182 end
183
184 return idk
185end
186
187function vRP.getPlayerEndpoint(player)
188 return GetPlayerEP(player) or "0.0.0.0"
189end
190
191--- sql
192function vRP.getUserData(user_id, cbr)
193 local task = Task(cbr, {false})
194 MySQL.query("vRP/get_banned", {user_id = user_id}, function(rows, affected)
195 if #rows > 0 then
196 task({rows[1]})
197 else
198 task()
199 end
200 end)
201end
202
203function vRP.isBanned(user_id, cbr)
204 local task = Task(cbr, {false})
205
206 MySQL.query("vRP/get_banned", {user_id = user_id}, function(rows, affected)
207 if #rows > 0 then
208 task({rows[1].banned})
209 else
210 task()
211 end
212 end)
213end
214
215function vRP.getBannedReason(user_id, cbr)
216 local task = Task(cbr, {false})
217
218 MySQL.query("vRP/get_banned", {user_id = user_id}, function(rows, affected)
219 if #rows > 0 then
220 task({rows[1].ban_reason})
221 else
222 task()
223 end
224 end)
225end
226
227--- sql
228function vRP.setBanned(user_id,banned)
229 if banned ~= false then
230 MySQL.query("vRP/banned", {user_id = user_id, banned = 1, reason = banned})
231 else
232 MySQL.query("vRP/unban", {user_id = user_id})
233 end
234end
235
236--- sql
237function vRP.isWhitelisted(user_id, cbr)
238 local task = Task(cbr, {false})
239
240 MySQL.query("vRP/get_whitelisted", {user_id = user_id}, function(rows, affected)
241 if #rows > 0 then
242 task({rows[1].whitelisted})
243 else
244 task()
245 end
246 end)
247end
248
249--- sql
250function vRP.setWhitelisted(user_id,whitelisted)
251 MySQL.query("vRP/set_whitelisted", {user_id = user_id, whitelisted = whitelisted})
252end
253
254--- sql
255function vRP.getLastLogin(user_id, cbr)
256 local task = Task(cbr,{""})
257 MySQL.query("vRP/get_last_login", {user_id = user_id}, function(rows, affected)
258 if #rows > 0 then
259 task({rows[1].last_login})
260 else
261 task()
262 end
263 end)
264end
265
266function vRP.getPlayerName(player)
267 return GetPlayerName(player) or "ukendt"
268end
269
270function vRP.setUData(user_id,key,value)
271 MySQL.execute("vRP/set_userdata", {user_id = user_id, key = key, value = value})
272end
273
274function vRP.getUData(user_id,key,cbr)
275 local task = Task(cbr,{""})
276
277 MySQL.query("vRP/get_userdata", {user_id = user_id, key = key}, function(rows, affected)
278 if #rows > 0 then
279 task({rows[1].dvalue})
280 else
281 task()
282 end
283 end)
284end
285
286function vRP.setSData(key,value)
287 MySQL.query("vRP/set_srvdata", {key = key, value = value})
288end
289
290function vRP.getSData(key, cbr)
291 local task = Task(cbr,{""})
292
293 MySQL.query("vRP/get_srvdata", {key = key}, function(rows, affected)
294 if #rows > 0 then
295 task({rows[1].dvalue})
296 else
297 task()
298 end
299 end)
300end
301
302-- return user data table for vRP internal persistant connected user storage
303function vRP.getUserDataTable(user_id)
304 return vRP.user_tables[user_id]
305end
306
307function vRP.getUserTmpTable(user_id)
308 return vRP.user_tmp_tables[user_id]
309end
310
311function vRP.isConnected(user_id)
312 return vRP.rusers[user_id] ~= nil
313end
314
315function vRP.isFirstSpawn(user_id)
316 local tmp = vRP.getUserTmpTable(user_id)
317 return tmp and tmp.spawns == 1
318end
319
320function vRP.getUserId(source)
321 if source ~= nil then
322 local ids = GetPlayerIdentifiers(source)
323 if ids ~= nil and #ids > 0 then
324 return vRP.users[ids[1]]
325 end
326 end
327
328 return nil
329end
330
331-- return map of user_id -> player source
332function vRP.getUsers()
333 local users = {}
334 for k,v in pairs(vRP.user_sources) do
335 users[k] = v
336 end
337
338 return users
339end
340
341-- return source or nil
342function vRP.getUserSource(user_id)
343 return vRP.user_sources[user_id]
344end
345
346function vRP.ban(user_id,reason)
347 if user_id ~= nil then
348 vRP.setBanned(user_id,reason)
349 local player = vRP.getUserSource(user_id)
350 if player ~= nil then
351 vRP.kick(player,"[Banned] "..reason)
352 end
353 end
354end
355
356function vRP.kick(source,reason)
357 DropPlayer(source,reason)
358end
359
360-- tasks
361
362function task_save_datatables()
363 TriggerEvent("vRP:save")
364
365 Debug.pbegin("vRP save datatables")
366 for k,v in pairs(vRP.user_tables) do
367 vRP.setUData(k,"vRP:datatable",json.encode(v))
368 TriggerEvent("htn_logging:saveUser",k)
369 end
370
371 Debug.pend()
372 SetTimeout(config.save_interval*1000, task_save_datatables)
373end
374task_save_datatables()
375
376local max_pings = math.ceil(config.ping_timeout*120/60)+2
377function task_timeout() -- kick users not sending ping event in 3 minutes
378 local users = vRP.getUsers()
379 for k,v in pairs(users) do
380 local tmpdata = vRP.getUserTmpTable(tonumber(k))
381 if tmpdata.pings == nil then
382 tmpdata.pings = 0
383 end
384
385 tmpdata.pings = tmpdata.pings+1
386 if tmpdata.pings >= max_pings then
387 vRP.kick(v,"[vRP] Ping Timeout - Intet client svar i 3 minutter.")
388 end
389 end
390
391 SetTimeout(60000, task_timeout)
392end
393task_timeout()
394
395function tvRP.ping()
396 local user_id = vRP.getUserId(source)
397 if user_id ~= nil then
398 local tmpdata = vRP.getUserTmpTable(user_id)
399 tmpdata.pings = 0 -- reinit ping countdown
400 end
401end
402
403-- handlers
404local isStopped = false
405function vRP.getServerStatus()
406 return isStopped
407end
408
409function vRP.setServerStatus(reason)
410 isStopped = reason
411end
412
413local antispam = {}
414AddEventHandler("playerConnecting",function(name,setMessage, deferrals)
415 deferrals.defer()
416
417 local source = source
418 Debug.pbegin("playerConnecting")
419 if isStopped == false then
420 local ids = GetPlayerIdentifiers(source)
421 if antispam[ids[1]] == nil then
422 antispam[ids[1]] = 30
423 if ids ~= nil and #ids > 0 then
424 deferrals.update("[vRP] Tjekker identifikatorer...")
425 vRP.getUserIdByIdentifiers(ids, function(user_id)
426 -- if user_id ~= nil and vRP.rusers[user_id] == nil then -- check user validity and if not already connected (old way, disabled until playerDropped is sure to be called)
427 if user_id ~= nil then -- check user validity
428 deferrals.update("[vRP] Tjekker efter ban...")
429 vRP.getUserData(user_id, function(userdata)
430 if not userdata.banned then
431 deferrals.update("[vRP] Tjekker efter whitelist...")
432 if not config.whitelist or userdata.whitelisted then
433 Debug.pbegin("playerConnecting_delayed")
434 if vRP.rusers[user_id] == nil then -- not present on the server, init
435 -- init entries
436 vRP.users[ids[1]] = user_id
437 vRP.rusers[user_id] = ids[1]
438 vRP.user_tables[user_id] = {}
439 vRP.user_tmp_tables[user_id] = {}
440 vRP.user_sources[user_id] = source
441 -- load user data table
442 deferrals.update("[vRP] Henter data...")
443 vRP.getUData(user_id, "vRP:datatable", function(sdata)
444 local data = json.decode(sdata)
445 if type(data) == "table" then vRP.user_tables[user_id] = data end
446
447 -- init user tmp table
448 local tmpdata = vRP.getUserTmpTable(user_id)
449
450 deferrals.update("[vRP] Sidste login...")
451 vRP.getLastLogin(user_id, function(last_login)
452 tmpdata.last_login = last_login or ""
453 tmpdata.spawns = 0
454
455 -- set last login
456 local ep = vRP.getPlayerEndpoint(source)
457 local last_login_stamp = ep.." "..os.date("%H:%M:%S %d/%m/%Y")
458 MySQL.execute("vRP/set_last_login", {user_id = user_id, last_login = last_login_stamp})
459
460 -- trigger join
461 print("[vRP] "..name.." ("..vRP.getPlayerEndpoint(source)..") joined (user_id = "..user_id..")")
462 TriggerEvent("vRP:playerJoin", user_id, source, name, tmpdata.last_login)
463 sendToDiscord(name, "**"..tostring(user_id) .. "** joinet serveren (**"..os.date("%H:%M:%S %d/%m/%Y").."**)")
464 deferrals.done()
465 end)
466 end)
467 else -- already connected
468 print("[vRP] "..name.." ("..vRP.getPlayerEndpoint(source)..") re-joined jhgghjghj(user_id = "..user_id..")")
469 TriggerEvent("vRP:playerRejoin", user_id, source, name)
470 deferrals.done()
471
472 -- reset first spawn
473 local tmpdata = vRP.getUserTmpTable(user_id)
474 tmpdata.spawns = 0
475 end
476 Debug.pend()
477 else
478 print("[vRP] "..name.." ("..vRP.getPlayerEndpoint(source)..") rejected: Du er ikke Whitelisted (user_id = "..user_id..")")
479 deferrals.done("[vRP] Ikke whitelisted, ansøg hurtigt på vores discord https://discord.gg/aZpaX5d (user_id = "..user_id..").")
480 end
481
482 else
483 local ban_reason = userdata.ban_reason
484 if type(userdata.ban_reason) == "table" then
485 ban_reason = "Ingen grund sat"
486 end
487 print("[vRP] "..name.." ("..vRP.getPlayerEndpoint(source)..") rejected: banned (user_id = "..user_id..")")
488 deferrals.done("[vRP] Du er bannet for: "..ban_reason.." Ansøg om Unban på vores Discord https://discord.gg/aZpaX5d (user_id = "..user_id..").")
489 end
490 end)
491 else
492 print("[vRP] "..name.." ("..vRP.getPlayerEndpoint(source)..") rejected: identification Fejl")
493 deferrals.done("[vRP] Tjek om du har dit steam åben og ellers prøv at genstarte det.")
494 end
495 end)
496 else
497 print("[vRP] "..name.." ("..vRP.getPlayerEndpoint(source)..") rejected: missing identifiers")
498 deferrals.done("[vRP] Tjek om du har dit steam åben og ellers prøv at genstarte det.")
499 end
500 else
501 print("[ANTI-SPAM] "..name.." ("..vRP.getPlayerEndpoint(source)..") prøvet at joine for hurtigt igen")
502 deferrals.done("[DT-AntiSpam] Du prøvet at joine for hurtigt prøv igen om "..antispam[ids[1]].." sekunder!")
503 end
504 else
505 print("("..vRP.getPlayerEndpoint(source)..") blev kicket for at joine imens serveren er igang med at "..isStopped)
506 deferrals.done("[DT-SafeStop] Serveren er igang med at "..isStopped)
507 end
508 Debug.pend()
509end)
510
511Citizen.CreateThread( function()
512 while true do
513 Citizen.Wait(1000)
514 for k,v in pairs(antispam) do
515 if tonumber(v) > 1 then
516 antispam[k] = tonumber(v) - 1
517 else
518 antispam[k] = nil
519 end
520 end
521 end
522end)
523
524AddEventHandler("playerDropped",function(reason)
525 local source = source
526 local suffix = "**"..os.date("%H:%M - %d/%m/%Y").."**"
527 Debug.pbegin("playerDropped")
528
529 -- remove player from connected clients
530 vRPclient.removePlayer(-1,{source})
531
532
533 local user_id = vRP.getUserId(source)
534
535 if user_id ~= nil then
536 TriggerEvent("vRP:playerLeave", user_id, source)
537
538 local steam = GetPlayerName(source)
539 local dmessage = "**".. tostring(user_id).. "** forlod serveren ("..suffix..")"
540
541 sendToDiscord(steam, dmessage)
542
543 -- save user data table
544 vRP.setUData(user_id,"vRP:datatable",json.encode(vRP.getUserDataTable(user_id)))
545
546 print("[vRP] disconnected (user_id = "..user_id..")")
547 vRP.users[vRP.rusers[user_id]] = nil
548 vRP.rusers[user_id] = nil
549 vRP.user_tables[user_id] = nil
550 vRP.user_tmp_tables[user_id] = nil
551 vRP.user_sources[user_id] = nil
552 end
553 Debug.pend()
554end)
555
556RegisterServerEvent("vRPcli:playerSpawned")
557AddEventHandler("vRPcli:playerSpawned", function()
558 Debug.pbegin("playerSpawned")
559 -- register user sources and then set first spawn to false
560 local user_id = vRP.getUserId(source)
561 local player = source
562 if user_id ~= nil then
563 vRP.user_sources[user_id] = source
564 local tmp = vRP.getUserTmpTable(user_id)
565 tmp.spawns = tmp.spawns+1
566 local first_spawn = (tmp.spawns == 1)
567
568 if first_spawn then
569 -- first spawn, reference player
570 -- send players to new player
571 for k,v in pairs(vRP.user_sources) do
572 vRPclient.addPlayer(source,{v})
573 end
574 -- send new player to all players
575 vRPclient.addPlayer(-1,{source})
576 end
577
578 -- set client tunnel delay at first spawn
579 Tunnel.setDestDelay(player, config.load_delay)
580
581 -- show loading
582 vRPclient.setProgressBar(player,{"vRP:loading", "botright", "Indlæser...", 0,0,0, 100})
583
584 SetTimeout(2000, function() -- trigger spawn event
585 TriggerEvent("vRP:playerSpawn",user_id,player,first_spawn)
586
587 SetTimeout(config.load_duration*1000, function() -- set client delay to normal delay
588 Tunnel.setDestDelay(player, config.global_delay)
589 vRPclient.removeProgressBar(player,{"vRP:loading"})
590 TriggerClientEvent('movebitch',player)
591 end)
592 end)
593 end
594
595 Debug.pend()
596end)
597
598RegisterServerEvent("vRP:playerDied")
599
600function sendToDiscord(name, message)
601 if message == nil or message == '' or message:sub(1, 1) == '/' then return FALSE end
602 local server = GetConvar("servernumber", "1")
603
604 PerformHttpRequest('https://discordapp.com/api/webhooks/698143260736225420/rUkEZYt_JQOskdvY5siv7jYdzO5AqwH8yGZgkn4bTb0olCQ7Vh0z9OqjROEwwlOXp_cv', function(err, text, headers) end, 'POST', json.encode({username = name, content = message}), { ['Content-Type'] = 'application/json' })
605end