Roblox to Discord API

I rewrote a roblox to discord API for public use. You can get the model here: https://www.roblox.com/library/4738830685/Roblox-Webhook-API. If you need an example or reference page then please let me know. It’s pretty straight forward, however.

Also, let me know if you want anything else added to the webhook API. I am also trying to find out a way to write an API for discord bots too; don’t expect this anytime soon, unfortunately. I look forward to hearing your replies.

Settings of API:

local apisettings = {}

apisettings["hex"] = {
	["join"] = "adffb4",
	["leave"] = "ff9494"
}

apisettings["rgb"] = {
	["join"] = {173,255,180},
	["leave"] = {255,148,148}
}

apisettings["webhooks"] = {
	["general"] = (""),
	["logs"] = ("")
}

function apisettings:GetWebhook(channel)
	return apisettings.webhooks[channel]
end

function apisettings:SetColourMode(mode)
	self.colourMode = mode
end

function apisettings:GetColourMode()
	return self.colourMode
end

function apisettings:GetJoinColour()
	return apisettings[apisettings:GetColourMode()].join
end

function apisettings:GetLeaveColour()
	return apisettings[apisettings:GetColourMode()].leave
end

return apisettings

Here, you can change the settings of the API - whether you want to use colour modes from hex or RGB (setcolourmode) and you can also enter the multiple webhooks you may or may not have for your server (it accepts 1 or more - make sure you name the webhook in the dictionary to the respective webhook in your server).

local hex = {}

function numberToString(i)
    local options = {"F", "E", "D", "C", "B", "A"}
    return options[16-i]
end

function hexOf(i)
    local base = math.floor(i/16)
    local remainder = (i - (base * 16))
    if base >= 10 then
        base = numberToString(base)
    end
    if remainder >= 10 then
        remainder = numberToString(remainder)
    end
    return(base..remainder)
end

function hex:FromRGB(r, g, b)
	return (hexOf(r)..hexOf(g)..hexOf(b))
end

function hex:FromTable(rgb_table)
	return (hexOf(rgb_table[1])..hexOf(rgb_table[2])..hexOf(rgb_table[3]))
end

function hex:FromBrickColour(brick_colour)
	local r = math.floor(brick_colour.Color.r * 255)
	local g = math.floor(brick_colour.Color.g * 255)
	local b = math.floor(brick_colour.Color.b * 255)
	return hex:FromRGB(r, g, b)
end

return hex

This API also uses a hex converter - you can convert from: RGB - 255, 255, 255; a table - {255,255,255} and from a BrickColor - BrickColor.new(“Really red”).

local chat_colour = {}


local player_colours = {
	BrickColor.new("Bright red"),
	BrickColor.new("Bright blue"),
	BrickColor.new("Earth green"),
	BrickColor.new("Bright violet"),
	BrickColor.new("Bright orange"),
	BrickColor.new("Bright yellow"),
	BrickColor.new("Light reddish violet"),
	BrickColor.new("Brick yellow"),
}

function GetNameValue(Name)
	local Length = #Name
	local Value = 0
	for Index = 1, Length do
		local CharacterValue = string.byte(string.sub(Name, Index, Index))
		local ReverseIndex = Length - Index + 1
		if Length % 2 == 1 then
			ReverseIndex = ReverseIndex - 1
		end
		if ReverseIndex % 4 >= 2 then
			CharacterValue = -CharacterValue
		end
		Value = Value + CharacterValue
	end
	return Value % 8
end

function chat_colour:getNameValue(name)
	local length = #name
	local value = 0
	for i = 1, length do
		local char_value = string.byte(string.sub(name, i, i))
		local reverse_index = length - i + 1
		if length % 2 == 1 then
			reverse_index = reverse_index - 1
		end
		if length % 4 >= 2 then
			char_value = -char_value
		end
		value = value + char_value
	end
	return value % 8
end

function chat_colour:getChatColour(name)
	return player_colours[chat_colour:getNameValue(name) - 1]
end

return chat_colour

If you wish to send a RichEmbed with a colour corresponding to the player’s chatcolour, you can do so with this module; give it a player name and it will return the BrickColor value of their name. For example:

chat_color:getChatColour("xJDiviisionZ") 
--> BrickColor.new("Really red")

The main API:

local webHook = {}
webHook.__index = webHook

local webhook_settings = require(script.Settings)
local hex = require(script.ValueToHex)

local HttpService = game:GetService("HttpService")
local Url = ("")

webhook_settings:SetColourMode("rgb")

function webHook:FromIDAndKey(id, key)
	Url = ("https://discordapp.com/api/webhooks/"..id.."/"..key)
end

function webHook:FromURL(new_url)
	Url = new_url
end

function webHook:Get()
	return Url
end

function webHook:GetChannelWebhook(channel)
	return webhook_settings.webhooks[channel]
end

function webHook:SetChannel(channel)
	return webHook:FromURL(webHook:GetChannelWebhook(channel))
end

function webHook:postMessage(message, player, channel)
	if channel then
		webHook:FromURL(webhook_settings:GetWebhook(channel))
	end
	local from = player or nil
	local content
	if from then
		content = (from..": ".. message)
	else
		content = message
	end
	local data = {["content"] = content}
	local newdata = HttpService:JSONEncode(data)
	HttpService:PostAsync(webHook:Get(), newdata)
end

function webHook:newRichEmbed()
	self.richEmbedData = {["embeds"] = {}}
	self.embedData = {}
	self.embedData["type"] = "rich"
	self.embedData["fields"] = {}
end

function webHook:updateRichEmbed()
	self.richEmbedData = {["embeds"] = {}}
	table.insert(self.richEmbedData.embeds, self.embedData)
end

function webHook:setTitle(title)
	if not typeof(title) == "string" then
		return error("Title must be a string value.")
	end
	self.embedData["title"] = title
	return webHook:updateRichEmbed()
end

function webHook:setImage(image_url)
	if not typeof(image_url) == "string" then
		return error("URL must be in string format.")
	end
	self.embedData["thumbnail"] = {["url"] = image_url}
	return webHook:updateRichEmbed()
end

function webHook:setDescription(description)
	if not typeof(description) == "string" then
		return error("Description must be a string value.")
	end
	self.embedData["description"] = description
	return webHook:updateRichEmbed()
end

function webHook:setColor(color)
	if not typeof(color) == "string" then
		return error("Color must be a HEX string value.")
	elseif string.len(color) > 6 then
		return error("Color's length can be no longer than 6.")
	elseif string.len(color) % 2 == 1 then
		return error("Color's length must be even.")
	end
	local new_color = ("0x"..color)
	self.embedData["color"] = tonumber(new_color)
	return webHook:updateRichEmbed()
end

function webHook:addField(field_data)
	local name = field_data["title"] or "Title"
	local value = field_data["content"] or "Content"
	local inline = field_data["inline"] or true
	table.insert(self.embedData["fields"], {["name"] = name, ["value"] = value, ["inline"] = inline})
	return webHook:updateRichEmbed()
end

function webHook:postRichEmbed(channel)
	if channel then
		webHook:FromURL(webhook_settings:GetWebhook(channel))
	end
	local data = self.richEmbedData
	local newdata = HttpService:JSONEncode(data)
	HttpService:PostAsync(webHook:Get(), newdata)
end

function webHook:newPlayerJoined(name, id, image, channel)
	if channel then
		webHook:FromURL(webhook_settings:GetWebhook(channel))
	end
	local userid = id or nil
	local image = image or ""
	local content
	local colour
	if userid then
		content = (name.." - "..userid)
	else
		content = (name)
	end
	if webhook_settings:GetColourMode() == "hex" then
		colour = webhook_settings:GetJoinColour()
	elseif webhook_settings:GetColourMode() == "rgb" then
		colour = hex:FromTable(webhook_settings:GetJoinColour())
	end
	webHook:newRichEmbed()
	webHook:setTitle("Player Joined")
	webHook:addField({["title"] = "Player Info", ["content"] = content, ["inline"] = true})
	webHook:setColor(colour)
	webHook:setImage(image)
	webHook:postRichEmbed()
end

function webHook:newPlayerLeft(name, id, image, channel)
	if channel then
		webHook:FromURL(webhook_settings:GetWebhook(channel))
	end
	local userid = id or nil
	local image = image or ""
	local content
	local colour
	if userid then
		content = (name.." - "..userid)
	else
		content = (name)
	end
	if webhook_settings:GetColourMode() == "hex" then
		colour = webhook_settings:GetLeaveColour()
	elseif webhook_settings:GetColourMode() == "rgb" then
		colour = hex:FromTable(webhook_settings:GetLeaveColour())
	end
	webHook:newRichEmbed()
	webHook:setTitle("Player Left")
	webHook:addField({["title"] = "Player Info", ["content"] = content, ["inline"] = true})
	webHook:setColor(colour)
	webHook:setImage(image)
	webHook:postRichEmbed()
end

return webHook

In here, you will find a multitude of functions which allow you to play around with the webhooks. They should be self explanatory but if you need any help, let me know.

An example of how to use this script:

local api = script.Parent
local webhook = require(api)
local chat_colours = require(api.GetChatColour)
local hex = require(api.ValueToHex)

webhook:FromURL("https://your.webhook.url")
webhook:SetChannel("your-webhook-channel")

game.Players.PlayerAdded:connect(function(player)
	local thumbnail, loaded = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
	webhook:newPlayerJoined(player.Name, player.UserId, tostring(thumbnail))
	player.Chatted:connect(function(message)
		webhook:newRichEmbed()
		webhook:setTitle(player.Name)
		webhook:setColor(hex:FromBrickColour(chat_colours:getChatColour(player.Name)))
		webhook:addField({["title"] = "Message", ["content"] = message, ["inline"] = true})
		webhook:postRichEmbed()
		webhook:postMessage(message)
	end)
end)

game.Players.PlayerRemoving:connect(function(player)
	local thumbnail, loaded = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
	webhook:newPlayerLeft(player.Name, player.UserId, tostring(thumbnail))
end)

Note that when creating richEmbeds, you must set all the content you wish to embed THEN post it. For example:

webhook:newRichEmbed() -- creates a new RichEmbed
webhook:setTitle("Test") -- sets the title of the RichEmbed we just created to a string value
webhook:setColor(hex:FromTable({255, 0, 0}) -- sets the colour to the table value 
-- remember you can use other means to convert to hex
webhook:addField({["title"] = "Testing", ["content"] = "This is the content of the field", ["inline"] = true})
-- note that inline is set to true by default
-- now that we've setup the RichEmbed, we can post it
-- either by:
webhook:postRichEmbed()
-- or
webhook:postRichEmbed("general")
-- the above allows you to change the channel without using webhook:SetChannel()
44 Likes

Thank you for the tutorial, i’m sure you spent much time on making this!

Appreciate the feedback. Yes, it took a while to set it up but it was fun, nonetheless.

2 Likes

It would be better if it was object/class-oriented.

1 Like

Nice contribution. Although I’d prefer writing my own code instead of using an API, but it seems a good way to save yourself some time.

What exactly would you want with it to be a new class? If you could provide some examples, that would be nice.

Basically, instead of using one object to define every method in the API, I recommend separating them into different objects. For example, instead of doing webhook:newRichEmbed(), you would do

local embed = webhook:newRichEmbed()
embed:setTitle("stuff")
embed:setColor()
webhook:postMessage(embed)

This can easily be achieved by making different tables, just like you have local module = {}, except you would have local embed = {} and have different methods/properties inside that object. Then, with that webhook:newRichEmbed() method, you can simply return the embed object.

1 Like

Yeah I get that. I just wanted to make it similar to Discord.js. I might rewrite it if people wanted it… thanks for the suggestion :^)

Yeah, I write Discord bots in discord.js too. Object Oriented Programming is really powerful and much easier to understand.

1 Like

That is true but it’s also not very like… it’s not really a common script so I don’t want to detract too much attention from my current projects to rewrite it. Thanks for the suggestion though.

Haha, you mean basically what I use for my Roblox game? I would publish the module that I use but it’s not exactly optimal and wrote it just recently in a rushed span of 20 minutes LOL.
Might consider if really needed though!
(Bad indentation in the code goes brr.)

EDIT: The post function also allows you to post multiple embeds at once.

1 Like

Theres a cool built-in way to convert between hex now, though I don’t have a clue when each were first implemented.

local color = Color3.fromHex("#ffffff");
local hex = string.format('%x%x%x', 255, 255, 255);