Discord RPC C#

repository·master·Indexed 20 days ago

https://github.com/lachee/discord-rpc-csharp

A managed C# implementation of the Discord RPC protocol for .NET developers to integrate Rich Presence (status updates, join requests, etc.) into applications. Supports .NET Framework 4.5, .NET Core 3.1, and .NET 7.0, 8.0, and 9.0. Features include support for static and dynamic assets, avatar and decoration retrieval, clickable buttons, party management, and URI scheme registration for game launching.

Tokens
7K
Snippets
26
Records
33
Agent score
71%

What's inside discord-rpc-csharp

  1. Use different Discord Activity Types

    master

    Discord allows you to specify different activity types to change how your application is presented to other users (e.g., "Playing", "Listening", "Watching", or "Competing").

    Note that time representation in the Discord client is controlled via @timestamps, and different activity types may render time differently.

    | Activity Type | Example |
    |---------------|---------|
    | Playing   | (Playing mode) |
    | Listening | (Listening mode) |
    | Watching  | (Watching mode) |
    | Competing | (Competing mode) |
  2. How to use DiscordRichPresence

    master

    The library operates in three distinct phases that must be followed in order:

    1. Initialization: Create and initialize the client.
    2. Rich Presence Setting: Update the presence state.
    3. Deinitialization and Disposal: Clean up resources.

    Important Lifecycle Rule: The DiscordRpcClient should be treated as a singleton. You should only ever create one instance in the lifetime of your application. Creating multiple instances can cause conflicts and unpredictable behavior in Discord.

  3. Handle animated avatars

    master

    If a user's avatar is animated (indicated by a hash starting with a_), you should request a GIF or WebP format to see the animation. For static avatars, use PNG.

    string url;
    if (client.CurrentUser.IsAvatarAnimated) 
    {
        // Use GIF or WebP for animations
        url = client.CurrentUser.GetAvatarURL(User.AvatarFormat.GIF, User.AvatarSize.x64);
    } 
    else 
    {
        url = client.CurrentUser.GetAvatarURL(User.AvatarFormat.PNG, User.AvatarSize.x64);
    }
  4. Create and manage Discord Parties

    master

    A Party allows Discord to group users together for a specific game and display party size. To create a party, include a Party object within your SetPresence call.

    Key properties:

    • ID: A unique string for your application. When two users share the same ID, Discord groups them together.
    • Privacy: Set to Party.PrivacySetting.Private to change the 'Join' button to 'Ask to Join'.
    • Size: The current number of users in the party.
    • Max: The maximum number of users allowed in the party.

    You can dynamically update the party size using DiscordRpcClient.UpdatePartySize(int) as players join or leave.

    client.SetPresence(new()
    {
        Details = "Party Example",
        State = "In Game",
        Party = new()
        {
            ID = "my-unique-party-id",
            Privacy = Party.PrivacySetting.Private,
            Size = 1,
            Max = 4,
        },
    });
  5. Display timers and progress in Discord activities

    master

    You can use the Timestamps class to display timers or progress bars in your Discord Rich Presence. The visual representation (e.g., a countdown vs. an elapsed time) depends on the ActivityType you choose and which Timestamps method you call.

    Note that Discord's display behavior varies by activity type. For example, while you can set timestamps for Playing activities, Discord may not display them as countdowns as they once did. Timestamps are most effective for Listening and Watching activities to show progress or elapsed time.

    client.SetPresence(new RichPresence()
    {
        Type = ActivityType.Watching,
        StatusDisplay = StatusDisplayType.Details,
        Details = "Skibidi Toilet - Season 1",
        State = "DaFuq!?Boom!",
        Timestamps = Timestamps.FromTimeSpan(TimeSpan.FromSeconds(66)),
    });
  6. Register URI Schemes for game launching

    master

    To enable the 'Join' button in Discord, your application must register a URI scheme. This allows Discord to launch your game when a user clicks a join invite.

    Steam Games: You can use the steam:// scheme by providing your Steam App ID to RegisterUriScheme.

    Non-Steam Games: Use RegisterUriScheme() without arguments to register a default scheme, or provide a custom string.

    MacOS Note: On MacOS, non-steam games require schemes to be registered via App Bundles. This library cannot automatically register non-steam schemes on MacOS; you must provide a Steam App ID or a custom URI scheme to RegisterUriScheme.

    // For standard/custom schemes
    client.RegisterUriScheme();
    client.Initialize();
    
    // For Steam games
    client.RegisterUriScheme("657300");
    client.Initialize();
  7. Add clickable buttons to your Discord presence

    master

    You can display clickable links within your Discord presence using the Buttons property of the RichPresence object. Each button consists of a Label (the text displayed on the button) and a Url (the destination link).

    Constraints and Behavior:

    • Limit: You can display a maximum of 2 buttons at once.
    • Visibility: Buttons are not visible to you (the owner of the activity). They are only visible to and clickable by other users viewing your profile.
    client.SetPresence(new RichPresence()
    {
        Details = "A Basic Example",
        State = "In Game",
        Buttons = new Button[]
        {
            new Button() { Label = "Fish", Url = "https://lachee.dev/" },
            new Button() { Label = "Sticks", Url = "https://en.wikipedia.org/wiki/Stick" }
        }
    });
  8. Use the Example App for testing and debugging

    master

    For debugging and testing the discord-rpc-csharp library, you can use the sample application Rich Presence for .NET (App ID: 424087019149328395).

    This application provides a set of example assets located in the Resources/Discord App Images/ folder. When testing image updates in your own implementation, you can use the filenames of these assets as the image_key in your RPC calls.

    App ID: 424087019149328395
  9. Implement the Discord Join flow with Secrets

    master

    The 'Join' flow allows users to enter a lobby via a button in Discord. For this to work, the host must have a Party, a Secret, and a registered URI Scheme set in their presence.

    1. Host Side: Set a Secret in the SetPresence call. This secret (e.g., a JWT or a token) tells the joining client how to connect to the lobby.
    2. Client Side: Subscribe to EventType.Join and handle the OnJoin event to receive the secret.

    Note: The library does not automatically subscribe to events. You must explicitly call client.Subscribe(EventType.Join).

    // Host setting the secret
    client.SetPresence(new()
    {
        Details = "Party Example",
        State = "In Game",
        Party = new() { /* .. Party Details .. */ },
        Secrets = new()
        {
            Join = Lobby.CreateJoinToken(Lobby.current.ID)
        },
    });
    
    // Joining client handling the event
    client.Subscribe(EventType.Join);
    client.OnJoin += (object sender, JoinMessage args) =>  {
        Lobby.JoinWithToken(args.Secret);
    };
  10. Use Static Assets for Rich Presence

    master

    You can display small and large images in your Discord Rich Presence using assets uploaded directly to your Discord Application. This is the preferred method as it is reliable and does not require an external web server.

    To use static assets:

    1. Upload your images to the Discord Developer Portal under AppRich PresenceArt Assets.
    2. Assign a key to each image.
    3. Reference these keys in the Assets property of your RichPresence object using LargeImageKey and SmallImageKey.

    You can also provide LargeImageText or SmallImageText to create tooltips that appear when a user hovers over the icons.

    client.SetPresence(new RichPresence()
    {
        Type = ActivityType.Playing,
        Details = "A Basic Example",
        State = "In Game",
        Assets = new Assets()
        {
            LargeImageKey = "image_large",
            LargeImageText = "Lachee's Discord IPC Library",
            SmallImageKey = "koala"
        },
    });
  11. Access user information via the OnReady event

    master

    User information (including avatars) is not immediately available when the RPC client connects. You must wait for the OnReady event to be emitted by the client. The DiscordRpcClient.CurrentUser property is only valid after this event has invoked.

    Important: Events are executed on a separate thread. If you are using a game engine (like Unity), you must use DiscordRpcClient.Invoke on your main thread or implement your own cross-thread data transfer mechanism to avoid threading issues.

    client.OnReady += (sender, msg) =>
    {
        // msg.User contains the current user information
        Console.WriteLine("Connected to discord with user {0}", msg.User.Username);
    };
  12. Enable Discord RPC for WIN UI 3, .NET MAUI, or WinUI 3 applications

    master

    To use this library with WIN UI 3 related applications (such as .NET MAUI), you must ensure the runFullTrust capability is defined in your Package.appxmanifest.

    Note: If you are using the standard C# templates for .NET MAUI or WIN UI 3, this capability is often added automatically. However, if the library fails to function, verify its presence in your manifest.

    <?xml version="1.0" encoding="utf-8"?>
    
    <Package
      xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
      xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
      xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
      IgnorableNamespaces="uap rescap">
      ...
        <Capabilities>
    	    <rescap:Capability Name="runFullTrust" />
        </Capabilities>
    </Package>