Какстомная команда

Как сделать команду !rule или !discord, чтобы открывало url ссылку?

Пример встроен
это CL часть

local CMD =
{--Заглавные буквы не вставлят! пример: за место !Rule пишите !rule.
["!rule"]="https://rule.com",
["!discord"]="https://discord.gg"
}

hook.Add( "OnPlayerChat", "OpenURLChat", function( pl, str) 
if not IsValid(pl) then return end 
if pl ~= LocalPlayer() then return end 
local str=str:lower()
if CMD[str] == nil then return end 
gui.OpenURL( CMD[str] )
end)

if SERVER then return end

local PREFIX = "!" -- префикс для команд

local function openUrl(url)
    return function()
        gui.OpenURL(url)
    end
end

local COMMANDS = {
    ["rules"] = openUrl("https://example.com/"), -- вместо "https://example.com/" вставляй свою ссылку
    ["discord"] = openUrl("https://example.com/"),
    -- ... другие команды
}

-- как добавлять другие команды:
-- ["имя команды"] = function(ply)
--     -- код команды
--     -- тут может быть что угодно
-- end

for k, v in pairs(COMMANDS) do
    -- преобразовать все команды в нижний регистр
    COMMANDS[k] = nil
    COMMANDS[string.lower(k)] = v
end

hook.Add("OnPlayerChat", "ChatCommands", function(ply, text)
    if ply ~= LocalPlayer() then return end
    if not string.StartWith(text, PREFIX) then return end

    local command = string.sub(text, 2)
    if command ~= "" then
        command = string.lower(command)
        if COMMANDS[command] then
            COMMANDS[command](ply)
            return true -- что бы не отображало то что написал игрок в чат
        end
    end
end)

закидывать по пути addons/addonname/lua/autorun

UPD: не увидел ответа выше, но уже написал :grinning:

кста
в хуке OnPlayerChat
если вернуть true то это не видит только LocalPlayer

This also means, that a message surpressed with this hook will be still visible to other clients.
Это также означает, что сообщение, подавленное этим хуком, будет по-прежнему видно другим клиентам.