This bot is a real hard finger, and works perfectly.
Or a possibility for us to create such things.
If you are capable of scripting something yourself, yes.
Otherwise, probably notâŠ
Yes if I just have a start. lol
You can find some very helpful tutorials at #development:tutorials
Also these links may come in handy:
FiveM Wiki
FiveM Natives reference
FiveM Docs
GTAForums
Also check the resources of other ppl and how they did certain things, that helped me a lot when I started
There is. Just copy my code and you should be fine. This will send all the special commands to a separate channel.
Note: This is my first try to understand and edit lua. I could have made some mistakes but it works.
Config.lua
DiscordWebhookSystemInfos = 'WEBHOOK_LINK_HERE'
DiscordWebhookKillinglogs = 'WEBHOOK_LINK_HERE'
DiscordWebhookChat = 'WEBHOOK_LINK_HERE'
DiscordWebhookDispatch = 'WEBHOOK_LINK_HERE'
SystemAvatar = 'https://wiki.fivem.net/w/images/d/db/FiveM-Wiki.png'
UserAvatar = 'https://i.imgur.com/KIcqSYs.png'
SystemName = 'SYSTEM'
--[[ Special Commands formatting
*YOUR_TEXT* --> Make Text Italics in Discord
**YOUR_TEXT** --> Make Text Bold in Discord
***YOUR_TEXT*** --> Make Text Italics & Bold in Discord
__YOUR_TEXT__ --> Underline Text in Discord
__*YOUR_TEXT*__ --> Underline Text and make it Italics in Discord
__**YOUR_TEXT**__ --> Underline Text and make it Bold in Discord
__***YOUR_TEXT***__ --> Underline Text and make it Italics & Bold in Discord
~~YOUR_TEXT~~ --> Strikethrough Text in Discord
]]
-- Use 'USERNAME_NEEDED_HERE' without the quotes if you need a Users Name in a special command
-- Use 'USERID_NEEDED_HERE' without the quotes if you need a Users ID in a special command
-- These Special Commands will be printed differently in Discord, depending on what you set it to
SpecialCommands = {
{'/911', '__**[911]**__: Dispatch to civilian channel!'},
}
-- These Blacklisted Commands will not be printed in Discord
BlacklistedCommands = {
'/fix',
'/revive',
}
server.lua
-- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA!
-- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA!
-- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA! -- JUST EDIT THE CONFIG.LUA!
-- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE!
-- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE!
-- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE!
-- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE!
-- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE!
-- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE! -- DO NOT EDIT THESE!
-- Error Check
if DiscordWebhookSystemInfos == nil and DiscordWebhookKillinglogs == nil and DiscordWebhookChat == nil and DiscordWebhookDisp[atch == nil then
local Content = LoadResourceFile(GetCurrentResourceName(), 'config.lua')
Content = load(Content)
Content()
end
if DiscordWebhookSystemInfos == 'WEBHOOK_LINK_HERE' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': Please add your "System Infos" Webhook\n\n')
else
PerformHttpRequest(DiscordWebhookSystemInfos, function(Error, Content, Head)
if Content == '{"code": 50027, "message": "Invalid Webhook Token"}' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': "System Infos" Webhook non-existing!\n\n')
end
end)
end
if DiscordWebhookKillinglogs == 'WEBHOOK_LINK_HERE' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': Please add your "Killing Log" Webhook\n\n')
else
PerformHttpRequest(DiscordWebhookKillinglogs, function(Error, Content, Head)
if Content == '{"code": 50027, "message": "Invalid Webhook Token"}' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': "Killing Log" Webhook non-existing!\n\n')
end
end)
end
if DiscordWebhookChat == 'WEBHOOK_LINK_HERE' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': Please add your "Chat" Webhook\n\n')
else
PerformHttpRequest(DiscordWebhookChat, function(Error, Content, Head)
if Content == '{"code": 50027, "message": "Invalid Webhook Token"}' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': "Chat" Webhook non-existing!\n\n')
end
end)
end
if DiscordWebhookDispatch == 'WEBHOOK_LINK_HERE' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': Please add your "Dispatch" Webhook\n\n')
else
PerformHttpRequest(DiscordWebhookChat, function(Error, Content, Head)
if Content == '{"code": 50027, "message": "Invalid Webhook Token"}' then
print('\n\nERROR\n' .. GetCurrentResourceName() .. ': "Dispatch" Webhook non-existing!\n\n')
end
end)
end
-- System Infos
PerformHttpRequest(DiscordWebhookSystemInfos, function(Error, Content, Head) end, 'POST', json.encode({username = SystemName, content = '**FiveM Server Webhook Started**'}), { ['Content-Type'] = 'application/json' })
AddEventHandler('playerConnecting', function()
ToDiscord(DiscordWebhookSystemInfos, SystemName, '```css\n' .. GetPlayerName(source) .. ' connecting\n```', SystemAvatar)
end)
AddEventHandler('playerDropped', function(Reason)
ToDiscord(DiscordWebhookSystemInfos, SystemName, '```fix\n' .. GetPlayerName(source) .. ' left (' .. Reason .. ')\n```', SystemAvatar)
end)
-- Killing Log
RegisterServerEvent('PlayerDied')
AddEventHandler('PlayerDied', function(Message, Weapon)
local date = os.date('*t')
if date.day < 10 then date.day = '0' .. tostring(date.day) end
if date.month < 10 then date.month = '0' .. tostring(date.month) end
if date.hour < 10 then date.hour = '0' .. tostring(date.hour) end
if date.min < 10 then date.min = '0' .. tostring(date.min) end
if date.sec < 10 then date.sec = '0' .. tostring(date.sec) end
if Weapon then
Message = Message .. ' [' .. Weapon .. ']'
end
ToDiscord(DiscordWebhookKillinglogs, SystemName, Message .. ' `' .. date.day .. '.' .. date.month .. '.' .. date.year .. ' - ' .. date.hour .. ':' .. date.min .. ':' .. date.sec .. '`', SystemAvatar)
end)
-- Chat
AddEventHandler('chatMessage', function(Source, Name, Message)
--Removing Color Codes (^0, ^1, ^2 etc.) from the name and the message
for i = 0, 9 do
Message = Message:gsub('%^' .. i, '')
Name = Name:gsub('%^' .. i, '')
end
--Checking if the message contains a special command
if IsCommand(Message, 'Special') then
Message = ReplaceSpecialCommand(Message, Source)
--Getting the steam avatar
local AvatarURL = UserAvatar
if GetIDFromSource('steam', Source) then
print('Using Steam')
local SteamIDHex = GetIDFromSource('steam', Source)
local SteamIDInt = tonumber(SteamIDHex, 16)
PerformHttpRequest('http://steamcommunity.com/profiles/' .. SteamIDInt .. '/?xml=1', function(Error, Content, Head)
local SteamProfileSplitted = stringsplit(Content, '\n')
for i, Line in ipairs(SteamProfileSplitted) do
if Line:find('<avatarFull>') then
local AvatarURL = Line:gsub(' <avatarFull><!%[CDATA%[', ''):gsub(']]></avatarFull>', '')
ToDiscord(DiscordWebhookDispatch, Name .. ' [ID: ' .. Source .. ']', Message, AvatarURL) --Sending the message to discord
break
end
end
end)
else
ToDiscord(DiscordWebhookDispatch, Name .. ' [ID: ' .. Source .. ']', Message, AvatarURL) --Sending the message to discord
end
return false
end
-- Shortens the Name, if needed
if Name:len() > 23 then
Name = Name:sub(1, 23)
end
--Checking if the message contains a blacklisted command
if not IsCommand(Message, 'Blacklisted') then
--Getting the steam avatar
local AvatarURL = UserAvatar
if GetIDFromSource('steam', Source) then
print('Using Steam')
local SteamIDHex = GetIDFromSource('steam', Source)
local SteamIDInt = tonumber(SteamIDHex, 16)
PerformHttpRequest('http://steamcommunity.com/profiles/' .. SteamIDInt .. '/?xml=1', function(Error, Content, Head)
local SteamProfileSplitted = stringsplit(Content, '\n')
for i, Line in ipairs(SteamProfileSplitted) do
if Line:find('<avatarFull>') then
local AvatarURL = Line:gsub(' <avatarFull><!%[CDATA%[', ''):gsub(']]></avatarFull>', '')
ToDiscord(DiscordWebhookChat, Name .. ' [ID: ' .. Source .. ']', Message, AvatarURL) --Sending the message to discord
break
end
end
end)
else
ToDiscord(DiscordWebhookChat, Name .. ' [ID: ' .. Source .. ']', Message, AvatarURL) --Sending the message to discord
end
end
end)
-- Functions
function ToDiscord(WebHook, Name, Message, Image)
if Message == nil or Message == '' then
return false
end
PerformHttpRequest(WebHook, function(Error, Content, Head) end, 'POST', json.encode({username = Name, content = Message, avatar_url = Image}), { ['Content-Type'] = 'application/json' })
end
function IsCommand(String, Type)
local StringSplitted = stringsplit(String, ' ')
if Type == 'Blacklisted' then
for i, BlacklistedCommand in ipairs(BlacklistedCommands) do
if StringSplitted[1]:lower() == BlacklistedCommand:lower() then
return true
end
end
elseif Type == 'Special' then
for i, SpecialCommand in ipairs(SpecialCommands) do
if StringSplitted[1]:lower() == SpecialCommand[1]:lower() then
return true
end
end
end
return false
end
function ReplaceSpecialCommand(String, Source)
local StringSplitted = stringsplit(String, ' ')
for i, SpecialCommand in ipairs(SpecialCommands) do
if StringSplitted[1]:lower() == SpecialCommand[1]:lower() then
StringSplitted[1] = SpecialCommand[2]
local newString = ''
for k, StringPart in ipairs(StringSplitted) do
if newString == '' then
newString = StringPart
else
newString = newString .. ' ' .. StringPart
end
end
newString = newString:gsub('USERNAME_NEEDED_HERE', GetPlayerName(Source))
newString = newString:gsub('USERID_NEEDED_HERE', Source)
return newString
end
end
end
function stringsplit(input, seperator)
if seperator == nil then
seperator = '%s'
end
local t={} ; i=1
for str in string.gmatch(input, '([^'..seperator..']+)') do
t[i] = str
i = i + 1
end
return t
end
function GetIDFromSource(Type, ID) --(Thanks To WolfKnight [forum.FiveM.net])
local IDs = GetPlayerIdentifiers(ID)
for k, CurrentID in pairs(IDs) do
local ID = stringsplit(CurrentID, ':')
if (ID[1]:lower() == string.lower(Type)) then
return ID[2]:lower()
end
end
return nil
end
-- Version Checking down here, better don't touch this
local CurrentVersion = '1.4.4'
local UpdateAvailable = false
local GithubResourceName = 'DiscordBot'
PerformHttpRequest('https://raw.githubusercontent.com/Flatracer/' .. GithubResourceName .. '_Resources/master/VERSION', function(Error, NewestVersion, Header)
PerformHttpRequest('https://raw.githubusercontent.com/Flatracer/' .. GithubResourceName .. '_Resources/master/CHANGES', function(Error, Changes, Header)
PerformHttpRequest('https://raw.githubusercontent.com/Flatracer/' .. GithubResourceName .. '_Resources/master/PREVIOUSVERSION', function(Error, PreviousVersion, Header)
print('\n')
print('##############')
print('## ' .. GithubResourceName)
print('##')
print('## Current Version: ' .. CurrentVersion)
print('## Newest Version: ' .. NewestVersion)
print('##')
if CurrentVersion ~= NewestVersion then
if CurrentVersion == PreviousVersion then
UpdateAvailable = true
end
print('## Outdated')
print('## Check the Topic')
if UpdateAvailable then
print('## Or type "update ' .. GetCurrentResourceName() .. '"')
end
print('## For the newest Version!')
print('##############')
print('CHANGES: ' .. Changes)
else
UpdateAvailable = false
print('## Up to date!')
print('##############')
end
print('\n')
end)
end)
end)
-- Instant Update down here, better don't touch this as well
AddEventHandler('rconCommand', function(CMDName, Arguments)
if CMDName:lower() == 'update' then
if #Arguments == 1 then
if Arguments[1]:lower() == GetCurrentResourceName():lower() then
TriggerEvent(GetCurrentResourceName() .. ':StartUpdate')
end
else
print('Argument count mismatch (Passed: ' .. #Arguments .. ', Wanted: 1)')
end
CancelEvent()
end
end)
RegisterServerEvent(GetCurrentResourceName() .. ':StartUpdate')
AddEventHandler(GetCurrentResourceName() .. ':StartUpdate', function()
if UpdateAvailable then
PerformHttpRequest('https://raw.githubusercontent.com/Flatracer/' .. GithubResourceName .. '_Resources/master/CHANGEDFILES', function(Error, Content, Header)
ContentSplitted = stringsplit(Content, '\n')
for k, Line in ipairs(ContentSplitted) do
local PreviousContent = ''
if Line:find('-add') then
Line = Line:gsub('-add')
PreviousContent = LoadResourceFile(GetCurrentResourceName(), Line) .. '\n'
end
PerformHttpRequest('https://raw.githubusercontent.com/Flatracer/' .. GithubResourceName .. '/master/' .. Line, function(Error, NewContent, Header)
SaveResourceFile(GetCurrentResourceName(), Line, PreviousContent .. NewContent, -1)
end)
end
end)
print('Update finished! Enter "restart ' .. GetCurrentResourceName() .. '" now!')
else
print('This is already the newest version! [' .. CurrentVersion .. ']')
end
end)
Do you know a way to do this with a button?
For example:
We are using action menu to give us our weapons. Now I would like to make a submenu called âRadioâ.
Is this submenu I would like to have some buttons. Maybe that Iâm code 4 or something.
How would I do this? Iâve tried it for like 6 hours now but canât get it to work. Can you please help me?
Sweet. Iâll throw this on and test it. If everything works, you rock!
Dude, you rock.
It had a error on Line 13 of the server.lua. Just a [ where there shouldnât have been. Fixed it and it works perfectly! Thank you.
FIX:
if DiscordWebhookSystemInfos == nil and DiscordWebhookKillinglogs == nil and DiscordWebhookChat == nil and DiscordWebhookDispatch == nil then
Updated to v1.5.0
- Added the option to specify commands which have their own webhook link
- Changed the âToDiscordâ function to an event (Can be called from other resources now)
Download in the First Post!
Is there a way to update the resource by typing a command via RCON?
This is not available for this update, with a reason. It would overwrite the config.lua
and remove your configuration. So please update it yourself.
This update broke for me? Not sure if this is on your end or what but the only thing that now gets streamed is players connecting and deaths but any message sent by players in game is not streamed.
IGNORE THIS
Huh, is it working or not?
Was working for me before I uploaded it,Iâd be weird if it doesnât work for you.
No it works I just restarted it and it was only streaming connecting players and players who died but I forgot to add the config to it.
Could you help me with trying to get it working with a button? I would really appreciate it!
I have tried it myself but I canât get it working at all. xD
Do you understand the way Action Menu
works?
I havenât checked it out, so I canât help right now
If you understand it, then just call this event with the buttons you added:
If you want to use one of the three default channel, you can use this:
-- The channel can be one of these: 'chat' or 'system' or 'kill'
TriggerEvent('DiscordBot:ToDiscord', 'WHICH_CHANNEL', 'NAME', 'MESSAGE', 'IMAGE_URL', true)
Otherwise, if you want to use a different webhook link, use this:
TriggerEvent('DiscordBot:ToDiscord', 'YOUR_WEBHOOK_HERE', 'NAME', 'MESSAGE', 'IMAGE_URL', false)
Yhea I was playing with this to. But still nothing. This is what Iâm using. Iâm doing this in a client loaded script.
if ( data == "Code 10" ) then
RemoveAllPedWeapons(GetPlayerPed(-1),true)
chatPrint( "OC: Code 10 gemeld! Fijne dag gewenst!")
TriggerEvent('DiscordBot:ToDiscord', 'myhookthingy', 'MyMom', '__**[OC]**__:** Ik meld me code 10.**', 'https://i.imgur.com/dX7bext.png', true)
I even tried to replace the whole event and replace it with a net event but still not any sign of it.
--Event to actually send Messages to Discord
RegisterNetEvent('DiscordBot:ToDiscord')
AddEventHandler('DiscordBot:ToDiscord', function(WebHook, Name, Message, Image, External)
if Message == nil or Message == '' then
return nil
end
if External then
Image = SystemAvatar
if WebHook:lower() == 'chat' then
WebHook = DiscordWebhookChat
elseif WebHook:lower() == 'system' then
WebHook = DiscordWebhookSystemInfos
elseif WebHook:lower() == 'kill' then
WebHook = DiscordWebhookKillinglogs
else
return nil
end
end
PerformHttpRequest(WebHook, function(Error, Content, Head) end, 'POST', json.encode({username = Name, content = Message, avatar_url = Image}), { ['Content-Type'] = 'application/json' })
end)
I also renamed the netevent to something else. Not that any of it worked
Three thingsâŠ
- You just posted your webhook link, someone could abuse itâŠ
- Change the true at the end of the
TriggerEvent
to false. - If you want to call if from a client sided script, use
TriggerServerEvent
, instead ofTriggerEvent
BlockquoteError running system event handling function for resource DiscordBot: citizen:/scripting/lua/scheduler.lua:41: Failed to execute thread: server/server.lua:157: bad argument #1 to âfor iteratorâ (table expected, got nil)
stack traceback:
[C]: in for iterator âfor iteratorâ
server/server.lua:157: in function âIsCommandâ
server/server.lua:83: in upvalue âhandlerâ
citizen:/scripting/lua/scheduler.lua:175: in function citizen:/scripting/lua/scheduler.lua:174
stack traceback:
[C]: in function âerrorâ
citizen:/scripting/lua/scheduler.lua:41: in field âCreateThreadNowâ
citizen:/scripting/lua/scheduler.lua:174: in function citizen:/scripting/lua/scheduler.lua:138
âĄÆöâcTm | www.fiverp.ro: t
hitch warning: frame time of 159 milliseconds
Sending heartbeat to live-internal.fivem.net:30110
Sending heartbeat to live-internal.fivem.net:30110
1
1
1
Sending heartbeat to live-internal.fivem.net:30110
Sending heartbeat to live-internal.fivem.net:30110
Sending heartbeat to live-internal.fivem.net:30110
Error running system event handling function for resource DiscordBot: citizen:/scripting/lua/scheduler.lua:41: Failed to execute thread: server/server.lua:157: bad argument #1 to âfor iteratorâ (table expected, got nil)
stack traceback:
[C]: in for iterator âfor iteratorâ
server/server.lua:157: in function âIsCommandâ
server/server.lua:83: in upvalue âhandlerâ
citizen:/scripting/lua/scheduler.lua:175: in function citizen:/scripting/lua/scheduler.lua:174
stack traceback:
[C]: in function âerrorâ
citizen:/scripting/lua/scheduler.lua:41: in field âCreateThreadNowâ
citizen:/scripting/lua/scheduler.lua:174: in function citizen:/scripting/lua/scheduler.lua:138