> For the complete documentation index, see [llms.txt](https://docs.ggwp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ggwp.com/ggwp-client-sdk/chat-complete-integration-example.md).

# Chat: Complete Integration Example

Here's a complete example showing typical Unity SDK usage with Dynamic Token authentication, custom replacement strategy, sanctions monitoring, and re-authentication handling:

{% code fullWidth="true" %}

```csharp
using UnityEngine;
using System.Threading.Tasks;
using GGWP.Chat;
using GGWP.Sanctions;
using GGWP.Utils.Async;

public class GGWPIntegration : MonoBehaviour
{
    private Subscriber<ChannelSanctionsState> sanctionsSubscriber;
    private Subscriber<SanitizationResponse> sanitizationSubscriber;
    private Subscriber<GGWP.Impl.AuthStatus> authSubscriber;

    async void Start()
    {
        await InitializeSDK();
        // Authenticate before subscribing to sanctions for immediate WebSocket connection
        await AuthenticateUser();
        ConfigureReplacementStrategy();
        MonitorAuthentication();
        // Subscribe to sanctions after authentication to get immediate real-time updates
        MonitorSanctions();
        MonitorSanitization();
    }

    async Task InitializeSDK()
    {
        if (GGWPSDK.Instance == null)
        {
            Debug.LogError("GGWPSDK not available");
            return;
        }

        // Initialize with customer ID and optional username
        GGWPSDK.Instance.InitializeSDK("your_customer_id", "player_username");
        Debug.Log("SDK initialized");
    }

    async Task AuthenticateUser()
    {
        // Use OAuth code exchange authentication (recommended)
        // This also establishes the WebSocket connection for sanctions updates
        string authCode = GetAuthCodeFromBackend();
        
        try
        {
            var result = await GGWPSDK.Instance?.AuthManager.ExchangeAuthCode(authCode);

            if (result == GGWP.Impl.Result.Success)
            {
                Debug.Log("OAuth authentication successful");
            }
        }
        catch (Exception ex)
        {
            Debug.LogError($"Authentication failed: {ex.Message}");
        }
    }

    void ConfigureReplacementStrategy()
    {
        // Optional: Configure which message version to use
        // If not set, service defaults with UseFiltered strategy will be used
        GGWPSDK.Instance?.ChatAPI.SetSanitizationConfig(new SanitizationConfigUpdate
        {
            client = new GGWP.Chat.Impl.SanitizationClientConfig
            {
                // Let the AI choose the best replacement strategy for each message
                messageReplacementConfig = ReplacementStrategy.UseRecommended
            },
            service = null  // Use service defaults for filtering settings
        });
    }

    async void MonitorAuthentication()
    {
        authSubscriber = new Subscriber<GGWP.Impl.AuthStatus>(
            GGWPSDK.Instance?.AuthManager.SubscribeAuthUpdates()
        );

        await foreach (var status in authSubscriber.GetStream())
        {
            switch (status.status)
            {
                case GGWP.Impl.AuthStatusName.CodeExchangeSession:
                    Debug.Log("OAuth session active - refreshes handled automatically");
                    break;
                    
                case GGWP.Impl.AuthStatusName.NoAuth:
                    // Very rare case: session failed to refresh multiple times in a row
                    Debug.LogWarning("Authentication session lost - re-authentication required");
                    
                    if (status.error.ToNullable() != null)
                    {
                        Debug.LogError($"Auth error: {status.error.ToNullable()}");
                    }
                    
                    // Perform another code exchange to restore the session
                    await ReauthenticateUser();
                    break;
            }
        }
    }

    private async Task ReauthenticateUser()
    {
        try
        {
            Debug.Log("Attempting to re-authenticate user...");
            
            // Get a new auth code from your backend
            string newAuthCode = GetAuthCodeFromBackend();
            
            // Exchange the new code for a fresh session
            var result = await GGWPSDK.Instance?.AuthManager.ExchangeAuthCode(newAuthCode);
            
            if (result == GGWP.Impl.Result.Success)
            {
                Debug.Log("Re-authentication successful");
            }
            else
            {
                Debug.LogError("Re-authentication failed");
                ShowLoginScreen();
            }
        }
        catch (Exception ex)
        {
            Debug.LogError($"Re-authentication error: {ex.Message}");
            ShowLoginScreen();
        }
    }

    async void MonitorSanctions()
    {
        // Subscribe to sanctions after authentication to ensure WebSocket is connected
        sanctionsSubscriber = new Subscriber<ChannelSanctionsState>(
            GGWPSDK.Instance?.SanctionsAPI.SubscribeSanctionsState()
        );

        await foreach (var state in sanctionsSubscriber.GetStream())
        {
            // Check if user is muted in chat and update UI accordingly
            if (state.chat.status == GGWP.Sanctions.Impl.MuteStatus.Muted)
            {
                Debug.Log("User is muted in chat");
                DisableChatInput();
                
                // Optionally show when the mute expires
                if (state.chat.expiryAt != null)
                {
                    ShowMuteExpiryNotification(state.chat.expiryAt.Value);
                }
            }
            else
            {
                EnableChatInput();
            }
        }
    }

    async void MonitorSanitization()
    {
        // Subscribe to all sanitization events for logging or analytics
        sanitizationSubscriber = new Subscriber<SanitizationResponse>(
            GGWPSDK.Instance?.ChatAPI.SubscribeSanitizedMessages()
        );

        await foreach (var sanitized in sanitizationSubscriber.GetStream())
        {
            LogMessageSanitization(sanitized);
        }
    }

    public async Task<bool> SendChatMessage(string message)
    {
        // ReplaceMessage uses the configured replacement strategy (UseRecommended in this case)
        var replaced = await GGWPSDK.Instance?.ChatAPI.ReplaceMessage(
            new ChatMessage { message = message }
        );

        if (replaced == null)
        {
            Debug.Log("Message blocked - user may be sanctioned");
            ShowMessageBlockedNotification();
            return false;
        }

        // The message returned depends on your configured ReplacementStrategy
        // UseFiltered: asterisks replace bad words
        // UseReplaced: alternative words replace bad words
        // UseRecommended: AI chooses best version based on context
        // UseOriginal: original message unchanged
        SendToChat(replaced.messageDetails.replacedMessage);
        return true;
    }

    private string GetAuthCodeFromBackend() 
    { 
        /* Your implementation - call your backend to get an auth code from GGWP services */ 
        return ""; 
    }
    
    private void DisableChatInput() 
    { 
        /* Your implementation - disable the chat input UI */ 
    }
    
    private void EnableChatInput() 
    { 
        /* Your implementation - enable the chat input UI */ 
    }
    
    private void LogMessageSanitization(SanitizationResponse response) 
    { 
        /* Your implementation - log sanitization events for analytics */ 
    }
    
    private void SendToChat(string message) 
    { 
        /* Your implementation - send the message to your chat system */ 
    }
    
    private void ShowLoginScreen() 
    { 
        /* Your implementation - display login screen to user */ 
    }
    
    private void ShowMuteExpiryNotification(DateTime expiryAt) 
    { 
        /* Your implementation - show when the mute will expire */ 
    }
    
    private void ShowMessageBlockedNotification() 
    { 
        /* Your implementation - inform user their message was blocked */ 
    }

    void OnDestroy()
    {
        // Clean up all subscribers to prevent memory leaks
        authSubscriber?.Dispose();
        sanctionsSubscriber?.Dispose();
        sanitizationSubscriber?.Dispose();
    }
}

```

{% endcode %}

}
