Skip to content

With vs without Voyager

Security Disclaimer

Both examples shown here are not safe to use in a live game, for the sake of simplicity these scripts are not secured. If you wish to use them in your game you need to follow the remote secruity tutorial.

Goal

Make a script that sends a message with embedded content that displays the player's feedback to Discord.

With Voyager

examples/playerFeedback.server.lua
local sendFeedbackRemote = game:GetService("ReplicatedStorage").SendFeedback
local voyager = require(game:GetService("ServerStorage").voyager)
local webhook = voyager.Webhook.new("webhookId", "webhookToken")

sendFeedbackRemote.OnServerEvent:Connect(function(player : Player, feedback : string)
    local embed = voyager.Embed.new()
        :SetDescription(feedback)
        :SetColor(Color3.fromRGB(0, 135, 255))
        :SetTimestamp()
        :SetAuthor(
            "Feedback from " .. player.DisplayName, 
            "https://www.roblox.com/users/" .. player.UserId .. "/profile"
        )
        :addField(
            "Account Age",
            "**" .. player.AccountAge .. "** Days"
        )
        :addField(
            "Has Verified Badge?",
            tostring(player.HasVerifiedBadge)
        )
        :addField(
            "From Game",
            "[Game Link](https://www.roblox.com/games/" .. game.PlaceId .. ")"
        )

    local _, requestStatus = webhook:SendMessage(nil, { embed })

    if not requestStatus.Success then
        warn("Request was not successful! " .. requestStatus.statusCode .. " " .. requestStatus.statusMessage)
    end
end)

Without Voyager

local sendFeedbackRemote = game:GetService("ReplicatedStorage").SendFeedback
local httpService = game:GetService("HttpService")

sendFeedbackRemote.OnServerEvent:Connect(function(player : Player, feedback : string)
    local requestBody = {
        ["embeds"] = {
            {
                ["description"] = feedback,
                ["author"] = {
                    ["name"] = "Feedback from " .. player.DisplayName,
                    ["url"] = "https://www.roblox.com/users/" .. player.UserId .. "/profile"
                },
                ["color"] = 34815,
                ["timestamp"] = DateTime.now():ToIsoDate(),
                ["fields"] = {
                    {
                        ["name"] = "Account Age",
                        ["value"] = "**" .. player.AccountAge .. "** Days"
                    },
                    {
                        ["name"] = "Has Verified Badge?",
                        ["value"] = tostring(player.HasVerifiedBadge)
                    },
                    {
                        ["name"] = "From Game",
                        ["value"] = "[Game Link](https://www.roblox.com/games/" .. game.PlaceId .. ")"
                    }
                }
            }
        }
    }

    local responce = httpService:RequestAsync({
        Url = "https://webhook.lewisakura.moe/api/webhooks/webhookId/webhookToken/queue",
        Method = "POST",
        Headers = {["Content-Type"] = "application/json"},
        Body = httpService:JSONEncode(requestBody)
    })

    if not responce.Success then
        warn("Request was not successful! " .. responce.StatusCode .. " " .. responce.StatusMessage)
    end
end)

Conclusion

As you can see, the example using Voyager is around 10 lines of code shorter, the code looks much better and way more readable than the example not using Voyager.