Last active
April 16, 2022 14:08
-
-
Save Earu/9c7c7064188f855c1809cc8c56e8db52 to your computer and use it in GitHub Desktop.
An advanced Garry's Mod server search query processor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function parse_host_name_tags(host_name) | |
local tags = {} | |
local function add_tag(tag) | |
tag = tag:Trim() | |
if #tag > 1 and #tag < 15 then | |
table.insert(tags, tag) | |
end | |
end | |
local start_index, _ = host_name:find("[%|%,%-]") | |
local end_index = 1 | |
while start_index do | |
local tag = end_index == 1 | |
and host_name:sub(end_index, start_index - 1):Trim() | |
or host_name:sub(end_index, start_index - 1):gsub("[%[%]%(%)]", ""):Trim() | |
add_tag(tag) | |
end_index = start_index + 1 | |
start_index, _ = host_name:find("[%|%,%-]", end_index) | |
end | |
local last_tag = host_name:sub(end_index, #host_name):gsub("[%[%]%(%)]", ""):Trim() | |
add_tag(last_tag) | |
local explicit_tag_patterns = { | |
"%[(.+)%]", "%((.+)%)", "%{(.+)%}", "%<(.+)%>", | |
"%[(.+)$", "%((.+)$", "%{(.+)$", "%<(.+)$", | |
} | |
local actual_host_name = (table.remove(tags, 1) or host_name) | |
for _, tag_pattern in ipairs(explicit_tag_patterns) do | |
actual_host_name = actual_host_name:gsub(tag_pattern, function(tag) | |
add_tag(tag) | |
return "" | |
end) | |
end | |
if #tags <= 0 then | |
add_tag("N/A") | |
end | |
return actual_host_name, tags | |
end | |
local valid_filters = { | |
["host"] = "FullHostName", | |
["tag"] = "Tags", | |
["gm"] = "Description", | |
["map"] = "Map", | |
["ip"] = "IPAddress", | |
} | |
local function default_search_processor(server, search_query) | |
local has_matching_tag = false | |
for _, tag in ipairs(server.Tags) do | |
if tag:lower():find(search_query, 1, true) then | |
has_matching_tag = true | |
break | |
end | |
end | |
return server.FullHostName:lower():find(search_query, 1, true) | |
or server.Description:lower():find(search_query, 1, true) | |
or server.Map:lower():find(search_query, 1, true) | |
or server.Gamemode:lower():find(search_query, 1, true) | |
or server.IPAddress:find(search_query, 1, true) | |
or has_matching_tag | |
end | |
local function parse_search_query(search_query) | |
if not search_query or #search_query:Trim() <= 0 then | |
return function(server) return true end | |
end | |
local filter_processors = {} | |
local filters = search_query:Split(";") | |
for _, filter in ipairs(filters) do | |
local chunks = filter:Split("=") | |
local has_valid_filter_value = chunks[2] and #chunks[2] > 0 | |
if has_valid_filter_value then | |
local filter_type = chunks[1]:Trim():lower() | |
local filter_value = chunks[2]:lower() | |
if not valid_filters[filter_type] then | |
table.insert(filter_processors, function(server) return false end) | |
continue | |
end | |
table.insert(filter_processors, function(server) | |
local server_value = server[valid_filters[filter_type]] | |
if not server_value then | |
return false | |
end | |
local server_value_type = type(server_value) | |
if isstring(server_value) then | |
return server_value:lower():find(filter_value, 1, true) | |
elseif server_value_type == "table" then | |
for _, value in ipairs(server_value) do | |
if value:lower():find(filter_value, 1, true) then | |
return true | |
end | |
end | |
return false | |
else | |
return tostring(server_value):lower():find(filter_value, 1, true) | |
end | |
end) | |
else | |
table.insert(filter_processors, function(server) return default_search_processor(server, filter:Trim():lower()) end) | |
end | |
end | |
return function(server) | |
for _, filter_processor in ipairs(filter_processors) do | |
if not filter_processor(server) then | |
return false | |
end | |
end | |
return true | |
end | |
end | |
local function fetch_servers(srv_type, callback, search_query) | |
serverlist.Query({ | |
Type = srv_type, | |
Callback = function(ping, host_name, description, map_name, ply_count, max_ply_count, bot_ply_count, has_password, workshop_id, ip_address, gamemode) | |
local actual_host_name, tags = parse_host_name_tags(host_name) | |
local server = { | |
Ping = ping, | |
FullHostName = host_name, | |
HostName = actual_host_name, | |
Tags = tags, | |
Description = description, | |
Map = map_name, | |
PlayerCount = ply_count, | |
MaxPlayerCount = max_ply_count, | |
BotPlayerCount = bot_ply_count, | |
HasPassword = has_password, | |
WorkshopID = workshop_id, | |
IPAddress = ip_address, | |
Gamemode = gamemode, | |
} | |
if search_query then | |
local execute_query = parse_search_query(search_query:lower()) | |
if execute_query(server) then | |
callback(server) | |
end | |
else | |
callback(server) | |
end | |
end, | |
}) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment