diff --git a/Manager.App/Components/Dialogs/AccountDialog.razor b/Manager.App/Components/Dialogs/AccountDialog.razor index 2a3d75f..e33353c 100644 --- a/Manager.App/Components/Dialogs/AccountDialog.razor +++ b/Manager.App/Components/Dialogs/AccountDialog.razor @@ -1,3 +1,5 @@ +@inject ISnackbar SnackbarService + @@ -14,11 +16,11 @@ Apply } - - + + - + Account id: @@ -28,6 +30,10 @@ Account name: @Client.AccountName + + Account handle: + @Client.AccountHandle + User agent: @Client.UserAgent @@ -51,6 +57,10 @@ + @if (!string.IsNullOrWhiteSpace(Client.AccountImage)) + { + + } @@ -84,14 +94,6 @@ - - - - - - - - diff --git a/Manager.App/Components/Dialogs/AccountDialog.razor.cs b/Manager.App/Components/Dialogs/AccountDialog.razor.cs index 16c6f64..738eed3 100644 --- a/Manager.App/Components/Dialogs/AccountDialog.razor.cs +++ b/Manager.App/Components/Dialogs/AccountDialog.razor.cs @@ -29,17 +29,6 @@ namespace Manager.App.Components.Dialogs Client.CookieContainer.Add(new Cookie { Name = "SET_NAME", Domain = ".youtube.com" }); } - private async Task RemoveCookie(Cookie? cookie) - { - if (cookie == null) - { - return; - } - - cookie.Expired = true; - await InvokeAsync(StateHasChanged); - } - private void ToggleCookieTextImport() { _showCookieTextImport =! _showCookieTextImport; @@ -97,13 +86,27 @@ namespace Manager.App.Components.Dialogs private bool CanSave() { - return Client.ClientState is { LoggedIn: true }; + if (Client.ClientState == null) + { + return false; + } + + if (string.IsNullOrWhiteSpace(Client.Id)) + { + return false; + } + + return Client.SapisidCookie != null && Client.ClientState.LoggedIn; } private async Task ValidateAccount() { _isLoading = true; - await Client.BuildClientAsync(); + var result = await Client.BuildClientAsync(); + if (!result.IsSuccess) + { + SnackbarService.Add(result.Error?.Description ?? "Error validating account.", Severity.Error); + } _isLoading = false; } diff --git a/Manager.YouTube/Models/AccountMenuInfo.cs b/Manager.YouTube/Models/AccountMenuInfo.cs index 2e1306b..e0c474a 100644 --- a/Manager.YouTube/Models/AccountMenuInfo.cs +++ b/Manager.YouTube/Models/AccountMenuInfo.cs @@ -5,4 +5,6 @@ public class AccountMenuInfo public string? AccountId { get; set; } public string? AccountHandle { get; set; } public string? ImageUrl { get; set; } + public int ImageWidth { get; set; } + public int ImageHeight { get; set; } } \ No newline at end of file diff --git a/Manager.YouTube/NetworkService.cs b/Manager.YouTube/NetworkService.cs index b3f4606..36a9ee9 100644 --- a/Manager.YouTube/NetworkService.cs +++ b/Manager.YouTube/NetworkService.cs @@ -128,16 +128,52 @@ public static class NetworkService return ResultError.Fail("Unable to get http client!"); } - var response = await http.SendAsync(httpRequest); - if (!response.IsSuccessStatusCode) + try { - var responseResult = await response.Content.ReadAsStringAsync(); - return ResultError.Fail(responseResult); + var response = await http.SendAsync(httpRequest); + if (!response.IsSuccessStatusCode) + { + var responseResult = await response.Content.ReadAsStringAsync(); + return ResultError.Fail(responseResult); + } + + var json = await response.Content.ReadAsStringAsync(); + var jsonDocument = JsonDocument.Parse(json); + var activeAccountHeader = jsonDocument.RootElement + .GetProperty("actions")[0] + .GetProperty("openPopupAction") + .GetProperty("popup") + .GetProperty("multiPageMenuRenderer") + .GetProperty("header") + .GetProperty("activeAccountHeaderRenderer"); + + var matRuns = activeAccountHeader + .GetProperty("manageAccountTitle") + .GetProperty("runs"); + + var accountPhotos = activeAccountHeader + .GetProperty("accountPhoto") + .GetProperty("thumbnails"); + + var accInfo = new AccountMenuInfo(); + + var highestImage = accountPhotos.EnumerateArray().OrderBy(x => x.GetProperty("width").Deserialize()) + .FirstOrDefault(); + accInfo.ImageUrl = highestImage.GetProperty("url").Deserialize(); + accInfo.ImageWidth = highestImage.GetProperty("width").Deserialize(); + accInfo.ImageHeight = highestImage.GetProperty("height").Deserialize(); + + foreach (var run in matRuns.EnumerateArray()) + { + var browseEndpoint = run.GetProperty("navigationEndpoint").GetProperty("browseEndpoint"); + accInfo.AccountId = browseEndpoint.GetProperty("browseId").GetString(); + accInfo.AccountHandle = browseEndpoint.GetProperty("canonicalBaseUrl").GetString()?.Replace("/", ""); + } + return accInfo; + } + catch (Exception e) + { + return ResultError.Error(e); } - - var json = await response.Content.ReadAsStringAsync(); - var jsonObject = JsonNode.Parse(json); - - return ResultError.Fail("Not implemented"); } } \ No newline at end of file diff --git a/Manager.YouTube/YouTubeClient.cs b/Manager.YouTube/YouTubeClient.cs index a6e489a..c26e304 100644 --- a/Manager.YouTube/YouTubeClient.cs +++ b/Manager.YouTube/YouTubeClient.cs @@ -1,4 +1,5 @@ using System.Net; +using DotBased.Monads; using Manager.YouTube.Models.Innertube; namespace Manager.YouTube; @@ -7,8 +8,10 @@ public sealed class YouTubeClient : IDisposable { public string Id { get; private set; } = ""; public string AccountName => ClientState?.UserAccountName ?? ""; + public string? AccountHandle { get; set; } + public string? AccountImage { get; set; } public string? UserAgent { get; set; } - public CookieContainer CookieContainer { get; } = new() { Capacity = 100, PerDomainCapacity = 50 }; + public CookieContainer CookieContainer { get; } = new() { PerDomainCapacity = 50 }; public ClientState? ClientState { get; private set; } public List DatasyncIds { get; set; } = []; public Cookie? SapisidCookie => CookieContainer.GetAllCookies()["SAPISID"]; @@ -35,14 +38,14 @@ public sealed class YouTubeClient : IDisposable _httpClient.DefaultRequestHeaders.Clear(); } - public async Task BuildClientAsync() + public async Task BuildClientAsync() { if (ClientState == null || !ClientState.LoggedIn) { var state = await NetworkService.GetClientStateAsync(this); if (!state.IsSuccess) { - return; + return state; } ClientState = state.Value; } @@ -52,7 +55,7 @@ public sealed class YouTubeClient : IDisposable var datasyncResult = await NetworkService.GetDatasyncIds(this); if (!datasyncResult.IsSuccess) { - return; + return datasyncResult; } foreach (var id in datasyncResult.Value) @@ -63,7 +66,17 @@ public sealed class YouTubeClient : IDisposable } } - var accountInfo = await NetworkService.GetCurrentAccountInfoAsync(this); + var accountInfoResult = await NetworkService.GetCurrentAccountInfoAsync(this); + if (!accountInfoResult.IsSuccess) + { + return accountInfoResult; + } + + Id = accountInfoResult.Value.AccountId ?? ""; + AccountHandle = accountInfoResult.Value.AccountHandle; + AccountImage = accountInfoResult.Value.ImageUrl; + + return Result.Success(); } public void Dispose()