From a52326776575d34ed14080e7b7781e607d99680b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?yui=E2=80=8B?= Date: Thu, 19 Sep 2024 11:08:02 +0200 Subject: [PATCH] Add support for setting activity type (#255) * add activity type property * forgot type in clone, add comments to enum * forgot these as well * cleanup duplicate code and add type update function --- DiscordRPC/DiscordRpcClient.cs | 306 +++++++-------------------------- DiscordRPC/RichPresence.cs | 51 +++++- 2 files changed, 112 insertions(+), 245 deletions(-) diff --git a/DiscordRPC/DiscordRpcClient.cs b/DiscordRPC/DiscordRpcClient.cs index 80ac2a5d..1c58df9c 100644 --- a/DiscordRPC/DiscordRpcClient.cs +++ b/DiscordRPC/DiscordRpcClient.cs @@ -333,10 +333,10 @@ private void ProcessMessage(IMessage message) //Resend our presence and subscription SynchronizeState(); } - + if (OnReady != null) OnReady.Invoke(this, message as ReadyMessage); - + break; case MessageType.Close: @@ -366,8 +366,8 @@ private void ProcessMessage(IMessage message) { var sub = message as SubscribeMessage; Subscription |= sub.Event; - } - + } + if (OnSubscribe != null) OnSubscribe.Invoke(this, message as SubscribeMessage); @@ -483,169 +483,86 @@ public void SetPresence(RichPresence presence) #region Updates /// - /// Updates only the of the and updates/removes the buttons. Returns the newly edited Rich Presence. + /// Updates the values assigned in the delegate passed /// - /// The buttons of the Rich Presence + /// Delegate used to update the rich presence /// Updated Rich Presence - public RichPresence UpdateButtons(Button[] button = null) + public RichPresence Update(Action func) { if (!IsInitialized) - { throw new UninitializedException(); - } // Clone the presence RichPresence presence; lock (_sync) { - if (CurrentPresence == null) - { - presence = new RichPresence(); - } - else - { - presence = CurrentPresence.Clone(); - } + presence = CurrentPresence == null ? new RichPresence() : CurrentPresence.Clone(); } - // Update the buttons. - presence.Buttons = button; + func(presence); SetPresence(presence); return presence; } + /// + /// Updates only the of the and sends the updated presence to Discord. Returns the newly edited Rich Presence. + /// + /// The type of the Rich Presence + /// Updated Rich Presence + public RichPresence UpdateType(ActivityType type) => Update(p => p.Type = type); + + /// + /// Updates only the of the and updates/removes the buttons. Returns the newly edited Rich Presence. + /// + /// The buttons of the Rich Presence + /// Updated Rich Presence + public RichPresence UpdateButtons(Button[] buttons = null) => Update(p => p.Buttons = buttons); + /// /// Updates only the of the and updates the button with the given index. Returns the newly edited Rich Presence. /// /// The buttons of the Rich Presence /// The number of the button /// Updated Rich Presence - public RichPresence SetButton(Button button, int index = 0) - { - if (!IsInitialized) - { - throw new UninitializedException(); - } - - // Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) - { - presence = new RichPresence(); - } - else - { - presence = CurrentPresence.Clone(); - } - } - - // Update the buttons - presence.Buttons[index] = button; - SetPresence(presence); - - return presence; - } + public RichPresence SetButton(Button button, int index = 0) => Update(p => p.Buttons[index] = button); /// /// Updates only the of the and sends the updated presence to Discord. Returns the newly edited Rich Presence. /// /// The details of the Rich Presence /// Updated Rich Presence - public RichPresence UpdateDetails(string details) - { - if (!IsInitialized) - throw new UninitializedException(); + public RichPresence UpdateDetails(string details) => Update(p => p.Details = details); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - presence.Details = details; - SetPresence(presence); - return presence; - } /// /// Updates only the of the and sends the updated presence to Discord. Returns the newly edited Rich Presence. /// /// The state of the Rich Presence /// Updated Rich Presence - public RichPresence UpdateState(string state) - { - if (!IsInitialized) - throw new UninitializedException(); + public RichPresence UpdateState(string state) => Update(p => p.State = state); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - presence.State = state; - SetPresence(presence); - return presence; - } /// /// Updates only the of the and sends the updated presence to Discord. Returns the newly edited Rich Presence. /// /// The party of the Rich Presence /// Updated Rich Presence - public RichPresence UpdateParty(Party party) - { - if (!IsInitialized) - throw new UninitializedException(); + public RichPresence UpdateParty(Party party) => Update(p => p.Party = party); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - presence.Party = party; - SetPresence(presence); - return presence; - } /// /// Updates the of the and sends the update presence to Discord. Returns the newly edited Rich Presence. /// Will return null if no presence exists and will throw a new if the Party does not exist. /// /// The new size of the party. It cannot be greater than /// Updated Rich Presence - public RichPresence UpdatePartySize(int size) + public RichPresence UpdatePartySize(int size) => Update(p => { - if (!IsInitialized) - throw new UninitializedException(); - - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Ensure it has a party - if (presence.Party == null) + // Ensure we have a party going on + if (p.Party == null) throw new BadPresenceException("Cannot set the size of the party if the party does not exist"); - //Update the value - presence.Party.Size = size; - SetPresence(presence); - return presence; - } + // Update the size + p.Party.Size = size; + }); /// /// Updates the of the and sends the update presence to Discord. Returns the newly edited Rich Presence. @@ -654,29 +571,15 @@ public RichPresence UpdatePartySize(int size) /// The new size of the party. It cannot be greater than /// The new size of the party. It cannot be smaller than /// Updated Rich Presence - public RichPresence UpdatePartySize(int size, int max) + public RichPresence UpdatePartySize(int size, int max) => Update(p => { - if (!IsInitialized) - throw new UninitializedException(); - - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Ensure it has a party - if (presence.Party == null) + // Ensure we have a party going on + if (p.Party == null) throw new BadPresenceException("Cannot set the size of the party if the party does not exist"); - //Update the value - presence.Party.Size = size; - presence.Party.Max = max; - SetPresence(presence); - return presence; - } + p.Party.Size = size; + p.Party.Max = max; + }); /// /// Updates the large of the and sends the updated presence to Discord. Both and are optional and will be ignored it null. @@ -684,25 +587,14 @@ public RichPresence UpdatePartySize(int size, int max) /// Optional: The new key to set the asset too /// Optional: The new tooltip to display on the asset /// Updated Rich Presence - public RichPresence UpdateLargeAsset(string key = null, string tooltip = null) + public RichPresence UpdateLargeAsset(string key = null, string tooltip = null) => Update(p => { - if (!IsInitialized) - throw new UninitializedException(); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } + if (p.Assets == null) + p.Assets = new Assets(); - //Update the value - if (presence.Assets == null) presence.Assets = new Assets(); - presence.Assets.LargeImageKey = key ?? presence.Assets.LargeImageKey; - presence.Assets.LargeImageText = tooltip ?? presence.Assets.LargeImageText; - SetPresence(presence); - return presence; - } + p.Assets.LargeImageKey = key ?? p.Assets.LargeImageKey; + p.Assets.LargeImageText = tooltip ?? p.Assets.LargeImageText; + }); /// /// Updates the small of the and sends the updated presence to Discord. Both and are optional and will be ignored it null. @@ -710,134 +602,66 @@ public RichPresence UpdateLargeAsset(string key = null, string tooltip = null) /// Optional: The new key to set the asset too /// Optional: The new tooltip to display on the asset /// Updated Rich Presence - public RichPresence UpdateSmallAsset(string key = null, string tooltip = null) + public RichPresence UpdateSmallAsset(string key = null, string tooltip = null) => Update(p => { - if (!IsInitialized) - throw new UninitializedException(); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } + if (p.Assets == null) + p.Assets = new Assets(); - //Update the value - if (presence.Assets == null) presence.Assets = new Assets(); - presence.Assets.SmallImageKey = key ?? presence.Assets.SmallImageKey; - presence.Assets.SmallImageText = tooltip ?? presence.Assets.SmallImageText; - SetPresence(presence); - return presence; - } + p.Assets.SmallImageKey = key ?? p.Assets.SmallImageKey; + p.Assets.SmallImageText = tooltip ?? p.Assets.SmallImageText; + }); /// /// Updates the of the and sends the updated presence to Discord. Will override previous secret entirely. /// /// The new secret to send to discord. /// Updated Rich Presence - public RichPresence UpdateSecrets(Secrets secrets) - { - if (!IsInitialized) - throw new UninitializedException(); - - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - presence.Secrets = secrets; - SetPresence(presence); - return presence; - } + public RichPresence UpdateSecrets(Secrets secrets) => Update(p => p.Secrets = secrets); /// /// Sets the start time of the to now and sends the updated presence to Discord. /// /// Updated Rich Presence - public RichPresence UpdateStartTime() { return UpdateStartTime(DateTime.UtcNow); } + public RichPresence UpdateStartTime() => UpdateStartTime(DateTime.UtcNow); /// /// Sets the start time of the and sends the updated presence to Discord. /// /// The new time for the start /// Updated Rich Presence - public RichPresence UpdateStartTime(DateTime time) + public RichPresence UpdateStartTime(DateTime time) => Update(p => { - if (!IsInitialized) - throw new UninitializedException(); + if (p.Timestamps == null) + p.Timestamps = new Timestamps(); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - if (presence.Timestamps == null) presence.Timestamps = new Timestamps(); - presence.Timestamps.Start = time; - SetPresence(presence); - return presence; - } + p.Timestamps.Start = time; + }); /// /// Sets the end time of the to now and sends the updated presence to Discord. /// /// Updated Rich Presence - public RichPresence UpdateEndTime() { return UpdateEndTime(DateTime.UtcNow); } + public RichPresence UpdateEndTime() => UpdateEndTime(DateTime.UtcNow); /// /// Sets the end time of the and sends the updated presence to Discord. /// /// The new time for the end /// Updated Rich Presence - public RichPresence UpdateEndTime(DateTime time) + public RichPresence UpdateEndTime(DateTime time) => Update(p => { - if (!IsInitialized) - throw new UninitializedException(); + if (p.Timestamps == null) + p.Timestamps = new Timestamps(); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - if (presence.Timestamps == null) presence.Timestamps = new Timestamps(); - presence.Timestamps.End = time; - SetPresence(presence); - return presence; - } + p.Timestamps.End = time; + }); /// /// Sets the start and end time of to null and sends it to Discord. /// /// Updated Rich Presence - public RichPresence UpdateClearTime() - { - if (!IsInitialized) - throw new UninitializedException(); + public RichPresence UpdateClearTime() => Update(p => p.Timestamps = null); - //Clone the presence - RichPresence presence; - lock (_sync) - { - if (CurrentPresence == null) { presence = new RichPresence(); } - else { presence = CurrentPresence.Clone(); } - } - - //Update the value - presence.Timestamps = null; - SetPresence(presence); - return presence; - } #endregion /// diff --git a/DiscordRPC/RichPresence.cs b/DiscordRPC/RichPresence.cs index aa5775cf..bc6f15ed 100644 --- a/DiscordRPC/RichPresence.cs +++ b/DiscordRPC/RichPresence.cs @@ -74,6 +74,12 @@ public string Details [JsonProperty("secrets", NullValueHandling = NullValueHandling.Ignore)] public Secrets Secrets { get; set; } + /// + /// The activity type + /// + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + public ActivityType Type { get; set; } + /// /// Marks the as a game session with a specific beginning and end. It was going to be used as a form of notification, but was replaced with the join feature. It may potentially have use in the future, but it currently has no use. /// @@ -170,7 +176,7 @@ internal virtual bool Matches(RichPresence other) if (other == null) return false; - if (State != other.State || Details != other.Details) + if (State != other.State || Details != other.Details || Type != other.Type) return false; //Checks if the timestamps are different @@ -243,6 +249,7 @@ public RichPresence ToRichPresence() var presence = new RichPresence(); presence.State = State; presence.Details = Details; + presence.Type = Type; presence.Party = !HasParty() ? Party : null; presence.Secrets = !HasSecrets() ? Secrets : null; @@ -687,7 +694,7 @@ public enum PrivacySetting Private = 0, /// - /// THe party is public, anyone can join. + /// The party is public, anyone can join. /// Public = 1 } @@ -787,6 +794,30 @@ public string Url private string _url; } + /// + /// Rich Presence activity type + /// + public enum ActivityType + { + // Streaming (1) and Custom (4) are not supported via RPC + /// + /// Playing status type. Displays as "Playing ..." + /// + Playing = 0, + /// + /// Listening status type. Displays as "Listening to ..." + /// + Listening = 2, + /// + /// Watching status type. Displays as "Watching ..." + /// + Watching = 3, + /// + /// Competing status type. Displays as "Competing in ..." + /// + Competing = 5 + } + /// /// The Rich Presence structure that will be sent and received by Discord. Use this class to build your presence and update it appropriately. /// @@ -833,6 +864,17 @@ public RichPresence WithDetails(string details) return this; } + /// + /// Sets the type of the Rich Presence. See also . + /// + /// The status type + /// The modified Rich Presence. + public RichPresence WithType(ActivityType type) + { + Type = type; + return this; + } + /// /// Sets the timestamp of the Rich Presence. See also . /// @@ -891,7 +933,8 @@ public RichPresence Clone() { State = this._state != null ? _state.Clone() as string : null, Details = this._details != null ? _details.Clone() as string : null, - + Type = this.Type, + Buttons = !HasButtons() ? null : this.Buttons.Clone() as Button[], Secrets = !HasSecrets() ? null : new Secrets { @@ -921,7 +964,6 @@ public RichPresence Clone() Max = this.Party.Max, Privacy = this.Party.Privacy, }, - }; } @@ -934,6 +976,7 @@ internal RichPresence Merge(BaseRichPresence presence) { this._state = presence.State; this._details = presence.Details; + this.Type = presence.Type; this.Party = presence.Party; this.Timestamps = presence.Timestamps; this.Secrets = presence.Secrets;