Trying to get chatlogger (via webhook) to add whether or not a server is private or public next to name

I have a chatlogger that sends all chatted messages (from public, Studio testing, and presumably private servers too) to a 3rd-party log (via webhook) so we can remotely catch rulebreakers. Our chatlogger prints the name of the player and their message, but I want to add whether or not that player is on a private server or not to their name (preferred) or message. I… also need it to work. Cause it’s not sending messages to the webhook at all.

I will say I’m newer to scripting and generally don’t know what I’m doing. Here is the script I tried, splicing our original (working) chatlog script with a game.PrivateServerId checking script. (It looks ugly and no DOUBT I did it very, very wrong.) It’s very long so I’ve put it under a dropdown.

local HttpService = game:GetService("HttpService")

local webhook = "WEBHOOK LINK"

local function getServerType()
	if game.PrivateServerId ~= "" then
		if game.PrivateServerOwnerId ~= 0 then
			Players.PlayerAdded:Connect(function(plr)
				plr.Chatted:Connect(function(msg)
					local data = {
						content = msg;
						username = plr.Name ("PRIV");
						avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
					}
					HttpService:PostAsync(webhook, HttpService:JSONEncode(data))
					
		else
					Players.PlayerAdded:Connect(function(plr)
						plr.Chatted:Connect(function(msg)
							local data = {
								content = msg;
								username = plr.Name ("REV");
								avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
							}
							HttpService:PostAsync(webhook, HttpService:JSONEncode(data))
				end
	else
		Players.PlayerAdded:Connect(function(plr)
			plr.Chatted:Connect(function(msg)
				local data = {
					content = msg;
					username = plr.Name;
					avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
				}
				HttpService:PostAsync(webhook, HttpService:JSONEncode(data)
				end
		end		
end

Here’s our chatlogger code WITHOUT all that mess. Note that this works. I just want to specify whether the player is in a private server or not via adding it on to msg; or plr.Name;.

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

local webhook = "WEBHOOK LINK"

Players.PlayerAdded:Connect(function(plr)
	plr.Chatted:Connect(function(msg)
		local data = {
			content = msg;
			username = plr.Name;
			avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
		}
		HttpService:PostAsync(webhook, HttpService:JSONEncode(data))
	end)
end)

Help is appreciated!
Please be patient with me though, I’m autistic and may ask for clarification or for you to reword what you said. I don’t understand a lot of this stuff, but I’m trying.

2 Likes
local function getServerType()
	if game.PrivateServerId ~= "" then
		if game.PrivateServerOwnerId ~= 0 then
			return "VIPServer"
		else
			return "ReservedServer"
		end
	else
		return "StandardServer"
	end
end
1 Like

I, uh.
This isn’t what I needed/wanted to do, but alright.

1 Like

Oh I see.

Change this to plr.Name.." (PRIV)"

Do the same for plr.Name.." (REV)"

I believe it’s something in the way I structured the code above that all. This helps a little though, thanks. Definitely solves my problem of trying to add that to the names.
Now I just need to get the script work in the first place.

Use commas instead of semicolons after your table entries

It’s difficult to answer this without knowing what you’re using to receive the POST requests and how the code is handled there? Can you elaborate on how this part has been coded and/or set up if it’s with a known service?

Have you made sure HTTP requests are allowed in your game (you can turn this on in settings)? Are you getting any errors in the output window?

Looking at your code, I would imagine that there would be a few errors. As @gooey333 stated, you were trying to concatenate the values player.Name and ‘PRIV’ but the way it’s written would attempt to call the string instead. Also, the code in the Details dropdown is missing a few parentheses.

I went through your code again to see what you were doing and wrote it out as my own, whether that helps you determine what you did differently or not may be helpful.

local server
local players = game:GetService 'Players'
local http    = game:GetService 'HttpService'
local hook    = 'WEBHOOK LINK'

local function getServerType()
	if game:IsStudio() then
		return -1 -- studio
	end
	
	if game.PrivateServerId ~= '' then
		if game.PrivateServerOwnerId ~= 0 then
			return 1 -- vip
		else
			return 2 -- reserved
		end
	end
	
	return 0 -- public
end

local function post(data)
	local json = http:JSONEncode(data)
	local succ, res = pcall(function ()
		return http:PostAsync(hook, json)
	end)
	
	-- PostAsync returns the HTTP response
	if succ then
		print(data, 'sent with response', res)
	else
		warn(res)
	end
end

local function handlePlayer(player)
	if not server then
		server = getServerType()
	end
	
	player.Chatted:connect(function (msg)
		--[[
			Unless your webhook specifically requires 'content', 'username', and 'avatar_url'...
			I would try to keep the packet as small as you can. If you've made the webhook yourself and/or changed the code
			so that you can use the $avatar_url, then I would just supply the userId and add the rest of
			the link when you're on the other end.
			
			For testing, allow posts to occur if you're in studio, but once you've completed it I would likely turn off
			the functionality by adding an if statement to determine whether server ~= -1
		]]
		
		--if server ~= -1 then
			local data = {
				type = server; -- on the webservice you can then check if this value == 0 for a public server etc and display it as such
				msg  = msg;
				uid  = player.UserId;
				name = player.Name;
			}
			post(data)
		--end
	end)
end

players.PlayerAdded:connect(handlePlayer) -- new players
for _, client in ipairs(players:GetPlayers()) do -- if players have already joined, which often happens in studio
	handlePlayer(client)
end

This is definitely a lot cleaner and easier to read than what I did originally.
My service DOES require a username and message, avatar just exist for the sake of aesthetic. It wouldn’t be able to take any more data beyond those three.

HTTP requests are allowed in my game. Again, my original chatlog script (at the bottom of the post, not the one in details) works fine.
I really just want to:

  • check the server type
  • when a player sends a message in a server, have it return the server type in their username (or message)

So it’d be like:

Username1 (PRIV): message here
Username2 (PRIV): message here
Username3 (REV): message here

I’m trying to do this via splicing my working chatlog code (bottom of the original post) with the standard if game.PrivateServerId code gooey333 posted in reply.

I’m not really sure if I fully understood what you mean, or if I fully understood your code.
I did figure out returning values, but on trying to link them up, it didn’t work out.

Here’s what I’ve got now (note I didn’t add the Reserved here):

local server
local players = game:GetService 'Players'
local http    = game:GetService 'HttpService'
local hook    = 'WEBHOOK LINK'

local function getServerType()
	if game:IsStudio() then
		return -1 -- studio
	end

	if game.PrivateServerId ~= '' then
		if game.PrivateServerOwnerId ~= 0 then
			return 1 -- vip
		else
			return 2 -- reserved
		end
	end

	return 0 -- public
end

local function post(data)
	local json = http:JSONEncode(data)
	local succ, res = pcall(function ()
		return http:PostAsync(hook, json)
	end)

	-- PostAsync returns the HTTP response
	if succ then
		print(data, 'sent with response', res)
	else
		warn(res)
	end
end

local function handlePlayer(player)
	if not server then
		server = getServerType()
	end

	player.Chatted:connect(function (msg)
		if server = -1 then
		local data = {
				content = msg;
				username = plr.Name.."(STU)";
				avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
			}
		post(data)
		end
		
		player.Chatted:connect(function (msg)
			if server = 1 then
				local data = {
					content = msg;
					username = plr.Name.."(PRIV)";
					avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
				}
				post(data)
			end
			
		player.Chatted:connect(function (msg)
			if server = 0 then
				local data = {
					content = msg;
					username = plr.Name;
					avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
				}
				post(data)
			end
	end)
end

players.PlayerAdded:connect(handlePlayer) -- new players
for _, client in ipairs(players:GetPlayers()) do -- if players have already joined, which often happens in studio
	handlePlayer(client)
end

I changed the getServerType() function to return a string instead of numbers as you’ve shown you wanted above. Then I used string.format to format the “Name (SERVER_TYPE)” as you wanted it. Check out string functions here, and the format function here

Your method of using a condition statement (i.e. the if server == 0 then etc) would work, but it’s not neccessarily required if you utilise functions like string.format.

Regarding the code you posted, there’s a few issues with it that you should look at for learning purposes:

  1. On the chatted event you created a new Chatted connection. You only need the one connection, and then you can check if the message / something else meets the condition inside of that function.
  2. You didn’t properly account for the end statements, nor the parentheses

I would recommend you go to this website, which will help you better understand scopes and blocks so that you can write code that will execute how you want it to. That website also provides really great lessons for many different things you’ll need to know for future projects, I’m sure!

p.s. make sure you open the output window in View→Output, more info can be found here, but it’s going to be helpful for you to debug your code as it will tell you if your script has an error :slight_smile:

local server
local players = game:GetService 'Players'
local http    = game:GetService 'HttpService'
local hook    = 'WEBHOOK LINK'

local function getServerType()
	if game:IsStudio() then
		return 'STU' -- studio
	end
	
	if game.PrivateServerId ~= '' then
		if game.PrivateServerOwnerId ~= 0 then
			return 'VIP' -- vip
		else
			return 'PRIV' -- reserved
		end
	end
	
	return 'PUB' -- public
end

local function post(data)
	local json = http:JSONEncode(data)
	local succ, res = pcall(function ()
		return http:PostAsync(hook, json)
	end)
	
	-- PostAsync returns the HTTP response
	if succ then
		print(data, 'sent with response', res)
	else
		warn(res)
	end
end

local function handlePlayer(player)
	if not server then
		server = getServerType()
	end
	
	player.Chatted:connect(function (msg)
		--[[
			Unless your webhook specifically requires 'content', 'username', and 'avatar_url'...
			I would try to keep the packet as small as you can. If you've made the webhook yourself and/or changed the code
			so that you can use the $avatar_url, then I would just supply the userId and add the rest of
			the link when you're on the other end.
			
			For testing, allow posts to occur if you're in studio, but once you've completed it I would likely turn off
			the functionality by adding an if statement to determine whether server ~= -1
		]]
		
		local nameAndServer = string.format('%s (%s)', plr.Name, server) -- this formats the string '%s (%s)' so that the first %s is the name of the player, and the second is the server type
		local data = {
			content    = msg;
			username   = nameAndServer;
			avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..plr.UserId
		}
		post(data)
	end)
end

players.PlayerAdded:connect(handlePlayer)
for _, client in ipairs(players:GetPlayers()) do
	handlePlayer(client)
end
1 Like

Thank you, you are a GODSEND.
However, this doesn’t appear to be working.
The output is returning this in regards to the script:

  17:20:05.212  IsStudio is not a valid member of DataModel "filename.rbxl"  -  Server - Chat logs + priv check:7
  17:20:05.212  Stack Begin  -  Studio
  17:20:05.212  Script 'ServerScriptService.Chat Logs.Chat logs + priv check', Line 7 - function getServerType  -  Studio - Chat logs + priv check:7
  17:20:05.212  Script 'ServerScriptService.Chat Logs.Chat logs + priv check', Line 38 - function handlePlayer  -  Studio - Chat logs + priv check:38

Shouldn’t game:IsStudio be RunService:IsStudio? Also requiring that I include local RunService = game:GetService("RunService")?

Sorry, yes it is a method of RunService. Should be changed to game:GetService(‘RunService’):IsStudio() - apologies!

1 Like

After fixing that, the output is now returning this:

22:55:30.680  ServerScriptService.Chat Logs.Chat logs + priv check:42: attempt to index nil with 'Name'  -  Server - Chat logs + priv check:42
22:55:30.680  Script 'ServerScriptService.Chat Logs.Chat logs + priv check', Line 42  -  Studio - Chat logs + priv check:42

I’m stumped, because line 42 looks fine to me. Unlike the previous error (which appeared in the output upon opening the game), this appears after I type something into chat.

Synaptix and I tweaked it in DMs, so here’s the final code for anybody in the future who wants to do this same thing. Who knows, Devforum posts from 3 years ago have saved me so much pain before.

local server
local players = game:GetService 'Players'
local http    = game:GetService 'HttpService'
local hook    = 'WEBHOOK LINK'

local function getServerType()
	if game:GetService('RunService'):IsStudio() then
		return 'STU' -- studio
	end
	
	if game.PrivateServerId ~= '' then
		if game.PrivateServerOwnerId ~= 0 then
			return 'PRIV' -- private
		else
			return 'REV' -- reserved
		end
	end
	
	return 'PUB' -- public
end

local function post(data)
	local json = http:JSONEncode(data)
	local succ, res = pcall(function ()
		return http:PostAsync(hook, json)
	end)
	
	-- PostAsync returns the HTTP response
	if succ then
		print(data, 'sent with response', res)
	else
		warn(res)
	end
end

local function handlePlayer(player)
	if not server then
		server = getServerType()
	end
	
	player.Chatted:connect(function (msg)
		local nameAndServer = string.format('%s (%s)', player.Name, server) -- this formats the string '%s (%s)' so that the first %s is the name of the player, and the second is the server type
		local data = {
			content    = msg;
			username   = nameAndServer;
			avatar_url = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userId="..player.UserId
		}
		post(data)
	end)
end

players.PlayerAdded:connect(handlePlayer)
for _, client in ipairs(players:GetPlayers()) do
	handlePlayer(client)
end
4 Likes