Integrate TextChatService:CanUsersDirectChatAsync or TextChannel:SetDirectChatRequester API to Comply with Settings

Hi Creators,

This post is a follow-up to our announcement about the removal of the legacy chat system and the requirement for all creators to migrate to TextChatService by April 30th, 2025.

We’ve released a new TextChatService:CanUserDirectChatAsync API and we will release TextChannel:SetDirectChatRequester API, by November 15th, 2024. These APIs determine whether users can receive direct chats in experience, based on the user and parental control settings. Creators who have implemented direct chat in their experience using a custom chat or forked legacy chat system implementation are required to adopt one of these APIs by January 30th, 2025. Full details of the action you may need to take are in the table below.

Who needs to take action:

Type of direct chat implementation Action required
1. Using default text channels in TextChatService None
2. Non-modified legacy chat systems By April 30, 2025
Migrate to TextChatService
3. Either:
a. Forked version of the legacy chat system


b. Custom chat that does not use legacy chat system or TextChatService as its backend
By January 30, 2025
Integrate TextChatService: CanUserDirectChatAsync API and check that Whisper and direct chats are gated by this method; OR
Migrate to TextChatService

By April 30, 2025
Migrate to TextChatService
4. Using TextChatService with a custom implementation of direct chat outside of default text channels By January 30, 2025
Integrate TextChannel: SetDirectChatRequestor API

Migrate to TextChatService Instead

We’ve made the TextChatService:CanUserDirectChatAsync API available as a transitional solution for creators who need more time to migrate to TextChatService. However, if you can, we recommend moving to TextChatService by January 30th, 2025 and integrating TextChannel:SetDirectChatRequester if necessary. Last week, we added two of the most requested features, Channel Tabs and UI Gradient to TextChatService. We’re continuing to invest in TextChatService, improving its performance and developing new features. TextChatService includes real-time chat translation which helps drive experience engagement.

What is direct chat?

Direct chat is a user-initiated chat that can only be seen by the users who initiated the chat, and the user who was requested to be in the chat. Chat is not visible to other users in the same experience. Whisper is one example of a user-initiated chat between two users since one user must initiate the chat with ‘/whisper, ‘/w’ or even by clicking on another username in chat. Another example includes a phone messaging app where users can initiate direct conversations with other users.

DefaultTextChannels like General or Team channels are not considered direct chat.

Implementing the APIs

You need to use one of the below APIs for any use case for user A to send or receive direct chat messages with any other user (say user B) on the same server. These are the third and fourth use cases in the table above.

TextChatService:CanUserDirectChatAsync API

The TextChatService:CanUserDirectChatAsync API checks whether a user has permission to chat directly with other users in-experiences. You need to use this API if you are in the 3rd use case (forked legacy chat or custom chat that doesn’t use legacy chat system or TextChatService).

We will retroactively update the legacy chat system scripts to use this API for whisper chat.

local directChat = TextChatService:CanUsersDirectChatAsync(userA, {userB})

-- check if we have any eligible participants

if #directChat > 0 then
 local directChannel = Instance.new("TextChannel")
 for _, participant in party do
   directChannel:AddUserAsync(participant)
 end

  return directChannel
end

warn("Could not create Direct TextChannel. Not enough eligible users")

return nil

TextChannel:SetDirectChatRequester API

TextChannel:SetDirectChatRequester sets TextChannel.DirectChannelRequester with the user who is initiating the direct chat. Any subsequent calls to TextChannel:AddUserAsync will check if the new user is allowed to direct chat with the requester. A similar check is performed before chats are delivered to participants. You need to use this API if you are in the 4th use case (creating custom direct chats in TextChatService that do not use the default or whisper channels).

local newTextChannel = Instance.new("TextChannel")

newTextChannel:SetDirectChatRequester(userA)

newTextChannel:AddUserAsync(userA.UserId)
newTextChannel:AdduserAsync(userB.UserId)

We’ve also released Experience Communication Guidelines to provide creators with best practices on how to offer in-experience chat.

We recognize this is a significant change. We appreciate your help to make chat on our platform safer. Please let us know if you have any questions.

Resources

FAQs

Do I need to implement any new APIs if I’m using the TextChatService and haven’t created any custom TextChannels?

  • No, you do not have to take any action. The built-in direct chat (aka whisper) functionality for TextChatService supports the new user and parental control settings.

What happens if I do not adopt one of the APIs by January 30, 2025?

  • If your experience falls into one of the categories above that requires adoption of either TextChatService:CanUserDirectChatAsync API or TextChannel:SetDirectChatRequester API and you do not do so by January 30th, in-experience chat may be disabled within your experience since it violates our Roblox Community Standards. Refer to the Experience Communication Guidelines to understand best practices for implementing TextChatService.

If I implement this API will I still have to migrate to TextChatService by April 30, 2025?

  • Yes. We’re providing this API and a migration timeline to provide an interim solution for creators needing more time to migrate to TextChatService.

How do I know if I am using the standard version or forked version of legacy chat?

  • We will send an email and inbox message to all affected creators. Additionally, you can verify if you are using the standard unforked version by looking at your explorer and confirming that there aren’t any copies of ChatScript or ChatServiceRunner in Chat, StarterPlayerScripts, or ServerScriptService.

    Additionally, check that the LoadDefaultChat toggle is set to “true,” as seen in the screenshot below.

71 Likes

This topic was automatically opened after 11 minutes.

I’m confused as to what impact this has for me as a developer. The table is helpful to distinguish different requirements, but I’m confused what category my game’s chat would fall in (presuming it will use TextChatService).

If I make a TextChannel for system messages because I want to use a new TextChannel object, do I fall in the table’s category 1 or 4? And if I switch these system message channels to the auto-generated defaults, does that mean I don’t need TextChannel:SetDirectChatRequestor API?

12 Likes

Please add an offset to change the text chat service default window relative to the corner that is chosen

9 Likes

Good question – we will elaborate on this point in the creator hub documentation shortly, but TLDR is:

If youre using TextChannels, you’ll need to ask a primary question when creating a TextChannel:

  • Am I creating this TextChannel because its user initiated?
    • If there’s an obvious Player to assign as the “requester player” via TextChannel:SetDirectChatRequester, then the answer is probably yes.

If you’re making a TextChannel that somewhat acts like a private chat between one or more uses like a whisper chat, all you’ll wanna do is mark who requested that channel to be created. TextChannels will handle the rest of the privacy stuff based on this clue:

local myCoolWhisperChannel = Instance.new("TextChannel")
myCoolWhisperChannel:SetDirectChatRequester(SomeInGamePlayer)

(Notably sometimes there are gameplay-driven channels that don’t include everyone in the server like Team chat that does NOT have an obvious requester and thus does not need to be marked as such)


TextChatService:CanUsersDirectChatAsync is somewhat of a manual version of the above API and is mostly here to support legacy chat for the few months between Jan and April.

Like TextChatService:CanUserChatAsync, there are some extended UX and DX use cases for TextChatService:CanUsersDirectChatAsync after TextChannels are the way to send chat messages so we’ve decided to support both APIs going forward.

For example, if you have created an in-universe phone app that lets you send private 1:1 messages between players in your game, you may want to adjust the UI or hide specific “phone numbers” based on the results of TextChatService:CanUserChatAsync or TextChatService:CanUsersDirectChatAsync without having to make a TextChannel for each possible conversation to check


If you’re making an experience and either

  • not creating TextChannels yourself (the first “who needs to take action” cohort)
  • creating non-default TextChannels, but theyre all “public” and not user-initiated

then you may not need to worry about these APIs. My expectation is that most experiences may not need to be too concerned about the Direct Chat privacy setting unless they are a more “social” driven experience or have some advanced social features that look and feel like the default /whisper chat

(Default whisper channels already use these APIs as expected so no need to take action if that’s enabled for your experience)

11 Likes

Is Roblox automatically changing over all experiences from Legacy Chats to TextChatService Based Chats? I have hundreds of experiences that are affected by this, this is extremely painful to bare no knowledge on whether or not I have to update games I made 10 years ago.

It would be extremely helpful to know if Roblox is rolling over the default chat like they did with 2008, 2014, and 2015-Presents chat’s.

8 Likes

We plan to have another update detailing how we intend to do this, but I can say that if are not able to update experiences in time, they will not be subject to moderation action on your account.

In most cases we anticipate we can safely disable the text filtering for your old legacy or lua-based chats and we may potentially have ways to hide legacy chat and show default TextChatService while the old legacy lua chat continues to run in the background to prevent breaking anything that relies on specifics of the old system.

11 Likes

I’m restating the question from the previous post because I didn’t receive an answer, and I think it could be useful:

Could you enable us to test the CanUserChatAsync and CanUserDirectChatAsync settings in the player emulator? Currently, I’m not entirely sure if I’ve set up the restrictions correctly.

Emulating the restriction would let me test out if TextFilterResult’s GetChatForUserAsync automatically restricts messages for players who aren’t allowed to chat by throwing an error. This is useful because I have a custom chat system, and it would allow me to not check for CanUserChatAsync/CanUserDirectChatAsync in places where GetChatForUserAsync is used

11 Likes

Thats a great idea and suggestion. While we didnt have any initial plans to do this, it might be interesting to see how easy this would be to add. This is not a commitment, but I will write this idea down for consideration.

14 Likes

Thank you for the detailed reply! That sounds reasonable - I presume that system messages are exempt because they’re not user-initiated.

Would it be possible to make TextChannels require using :SetDirectChatRequester(), and allow nil to represent the server as the requester (for cases like system messages)? This would:

  • prevent people from missing adding this function to their code if it’s actually needed.
  • remove ambiguity about the system, because the code handles more of the details.
  • prevent a whole lot of moderation cases based on a programming mistake (that doesn’t throw any warning or errors).
5 Likes

My game uses legacy chat but heavily modified both the chat bubbles and the chat box window to my personal preference. (including making the distant chat bubble UI have randomized texts, making certain error messages not show up and etc)

The heavy modifications are done on purpose for the style the game is going for, since I am not fond of some parts that roblox’s new chat has, which I could try to make similar modifications to what I’ve done for my game’s legacy chat however it seems I could only customize the UI of it. Which means I cannot make the new chat have a modified distant chat bubble, nor prevent certain error messages showing up on the chat box window.

So what I’m getting here is that even if I implement the API into my heavily modified legacy chat, I still have to migrate to TextChatService anyway?

I’d like to point out that a game like Deepwoken also does use legacy chat judging by the old chat bubbles, and I’m sure there are a good amount of games that use either custom chat or legacy chat. It is all by preference or part of how the game is supposed to be styled.

By the way my modified legacy chat does this:
image

14 Likes

This is such a power-playing guideline and just makes implementing custom chat solutions more painful. Why can’t we just translate and filter text on the server for each player? Why do we have to link who the chatting users are, and who started it?

The answer is Roblox wants to be able to listen in on everything said in our games. They can’t determine who is saying what if you bypass their chat system and send it all through remotes.

Which begs the question–why would they need to track that? Moderation is already taken care of with text filtering, so they must have some other ulterior motives.

12 Likes

Legal reasons. If your experience has a bad actor saying bad things, then even if it’s moderated, Roblox would still be liable for your custom chat API not letting them see the bad actor talking.

11 Likes

We require the following two features to be added in order to move our game over to TextChatService by the deadline:

Please add both (they are incredibly easy fixes that will take maybe an hour), otherwise we will be unable to switch

13 Likes

Honestly this is mostly confusing for me and I might just wait to see if I’m effected. I think this just effects direct messaging with other users?? But I don’t even know if I’m using legacy or the new chat? And why would it matter without any form of direct messaging besides just bubble chat?

Slightly confused, oh well!
My game uses a slightly custom chat system just to display the messages, but everything else is built in, so I guess I just hope I’m not effected? ???

5 Likes

I’m a little confused by these new rules, I currently have a game that has custom chat only for “admins” of the experience that works across different places. Right now the custom chat goes through the FilterStringForBroadCast, and then goes through MessagingService to be replicated to other places. If i update my custom chat to use TextChannels, can I still send the messages to other places through MessagingService?

2 Likes

People are confused about Fork Chats requirements, is this meant to be the following?

  1. Either:
    a. Forked version of the legacy chat system

b. Custom chat that does not use legacy chat system or TextChatService as its backend|By January 30, 2025
Integrate TextChatService: CanUserDirectChatAsync API and check that Whisper and direct chats are gated by this method;

OR

By April 30, 2025
Migrate to TextChatService

If not the case, are we actually required to fully use TextChatService on April 30, 2025?

3 Likes

i don’t understand why Chage something when its ok i use Roblox chat in my games i don’t use voice

3 Likes

A reminder that not all developers can even migrate over to this because cross-server communication, in-transit message editing and message history just don’t exist as features. This effectively kills off social-deduction games as many become easier to exploit. Cross-server messaging systems also just outright became a no-go. Please do re-consider this change in favour of a different API structure that doesn’t shoot down these use-cases. :pray:


Why wasn’t CanUsersChatAsync considered for this, it seems to have the exact same documented purpose? Is CanUsersChatAsync used for a different purpose?

10 Likes

is there a way Xbox can use chat to say hello on Roblox?

4 Likes