-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Music services support (partial)
* Initial music service support? * Finish login support * Music client login in cli * Adding Playlist to queue and start stream Merged #2
- Loading branch information
Showing
57 changed files
with
2,435 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace Sonos.Base.Music | ||
{ | ||
public enum AuthenticationType | ||
{ | ||
Anonymous, | ||
AppLink, | ||
DeviceLink, | ||
UserId, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Sonos.Base.Music | ||
{ | ||
public interface IMusicClientCredentialStore | ||
{ | ||
Task<MusicClientAccount?> GetAccountAsync(int serviceId, CancellationToken cancellationToken = default); | ||
|
||
Task<bool> SaveAccountAsync(int serviceId, string key, string token, CancellationToken cancellationToken = default); | ||
} | ||
|
||
public record MusicClientAccount(string Key, string Token); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging.Abstractions; | ||
using Sonos.Base.Services; | ||
using System.Text.Json; | ||
|
||
namespace Sonos.Base.Music | ||
{ | ||
public class KvMusicServiceAccountStore : IMusicClientCredentialStore | ||
{ | ||
private readonly SystemPropertiesService _propertiesService; | ||
private readonly ILogger<KvMusicServiceAccountStore> _logger; | ||
private readonly Dictionary<int, MusicClientAccount> store = new Dictionary<int, MusicClientAccount>(); | ||
|
||
public KvMusicServiceAccountStore(SystemPropertiesService propertiesService, ILogger<KvMusicServiceAccountStore>? logger) | ||
{ | ||
_propertiesService = propertiesService; | ||
_logger = logger ?? NullLogger<KvMusicServiceAccountStore>.Instance; | ||
} | ||
|
||
public async Task<MusicClientAccount?> GetAccountAsync(int serviceId, CancellationToken cancellationToken = default) | ||
{ | ||
_logger.LogDebug("Loading account for service {serviceId}", serviceId); | ||
if (!store.ContainsKey(serviceId)) | ||
{ | ||
try | ||
{ | ||
var key = GetKeyForService(serviceId); | ||
var data = await _propertiesService.GetStringAsync(key, cancellationToken); | ||
var account = JsonSerializer.Deserialize<MusicClientAccount>(data); | ||
if (account == null) | ||
{ | ||
return null; | ||
} | ||
store[serviceId] = account; | ||
return account; | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogWarning(ex, "Error getting account for {serviceId}", serviceId); | ||
return null; | ||
} | ||
} | ||
return store[serviceId]; | ||
} | ||
|
||
public async Task<bool> SaveAccountAsync(int serviceId, string key, string token, CancellationToken cancellationToken = default) | ||
{ | ||
var account = new MusicClientAccount(key, token); | ||
store[serviceId] = account; | ||
|
||
try | ||
{ | ||
var result = await _propertiesService.SetStringAsync(GetKeyForService(serviceId), JsonSerializer.Serialize(account), cancellationToken); | ||
return result; | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogWarning(ex, "Error saving account for {serviceId}", serviceId); | ||
return false; | ||
} | ||
} | ||
|
||
private string GetKeyForService(int serviceId) => $"SonosNet-Music-{serviceId}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging.Abstractions; | ||
|
||
namespace Sonos.Base.Music | ||
{ | ||
internal class MemoryMusicServiceAccountStore : IMusicClientCredentialStore | ||
{ | ||
private readonly ILogger<MemoryMusicServiceAccountStore> logger; | ||
|
||
public MemoryMusicServiceAccountStore(ILogger<MemoryMusicServiceAccountStore>? logger = null) | ||
{ | ||
this.logger = logger ?? NullLogger<MemoryMusicServiceAccountStore>.Instance; | ||
} | ||
|
||
private readonly Dictionary<int, MusicClientAccount> store = new Dictionary<int, MusicClientAccount>(); | ||
|
||
public async Task<MusicClientAccount?> GetAccountAsync(int serviceId, CancellationToken cancellationToken = default) | ||
{ | ||
logger.LogDebug("Loading account for service {serviceId}", serviceId); | ||
return store.ContainsKey(serviceId) ? store[serviceId] : null; | ||
} | ||
|
||
public async Task<bool> SaveAccountAsync(int serviceId, string key, string token, CancellationToken cancellationToken = default) | ||
{ | ||
logger.LogDebug("Saving account for service {serviceId}", serviceId); | ||
if (store.ContainsKey(serviceId)) | ||
{ | ||
store[serviceId] = new MusicClientAccount(key, token); | ||
} | ||
else | ||
{ | ||
store.Add(serviceId, new MusicClientAccount(key, token)); | ||
} | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System.Xml.Serialization; | ||
|
||
namespace Sonos.Base.Music.Models | ||
{ | ||
[Serializable()] | ||
[XmlRoot(Namespace = "http://www.sonos.com/Services/1.1")] | ||
public class GetAppLinkRequest : MusicClientBaseRequest | ||
{ | ||
/// <summary> | ||
/// Load from DevicePropertiesService.GetHouseholdID() | ||
/// </summary> | ||
[XmlElement(ElementName = "householdId", Namespace = "http://www.sonos.com/Services/1.1")] | ||
public string HouseholdId { get; set; } | ||
} | ||
|
||
/// <remarks/> | ||
[Serializable()] | ||
[System.ComponentModel.DesignerCategory("code")] | ||
[XmlType(AnonymousType = true, Namespace = "http://www.sonos.com/Services/1.1")] | ||
[XmlRoot(Namespace = "http://www.sonos.com/Services/1.1", IsNullable = false)] | ||
public partial class GetAppLinkResponse : ISmapiResponse<GetAppLinkResult> | ||
{ | ||
[XmlElement("getAppLinkResult")] | ||
public GetAppLinkResult Result { get; set; } | ||
} | ||
|
||
/// <remarks/> | ||
[Serializable()] | ||
[System.ComponentModel.DesignerCategory("code")] | ||
[XmlType(AnonymousType = true, Namespace = "http://www.sonos.com/Services/1.1")] | ||
public partial class GetAppLinkResult | ||
{ | ||
[XmlElement("authorizeAccount")] | ||
public GetAppLinkAuthorizeAccount AuthorizeAccount { get; set; } | ||
|
||
[XmlElement("createAccount")] | ||
public GetAppLinkAccount CreateAccount { get; set; } | ||
} | ||
|
||
[Serializable()] | ||
[System.ComponentModel.DesignerCategory("code")] | ||
[XmlType(AnonymousType = true, Namespace = "http://www.sonos.com/Services/1.1")] | ||
public partial class GetAppLinkAccount | ||
{ | ||
[XmlElement("appUrlStringId")] | ||
public string AppUrlStringId { get; set; } | ||
} | ||
|
||
[Serializable()] | ||
[System.ComponentModel.DesignerCategory("code")] | ||
[XmlType(AnonymousType = true, Namespace = "http://www.sonos.com/Services/1.1")] | ||
public partial class GetAppLinkAuthorizeAccount : GetAppLinkAccount | ||
{ | ||
[XmlElement("deviceLink")] | ||
public GetAppLinkDeviceLink DeviceLink { get; set; } | ||
} | ||
|
||
|
||
public partial class GetAppLinkDeviceLink | ||
{ | ||
[XmlElement("regUrl")] | ||
|
||
public string RegistrationUrl { get; set; } | ||
[XmlElement("linkCode")] | ||
|
||
public string LinkCode { get; set; } | ||
[XmlElement("showLinkCode")] | ||
|
||
public bool ShowLinkCode { get; set; } | ||
} | ||
} |
Oops, something went wrong.