Skip to content

Commit 463d80c

Browse files
authored
Social SDK: Integrating Moderation Guide (#7573)
* Social SDK: Integrating Moderation Guide A guide for integrating moderation tools and managing content moderation when using the Discord Social SDK. Review note: Running link decoration also updated the unreal guide. * Review updates
1 parent 2e52d43 commit 463d80c

File tree

6 files changed

+335
-1
lines changed

6 files changed

+335
-1
lines changed

docs/discord-social-sdk/development-guides.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ subpages:
1313
- development-guides/managing-lobbies.mdx
1414
- development-guides/linked-channels.mdx
1515
- development-guides/joining-voice-chat.mdx
16+
- development-guides/integrating-moderation.mdx
1617
- development-guides/debugging-logging.mdx
1718
- development-guides/using-with-discord-apis.mdx
1819
---
@@ -75,6 +76,10 @@ If you are new to the Discord Social SDK, we recommend you start with the [Getti
7576
<Card title="Debugging & Logging" link="/docs/discord-social-sdk/development-guides/debugging-logging" icon="BugIcon">
7677
Use logging and debugging tools to troubleshoot issues.
7778
</Card>
79+
<Card title="Integrating Moderation" link="/docs/discord-social-sdk/development-guides/integrating-moderation"
80+
icon="ShieldIcon">
81+
Integrating and managing content moderation for your game when using the Discord Social SDK.
82+
</Card>
7883
<Card title="Using with Discord APIs" link="/docs/discord-social-sdk/development-guides/using-with-discord-apis" icon="ClydeIcon">
7984
Make requests to Discord's HTTP APIs from your game.
8085
</Card>
Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
---
2+
sidebar_label: Integrating Moderation
3+
---
4+
import PublicClient from '../partials/callouts/public-client.mdx';
5+
import SupportCallout from '../partials/callouts/support.mdx';
6+
7+
[Home](/docs/intro) > [Discord Social SDK](/docs/discord-social-sdk/overview) > [Development Guides](/docs/discord-social-sdk/development-guides) > {sidebar_label}
8+
9+
# Moderation with the Discord Social SDK
10+
11+
{/*
12+
Script for converting mermaid sequence diagrams to SVG.
13+
14+
# docker run --rm -u `id -u`:`id -g` -v "$(pwd):/data" minlag/mermaid-cli -i "/data/$file" -o "/data/$filename.svg" -t dark -b '#313338'
15+
*/}
16+
17+
This guide will walk you through integrating and managing content moderation for your game when using the Discord Social SDK.
18+
19+
## Overview
20+
21+
Effective moderation is essential for creating healthy social experiences. This guide will help you:
22+
23+
- Better understand your moderation responsibilities
24+
- Implement client-side moderation for text and audio content alongside the Discord Social SDK
25+
26+
## Prerequisites
27+
28+
Before you begin, make sure you have:
29+
30+
- A basic understanding of how the SDK works from the [Getting Started Guide](/docs/discord-social-sdk/getting-started)
31+
- A basic understanding of your game's communication features
32+
- Familiarity with [provisional accounts](/docs/discord-social-sdk/development-guides/using-provisional-accounts)
33+
- Reviewed the [Discord Social SDK Terms](https://support-dev.discord.com/hc/en-us/articles/30225844245271-Discord-Social-SDK-Terms)
34+
35+
## Your Moderation Responsibilities
36+
37+
### Moderation on Discord
38+
39+
[Discord's Community Guidelines](https://discord.com/guidelines) and [Terms of Service](https://discord.com/terms) apply to any content that is rendered on Discord, including:
40+
41+
- Text messages, audio, and video sent within Discord’s platform
42+
- Text messages that are appear on Discord (such as in DMs or Linked Channels) after being sent by players in your game (whether they have linked their Discord account or are using a provisional account)
43+
44+
Discord can take various actions against such content on Discord for violating its terms or policies, including through Discord platform-wide account bans and restrictions. Actions against a player’s Discord account will not affect their separate account in the game (see [below](https://www.notion.so/Text-and-Voice-Moderation-1d0f46fd48aa80eda914cd3134d65afb?pvs=21) for more details); however, if a player’s Discord account is banned, they will no longer have access to the SDK features that require an account connection.
45+
46+
### Game Developer's Responsibility
47+
48+
Your terms and policies apply to the content in your game. You are responsible for:
49+
50+
- Ensuring you comply with the [Discord Social SDK Terms](https://support-dev.discord.com/hc/en-us/articles/30225844245271-Discord-Social-SDK-Terms)
51+
- Creating game-specific content policies and enforcing them
52+
- In-game content moderation for messages or audio within your game
53+
- Implementing appropriate UIs for reporting and moderation; this includes providing players a way to report issues or violations of your policies and reviewing and taking appropriate action on such reports
54+
55+
## Client-Side Chat Moderation
56+
57+
While the Social SDK does not have a direct integration with external moderation toolkits, a client side approach to
58+
outgoing and incoming messages can be implemented when sending messages through [`Client::SendUserMessage`] and/or
59+
receiving them through [`Client::SetMessageCreatedCallback`].
60+
61+
### How it works:
62+
63+
An example moderation integration would be the following:
64+
65+
**Message Sending**
66+
67+
- Before a user sends a message, your client validates it with your backend
68+
- If it passes validation, the message is sent through the SDK
69+
- Messages can be optimistically rendered while validation occurs
70+
71+
{/*
72+
```
73+
sequenceDiagram
74+
participant User
75+
participant GameClient
76+
participant BackendService as Moderation Backend
77+
participant DiscordSDK as Discord Social SDK
78+
participant DiscordServers as Discord
79+
80+
%% User initiates sending a message %%
81+
User->>GameClient: Enters and submits message text
82+
activate GameClient
83+
84+
%% Optimistic rendering and validation request %%
85+
Note right of GameClient: Optimistically render message in UI
86+
GameClient->>BackendService: POST /validate (message)
87+
activate BackendService
88+
89+
%% Backend validates %%
90+
Note right of BackendService: Perform validation logic
91+
BackendService-->>GameClient: Response (isValid: boolean, moderatedText?: string)
92+
deactivate BackendService
93+
94+
%% Conditional sending based on validation %%
95+
alt Message is Valid (isValid: true)
96+
GameClient->>DiscordSDK: Client::SendUserMessage(recipient, message)
97+
activate DiscordSDK
98+
DiscordSDK->>DiscordServers: Forward message
99+
activate DiscordServers
100+
DiscordServers-->>DiscordSDK: Message Acknowledged (messageId)
101+
deactivate DiscordServers
102+
DiscordSDK-->>GameClient: Callback(result: Success, messageId)
103+
deactivate DiscordSDK
104+
Note right of GameClient: Confirm message sent (update UI if needed)
105+
else Message is Invalid (isValid: false)
106+
Note right of GameClient: Remove optimistically rendered message from UI
107+
GameClient->>User: Notify: "Message violated content policy"
108+
end
109+
deactivate GameClient
110+
```
111+
*/}
112+
![Message sending sequence diagram](images/social-sdk/integrating-moderation/message-sending.svg)
113+
114+
```cpp
115+
// Example: Validating a message before sending
116+
void validateAndSendMessage(const std::string& message) {
117+
// Optimistically render the message immediately
118+
renderMessage(myUserId, message);
119+
120+
// Send to backend for validation
121+
myBackend->validateMessage(message, [this, message](bool isValid, std::string moderated) {
122+
if (isValid) {
123+
// Send through Discord SDK
124+
client->SendUserMessage(recipientId, message, [](auto result, uint64_t messageId) {
125+
if (result.Successful()) {
126+
std::cout << "✅ Message sent successfully\n";
127+
} else {
128+
std::cout << "❌ Failed to send message: " << result.GetError() << "\n";
129+
}
130+
});
131+
} else {
132+
// Remove the invalid message from UI and notify user
133+
removeMessage(myUserId, message);
134+
notifyUser("Message violated content policy");
135+
}
136+
});
137+
}
138+
```
139+
140+
**Message Receiving**
141+
142+
- When a message is received from players within Discord or a Game Client, your client sends it to your backend for validation
143+
- Once validation succeeds, render the message in the game
144+
145+
:::info
146+
Depending on how long your content moderation processing takes, you may wish to optimistically render the incoming
147+
message, and remove or alter it if your moderation service deems it appropriate. However, this does pose the risk of
148+
temporarily exposing content to your game players that does not align with your moderation policies.
149+
:::
150+
151+
152+
{/*
153+
```
154+
sequenceDiagram
155+
participant DiscordSDK as Discord Social SDK
156+
participant GameClient as Game Client
157+
participant BackendService as Moderation Backend
158+
159+
%% Message Arrives %%
160+
activate DiscordSDK
161+
162+
%% SDK delivers message to Game Client via callback %%
163+
Note right of DiscordSDK: Message arrives for subscribed channel/user
164+
DiscordSDK->>GameClient: Trigger Client::SetMessageCreatedCallback(message)
165+
deactivate DiscordSDK
166+
activate GameClient
167+
168+
%% Game Client sends received message for validation %%
169+
GameClient->>BackendService: POST /validate (receivedMessage)
170+
activate BackendService
171+
172+
%% Backend validates %%
173+
Note right of BackendService: Perform validation logic
174+
BackendService-->>GameClient: Response (isValid: boolean)
175+
deactivate BackendService
176+
177+
%% Conditional rendering based on validation %%
178+
alt Message is Valid (isValid: true)
179+
Note right of GameClient: Render received message in game UI
180+
else Message is Invalid (isValid: false)
181+
Note right of GameClient: Discard message (do not render)
182+
end
183+
deactivate GameClient
184+
```
185+
*/}
186+
![Message receiving sequence diagram](images/social-sdk/integrating-moderation/message-receiving.svg)
187+
188+
:::info
189+
You may wish to implement moderation caching on your backend to avoid redundant validation. This is especially true for
190+
lobby messages, which are sent to multiple recipients.
191+
:::
192+
193+
As a reminder, you are responsible for any third-party moderation toolkits or services you use for your game and will ensure you comply with any applicable terms and laws, including obtaining consents from players as necessary for processing their data using such moderation services.
194+
195+
## Handling Users with Banned Discord Accounts
196+
197+
### Discord Platform Bans
198+
199+
:::info
200+
If a player has connected their Discord account with your game, and it is banned, their [`Client`] will be
201+
immediately disconnected, and that user will no longer be able to authenticate through Discord.
202+
:::
203+
204+
The recommended path for integrating the Discord Social SDK is that your game has a primary authentication other than Discord that initially sets up a provisional account, and have the player link their Discord account to this primary authentication.
205+
206+
This approach protects your users' game access and data if they encounter issues with their Discord account, such as a permanent or temporary ban. To implement this recommended path:
207+
208+
1. Create an account through a [non-Discord authentication provider](/docs/discord-social-sdk/development-guides/using-provisional-accounts#configuring-your-identity-provider), and create a provisional account attached to it.
209+
2. When users later authenticate through Discord to link their account, have your game back end execute the [merge their provisional account with their Discord Account](/docs/discord-social-sdk/development-guides/using-provisional-accounts#merging-provisional-accounts).
210+
3. The account merging process will internally store the `externalAuthToken` from the provisional account against their Discord account. If a ban of the Discord account happens, that `externalAuthToken` will be attached to the new provisional account that is created in its stead, with the original Discord account's in-game friends, and will be available through the authentication provider the account was initially setup with.
211+
4. As a last step, your game back end should maintain the record of the `externalAuthToken` against the user account, even after the account merging process, since it will be needed to [authenticate via a provisional account](/docs/discord-social-sdk/development-guides/using-provisional-accounts#implementing-provisional-accounts) should Discord authentication fails for a ban, or any other reason.
212+
213+
{/*
214+
```
215+
sequenceDiagram
216+
participant User
217+
participant Game
218+
participant NonDiscordAuth as Non-Discord Auth Provider
219+
participant GameBackend as Game Backend
220+
participant Discord
221+
222+
User->>Game: Start game
223+
Game->>NonDiscordAuth: Create account
224+
NonDiscordAuth-->>Game: Authentication successful
225+
Game->>GameBackend: Request provisional account
226+
GameBackend->>Discord: Create provisional account
227+
Discord-->>GameBackend: Account created
228+
GameBackend-->>Game: Return Provisional Account
229+
Note over GameBackend: Store externalAuthToken
230+
231+
User->>Game: Choose to link Discord account
232+
Game->>Discord: Request authentication
233+
Discord-->>Game: Auth successful
234+
Game->>GameBackend: Request account merge
235+
GameBackend->>Discord: Merge Provisional Account
236+
Note over Discord: Stores externalAuthToken against Discord account
237+
Discord-->>GameBackend: Merge successful
238+
239+
Note over GameBackend: Maintain externalAuthToken record
240+
241+
alt Discord Authentication Fails (Ban or Other Issue)
242+
User->>Game: Attempt to login
243+
Game->>Discord: Request authentication
244+
Discord-->>Game: Auth failed
245+
Game->>NonDiscordAuth: Fallback authentication
246+
NonDiscordAuth-->>Game: Authentication successful
247+
Game->>GameBackend: Access provisional account with externalAuthToken
248+
GameBackend-->>Game: Access granted with in-game friends list
249+
Game-->>User: Access game
250+
end
251+
```
252+
*/}
253+
![Platform bans sequence diagram](images/social-sdk/integrating-moderation/platform-bans.svg)
254+
255+
:::warn
256+
If you use Discord as the primary or sole authentication mechanism for your game, you risk players permanently losing access to their in-game data if their Discord account is banned, as there is no way to migrate them to a provisional account that is connected to an external authentication provider.
257+
:::
258+
259+
:::info
260+
At this time, there is no API to look up if a player's Discord account has been banned.
261+
:::
262+
263+
### Discord Server Bans
264+
265+
If you wish to tie your in-game moderation policies to a specific Discord server that you own, such as your official community server, you are able to retrieve ban information for your Discord Server via our REST APIs.
266+
267+
See the references for the REST endpoints[`{guild.id}/guilds/{guild.id}/bans`](/docs/resources/guild#get-guild-bans)
268+
or [`/guilds/{guild.id}/bans/{user.id}`](/docs/resources/guild#get-guild-ban)
269+
for more information on retrieving all bans for your guild, or ban information for a specific user within your guild.
270+
271+
## Voice Chat Moderation
272+
273+
The Discord Social SDK provides access to audio streams for in-game voice calls, allowing you to implement audio
274+
moderation for your game's voice chat functionality. The data for the call is available through
275+
[`Client::StartCallWithAudioCallbacks`], and can be passed to your voice moderation system.
276+
277+
```cpp
278+
// Example: Capturing local voice chat audio for asynchronous moderation.
279+
280+
// Callback for local users' audio with moderation
281+
auto capturedCallback = [](int16_t const* data,
282+
uint64_t samplesPerChannel, int32_t sampleRate,
283+
uint64_t channels) {
284+
// Call the moderation function
285+
moderateCapturedVoice(data, samplesPerChannel);
286+
};
287+
288+
// Start the call with our moderation callback
289+
auto call = client->StartCallWithAudioCallbacks(lobbyId, receivedCallback, capturedCallback);
290+
```
291+
292+
293+
---
294+
295+
## Next Steps
296+
297+
<Container>
298+
<Card title="Sending Direct Messages" link="/docs/discord-social-sdk/development-guides/sending-direct-messages"
299+
icon="ChatIcon">
300+
Enable private messaging between players.
301+
</Card>
302+
<Card title="Joining Voice Chat" link="/docs/discord-social-sdk/development-guides/joining-voice-chat"
303+
icon="VoiceNormalIcon">
304+
Add in-game voice communication.
305+
</Card>
306+
<Card title="Linked Channels" link="/docs/discord-social-sdk/development-guides/linked-channels"
307+
icon="TextControllerIcon">
308+
Connect game lobbies to Discord text channels.
309+
</Card>
310+
</Container>
311+
312+
<SupportCallout/>
313+
314+
---
315+
316+
## Change Log
317+
318+
| Date | Changes |
319+
|--------------|-----------------|
320+
| May 22, 2025 | initial release |
321+
322+
{/* Autogenerated Reference Links */}
323+
[`Client`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a302dda8b19408696fa186e739c5c24c8
324+
[`Client::SendUserMessage`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a3cf9d2b1b5a4a61dcad995dfc1009703
325+
[`Client::SetMessageCreatedCallback`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a28325a8e8c688a84ac851da4bc86e148
326+
[`Client::StartCallWithAudioCallbacks`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#abcaa891769f9e912bfa0e06ff7221b05

docs/discord-social-sdk/getting-started/using-unreal-engine.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,4 +717,4 @@ You have successfully set up the Discord Social SDK with Unreal Engine and authe
717717
[`Client::Connect`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a873a844c7c4c72e9e693419bb3e290aa
718718
[`Client::GetRelationships`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ad481849835cd570f0e03adafcf90125d
719719
[`Client::UpdateToken`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a606b32cef7796f7fb91c2497bc31afc4
720-
[`RunCallbacks`]: https://discord.com/developers/docs/social-sdk/namespacediscordpp.html#ab5dd8cf274f581ee1885de5816be3c29
720+
[`RunCallbacks`]: https://discord.com/developers/docs/social-sdk/namespacediscordpp.html#ab5dd8cf274f581ee1885de5816be3c29

static/images/social-sdk/integrating-moderation/message-receiving.svg

Lines changed: 1 addition & 0 deletions
Loading

static/images/social-sdk/integrating-moderation/message-sending.svg

Lines changed: 1 addition & 0 deletions
Loading

static/images/social-sdk/integrating-moderation/platform-bans.svg

Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)