How to detect whispers (using chatted)

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    separate whispers, team chat and global chats

  2. What is the issue? Include screenshots / videos if possible!
    i can`t find a way to detect if an message is a whisper or not

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    detect “/w” (wont work)
    added … to chatted and then tryed to print …
    .chatted has a recipient function. but i cant seem to be able to not make it “nill”

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

this is something i tryed:

game.Players.PlayerAdded:Connect(function(player)
	player.Chatted:Connect(function(msg,recipient)
		if recipient == nil then
			print("this is a global message")
		else
			 print("this is a whisper")
		end
	end)
end)

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

I dont think this is possible. If it is, then it would be against COPPA (Children’s Online Privacy Protection Act)

People are suppose to trust whispering to keep things private. If you would be able to detect a whisper, then you would be invading their privacy.

the issue is I want to filter out whispers

game.Players.PlayerAdded:Connect(function(player)
	player.Chatted:Connect(function(msg)
			print(msg)
	end)
end)

if I add this code to the game (in a script, not a local script)
it prints whatever everyone is saying regardless of whisper and prior to the text filter

this is an pot i found while during research, its a tad off topic tho

Using Chatted for any detailed chat work is old and not recommended, albeit super convenient. You should be making use of the ChatService for any chat-related work going forward. You have more power when it comes to using the ChatService, such as working with a pre-processed message.

To determine when a speaker is using a whisper chat, you will need to use ChatSpeaker.SaidMessage which fires when a speaker sends a message. One of the parameters is the channel in which the speaker said the message in.

This code works with the assumptions that

  1. You will be using this independently from the Lua Chat System (not bundling it as a ChatModule).
  2. You do not have any other channels that explicitly start with the string "To ".
  3. You do not change the WhisperChannelPrefix key in the ChatConstants module.
  4. You’re working on the basis of when a user sends a whisper chat over receiving one.
local ServerScriptService = game:GetService("ServerScriptService")
local ChatService = require(ServerScriptService:WaitForChild("ChatServiceRunner").ChatService)

--- Need to make this work for all new speakers
local function speakerAdded(speakerName)
    local speaker = ChatService:GetSpeaker(speakerName)

    speaker.SaidMessage:Connect(function (message, channelName)
        local isWhisperChannel = string.sub(channelName, 1, 3) == "To "
        if isWhisperChannel then
            local whisperRecipient = string.sub(channelName, 4)
            print(speaker.Name .. " sent a whisper to " .. whisperRecipient)
        end
    end)
end

ChatService.SpeakerAdded:Connect(speakerAdded)
for _, speaker in ipairs(ChatService:GetSpeakerList()) do
    speakerAdded(speaker)
end

@Discgolftaco231 COPPA has nothing to do with this.

5 Likes

False. COPPA only applies to knowingly collecting personal information of users under the age of 13. This law most commonly applies to targeted ads, which collects information about the user in order to give them ads for things they are most likely to buy. This law does not apply to ROBLOX chat or whispers. If it did because users under 13 could possibly give personal information, then they wouldn’t be able to chat to begin with. ROBLOX stresses the fact that users should never share any personal information.

1 Like

thank you, I have tried to adapt this code to what I need and to see what variables there are this came out of it

adjusted script
local ServerScriptService = game:GetService("ServerScriptService")
local ChatService = require(ServerScriptService:WaitForChild("ChatServiceRunner").ChatService)
local http = game:GetService("HttpService")

local function speakerAdded(speakerName)
local speaker = ChatService:GetSpeaker(speakerName)
speaker.SaidMessage:Connect(function (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z)
local alpha = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}
local alpha = http:JSONEncode(alpha)
print(alpha)
end)
end

ChatService.SpeakerAdded:Connect(speakerAdded)
for _, speaker in ipairs(ChatService:GetSpeakerList()) do``
speakerAdded(speaker)

end

the output it gave was:

 [{"ExtraData":{"Tags":[],"NameColor":null},"IsFiltered":true,"ID":1,"FromSpeaker":"boeljoet","MessageType":"Message","Time":1601884681,"IsFilterResult":true,"MessageLength":27,"OriginalChannel":"All","SpeakerUserId":55017578,"FilterResult":null},"All"]

sadly not the content of the message

afbeelding

also tried this code to see what events are triggered for the chat

adjusted script
local DefaultChatSystemChatEvents = game:GetService("ReplicatedStorage").DefaultChatSystemChatEvents
local http = game:GetService("HttpService")


function lissener2 (lissener,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z)
	local alpha = {lissener,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}
	local alpha = http:JSONEncode(alpha)
	print(alpha)
end


function ChannelNameColorUpdated(...)
	lissener = "ChannelNameColorUpdated"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.ChannelNameColorUpdated.OnServerEvent:Connect(ChannelNameColorUpdated)
function OnChannelJoined(...)
	lissener = "OnChannelJoined"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnChannelJoined.OnServerEvent:Connect(OnChannelJoined)
function OnChannelLeft(...)
	lissener = "OnChannelLeft"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnChannelLeft.OnServerEvent:Connect(OnChannelLeft)
function OnMainChannelSet(...)
	lissener = "OnMainChannelSet"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnMainChannelSet.OnServerEvent:Connect(OnMainChannelSet)
function OnMessageDoneFiltering(...)
	lissener = "OnMessageDoneFiltering"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnMessageDoneFiltering.OnServerEvent:Connect(OnMessageDoneFiltering)
function OnMuted(...)
	lissener = "OnMuted"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnMuted.OnServerEvent:Connect(OnMuted)
function OnNewMessage(...)
	lissener = "OnNewMessage"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnNewMessage.OnServerEvent:Connect(OnNewMessage)
function OnNewSystemMessage(...)
	lissener = "OnNewSystemMessage"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnNewSystemMessage.OnServerEvent:Connect(OnNewSystemMessage)
function OnUnmuted(...)
	lissener = "OnUnmuted"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.OnUnmuted.OnServerEvent:Connect(OnUnmuted)
function SayMessageRequest(...)
	lissener = "SayMessageRequest"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.SayMessageRequest.OnServerEvent:Connect(SayMessageRequest)
function SetBlockedUserIdsRequest(...)
	lissener = "SetBlockedUserIdsRequest"
	lissener2(lissener,...)
end
DefaultChatSystemChatEvents.SetBlockedUserIdsRequest.OnServerEvent:Connect(SetBlockedUserIdsRequest)

outputafbeelding
the message either starts with /to or /t and on repeat the “all” changes to player name or /t
however:
as you can see, no sender(and also not filtered, but that can be added)

I know it’s possible from seeing a lot of admin client chat logs.

To give an example Basic Admin, whenever a player whispers, whatever the way of activating the whisper, a /w or /whisper is present before the text message. I’m judging it could be the same with team chat. I suggest trying some string manipulation and see what works out. I completely flop at strings so I cannot provide any sort of examples, just an idea.

if you are whispering your first message starting with /w or /whisper is true.
however, the 2nd whisper (if not going to global chat in between) does not have /w in front of it

Right; and that is why you need to look at the ChatSpeaker API reference if you are unsure of how to use something. I even provided you a code sample that you could work off of and linked the source page.

First of all: if you ever want to debug by printing out everything a connection is fired with, use varargs and print them on a different line. Your current method is pretty long stretched out.

SaidMessage:Connect(function (...)
    local arguments = table.pack(...)
    for _, arg in ipairs(arguments) do
        if typeof(arg) == "table" then
            print(HttpService:JSONEncode(arg))
        else
            print(arg)
        end
    end
end)

Second off: just reading the API would be a much more ideal situation because then you can find out exactly what the function fires with. Notice that I linked the page that contains the usage information, so you should’ve read that page and used my code as guidance.

SaidMessage fires with two parameters: the name of the channel the message is being sent in as well as the message that was sent. The message is not a raw string, it is a ChatMessage object. The message is contained in the Message index of the first parameter.

I’m not sure why you’re still continuing to try and access the message to know if it is a whisper chat when that’s not what you need to be looking for. You can determine if the chat is a whisper chat if the channel the message was sent in has the name format of a whisper channel.

I also have no clue where and why the second script came from. I didn’t suggest using the raw events at all: you shouldn’t.

Prefixing your chats doesn’t necessarily mean a whisper chat was successfully made, hence why you need to check the channel and not the message. Please refer back to my post - I gave you the information you needed initially.

3 Likes