* 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 propstags/2.0
| @@ -1,4 +1,4 @@ | |||||
| using System.Diagnostics; | |||||
| using System.Diagnostics; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -1,15 +1,15 @@ | |||||
| namespace Discord | |||||
| namespace Discord | |||||
| { | { | ||||
| public class GameAsset | public class GameAsset | ||||
| { | { | ||||
| internal GameAsset() { } | internal GameAsset() { } | ||||
| internal ulong ApplicationId { get; set; } | |||||
| internal ulong? ApplicationId { get; set; } | |||||
| public string Text { get; internal set; } | public string Text { get; internal set; } | ||||
| public string ImageId { get; internal set; } | public string ImageId { get; internal set; } | ||||
| public string GetImageUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | 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; | |||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| using System.Diagnostics; | |||||
| using System.Diagnostics; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -7,8 +7,8 @@ namespace Discord | |||||
| { | { | ||||
| internal RichGame() { } | 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 ulong ApplicationId { get; internal set; } | ||||
| public GameAsset SmallAsset { get; internal set; } | public GameAsset SmallAsset { get; internal set; } | ||||
| public GameAsset LargeAsset { get; internal set; } | public GameAsset LargeAsset { get; internal set; } | ||||
| @@ -19,4 +19,4 @@ namespace Discord | |||||
| public override string ToString() => Name; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => $"{Name} (Rich)"; | private string DebuggerDisplay => $"{Name} (Rich)"; | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -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)"; | |||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| #pragma warning disable CS1591 | |||||
| #pragma warning disable CS1591 | |||||
| using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Serialization; | using Newtonsoft.Json.Serialization; | ||||
| using System.Runtime.Serialization; | using System.Runtime.Serialization; | ||||
| @@ -29,6 +29,10 @@ namespace Discord.API | |||||
| public Optional<API.GameTimestamps> Timestamps { get; set; } | public Optional<API.GameTimestamps> Timestamps { get; set; } | ||||
| [JsonProperty("instance")] | [JsonProperty("instance")] | ||||
| public Optional<bool> Instance { get; set; } | public Optional<bool> Instance { get; set; } | ||||
| [JsonProperty("sync_id")] | |||||
| public Optional<string> SyncId { get; set; } | |||||
| [JsonProperty("session_id")] | |||||
| public Optional<string> SessionId { get; set; } | |||||
| [OnError] | [OnError] | ||||
| internal void OnError(StreamingContext context, ErrorContext errorContext) | internal void OnError(StreamingContext context, ErrorContext errorContext) | ||||
| @@ -4,6 +4,27 @@ namespace Discord.WebSocket | |||||
| { | { | ||||
| public static IActivity ToEntity(this API.Game model) | 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 | // Rich Game | ||||
| if (model.ApplicationId.IsSpecified) | if (model.ApplicationId.IsSpecified) | ||||
| { | { | ||||
| @@ -34,7 +55,7 @@ namespace Discord.WebSocket | |||||
| } | } | ||||
| // (Small, Large) | // (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[] | return new GameAsset[] | ||||
| { | { | ||||