From 64b9cc7a538195040cd60779b68c0d11b77ca3c0 Mon Sep 17 00:00:00 2001 From: Still Hsu <341464@gmail.com> Date: Mon, 19 Mar 2018 04:06:53 +0800 Subject: [PATCH] Add Spotify track support (#970) * Initial Spotify support * Remove GameAsset#ToEntity - appId doesn't seem to be necessary, and Spotify Game doesn't return appId either. * Implement SpotifyGame details * Implement song Duration prop * Add album art CDN * Fix ActivityType * Remove payload debug * Add changes according to review + Make `ApplicationId` nullable + Move ctor after props --- .../Entities/Activities/Game.cs | 2 +- .../Entities/Activities/GameAsset.cs | 8 +++---- .../Entities/Activities/RichGame.cs | 8 +++---- .../Entities/Activities/SpotifyGame.cs | 23 +++++++++++++++++++ src/Discord.Net.Rest/API/Common/Game.cs | 6 ++++- .../Extensions/EntityExtensions.cs | 23 ++++++++++++++++++- 6 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 src/Discord.Net.Core/Entities/Activities/SpotifyGame.cs diff --git a/src/Discord.Net.Core/Entities/Activities/Game.cs b/src/Discord.Net.Core/Entities/Activities/Game.cs index fe32470ee..179ad4eaa 100644 --- a/src/Discord.Net.Core/Entities/Activities/Game.cs +++ b/src/Discord.Net.Core/Entities/Activities/Game.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; namespace Discord { diff --git a/src/Discord.Net.Core/Entities/Activities/GameAsset.cs b/src/Discord.Net.Core/Entities/Activities/GameAsset.cs index 385f37214..02c29ba41 100644 --- a/src/Discord.Net.Core/Entities/Activities/GameAsset.cs +++ b/src/Discord.Net.Core/Entities/Activities/GameAsset.cs @@ -1,15 +1,15 @@ -namespace Discord +namespace Discord { public class GameAsset { internal GameAsset() { } - internal ulong ApplicationId { get; set; } + internal ulong? ApplicationId { get; set; } public string Text { get; internal set; } public string ImageId { get; internal set; } public string GetImageUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) - => CDN.GetRichAssetUrl(ApplicationId, ImageId, size, format); + => ApplicationId.HasValue ? CDN.GetRichAssetUrl(ApplicationId.Value, ImageId, size, format) : null; } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Core/Entities/Activities/RichGame.cs b/src/Discord.Net.Core/Entities/Activities/RichGame.cs index e66eac1d2..fc3f68cf0 100644 --- a/src/Discord.Net.Core/Entities/Activities/RichGame.cs +++ b/src/Discord.Net.Core/Entities/Activities/RichGame.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; namespace Discord { @@ -7,8 +7,8 @@ namespace Discord { internal RichGame() { } - public string Details { get; internal set;} - public string State { get; internal set;} + public string Details { get; internal set; } + public string State { get; internal set; } public ulong ApplicationId { get; internal set; } public GameAsset SmallAsset { get; internal set; } public GameAsset LargeAsset { get; internal set; } @@ -19,4 +19,4 @@ namespace Discord public override string ToString() => Name; private string DebuggerDisplay => $"{Name} (Rich)"; } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Core/Entities/Activities/SpotifyGame.cs b/src/Discord.Net.Core/Entities/Activities/SpotifyGame.cs new file mode 100644 index 000000000..b8a4b8043 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Activities/SpotifyGame.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Discord +{ + [DebuggerDisplay(@"{DebuggerDisplay,nq}")] + public class SpotifyGame : Game + { + public string[] Artists { get; internal set; } + public string AlbumArt { get; internal set; } + public string AlbumTitle { get; internal set; } + public string TrackTitle { get; internal set; } + public string SyncId { get; internal set; } + public string SessionId { get; internal set; } + public TimeSpan? Duration { get; internal set; } + + internal SpotifyGame() { } + + public override string ToString() => Name; + private string DebuggerDisplay => $"{Name} (Spotify)"; + } +} diff --git a/src/Discord.Net.Rest/API/Common/Game.cs b/src/Discord.Net.Rest/API/Common/Game.cs index 29e0d987d..4cde8444a 100644 --- a/src/Discord.Net.Rest/API/Common/Game.cs +++ b/src/Discord.Net.Rest/API/Common/Game.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591 using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System.Runtime.Serialization; @@ -29,6 +29,10 @@ namespace Discord.API public Optional Timestamps { get; set; } [JsonProperty("instance")] public Optional Instance { get; set; } + [JsonProperty("sync_id")] + public Optional SyncId { get; set; } + [JsonProperty("session_id")] + public Optional SessionId { get; set; } [OnError] internal void OnError(StreamingContext context, ErrorContext errorContext) diff --git a/src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs b/src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs index 181a837e4..f268a7ff2 100644 --- a/src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs +++ b/src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs @@ -4,6 +4,27 @@ namespace Discord.WebSocket { public static IActivity ToEntity(this API.Game model) { + // Spotify Game + if (model.SyncId.IsSpecified) + { + var assets = model.Assets.GetValueOrDefault()?.ToEntity(); + string albumText = assets?[1]?.Text; + string albumArtId = assets?[1]?.ImageId?.Replace("spotify:",""); + var timestamps = model.Timestamps.IsSpecified ? model.Timestamps.Value.ToEntity() : null; + return new SpotifyGame + { + Name = model.Name, + SessionId = model.SessionId.GetValueOrDefault(), + SyncId = model.SyncId.Value, + AlbumTitle = albumText, + TrackTitle = model.Details.GetValueOrDefault(), + Artists = model.State.GetValueOrDefault()?.Split(';'), + Duration = timestamps?.End - timestamps?.Start, + AlbumArt = albumArtId != null ? $"https://i.scdn.co/image/{albumArtId}" : null, + Type = ActivityType.Listening + }; + } + // Rich Game if (model.ApplicationId.IsSpecified) { @@ -34,7 +55,7 @@ namespace Discord.WebSocket } // (Small, Large) - public static GameAsset[] ToEntity(this API.GameAssets model, ulong appId) + public static GameAsset[] ToEntity(this API.GameAssets model, ulong? appId = null) { return new GameAsset[] {