[CHANGE] Reworked client creation
This commit is contained in:
@@ -2,112 +2,195 @@
|
||||
|
||||
<ForcedLoadingOverlay Visible="_isLoading"/>
|
||||
|
||||
@{
|
||||
var client = PreparingClient?.YouTubeClient;
|
||||
var clientState = client?.State;
|
||||
var channel = PreparingClient?.Channel;
|
||||
var avatar = channel?.AvatarImages.FirstOrDefault();
|
||||
var banner = channel?.BannerImages.FirstOrDefault();
|
||||
}
|
||||
<MudDialog>
|
||||
<TitleContent>
|
||||
<MudText Typo="Typo.h6">Add new account</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
<MudStack Spacing="2">
|
||||
<MudStack Row Spacing="2" AlignItems="AlignItems.Start" Justify="Justify.SpaceEvenly" StretchItems="StretchItems.All">
|
||||
@switch (_steps)
|
||||
{
|
||||
case AccountImportSteps.Authenticate:
|
||||
<MudStack Spacing="2">
|
||||
<MudTextField Label="UserAgent" Required @bind-Value="@Client.UserAgent"/>
|
||||
</MudStack>
|
||||
<MudSimpleTable Bordered Dense Elevation="0" Outlined Square Hover>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Account id:</td>
|
||||
<td>@Client.Id</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Account name:</td>
|
||||
<td>@Client.External.Channel?.ChannelName</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Account handle:</td>
|
||||
<td>@Client.External.Channel?.Handle</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Logged in:</td>
|
||||
<td style="@($"color: {(Client.External.State?.LoggedIn ?? false ? "green" : "red")}")">@Client.External.State?.LoggedIn</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>YouTube Premium:</td>
|
||||
<td style="@($"color: {(Client.External.State?.IsPremiumUser ?? false ? "green" : "red")}")">@Client.External.State?.IsPremiumUser</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>User agent:</td>
|
||||
<td>@Client.UserAgent</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InnerTube client:</td>
|
||||
<td>@Client.External.State?.InnerTubeClient</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InnerTube client version:</td>
|
||||
<td>@Client.External.State?.InnerTubeClientVersion</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InnerTube API key:</td>
|
||||
<td>@Client.External.State?.InnertubeApiKey</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Language:</td>
|
||||
<td>@Client.External.State?.InnerTubeContext?.InnerTubeClient?.HLanguage</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
@{
|
||||
var avatar = Client.External.Channel?.AvatarImages.FirstOrDefault();
|
||||
}
|
||||
@if (avatar != null)
|
||||
{
|
||||
<MudImage Src="@avatar.Url" Elevation="0" ObjectFit="ObjectFit.ScaleDown" Width="75"/>
|
||||
}
|
||||
</MudStack>
|
||||
<MudPaper Elevation="0" Outlined Class="pa-2">
|
||||
<MudSwitch @bind-Value="@IsAnonymous" Color="Color.Info">Anonymous client</MudSwitch>
|
||||
<MudTextField @bind-Value="@DefaultUserAgent" Required Label="User agent"
|
||||
HelperText="Use an WEB client user agent."/>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="0" Outlined Class="pa-2">
|
||||
<MudText>Import cookies</MudText>
|
||||
<MudForm @bind-IsValid="@_cookieTextValid" Disabled="@(Client.CookieContainer.Count != 0)">
|
||||
<MudTextField @bind-Value="@_cookieDomain" Immediate Required Label="Domain" RequiredError="Domain is required."/>
|
||||
<MudTextField Class="my-2" Lines="4" AutoGrow @bind-Value="@_cookieText" Immediate Required Label="Cookies" Placeholder="EXAMPLE: Cookie1=Value1; Cookie2=Value2;"
|
||||
Validation="@(new Func<string, string?>(ValidateCookieText))"/>
|
||||
<MudButton Variant="Variant.Outlined" Disabled="@(!_cookieTextValid)" OnClick="ParseCookies">Load</MudButton>
|
||||
</MudForm>
|
||||
</MudPaper>
|
||||
<MudStack Row Spacing="2" Style="height: 100%">
|
||||
<MudPaper Elevation="0" Outlined Class="pa-2" Style="width: 50%;">
|
||||
<MudText>Import cookies</MudText>
|
||||
<MudText Typo="Typo.caption">@($"{ImportCookies.Count} cookie(s) imported")</MudText>
|
||||
<MudForm @bind-IsValid="@_cookieImportTextValid" Disabled="@(IsAnonymous)">
|
||||
<MudTextField @bind-Value="@_cookieDomain" Immediate Required Label="Domain"
|
||||
RequiredError="Domain is required."/>
|
||||
<MudTextField Class="my-2" Lines="4" AutoGrow @bind-Value="@_cookieText" Immediate
|
||||
Required Label="Cookies" Variant="Variant.Outlined"
|
||||
Placeholder="EXAMPLE: Cookie1=Value1; Cookie2=Value2;"
|
||||
Validation="@(new Func<string, string?>(ValidateCookieText))"/>
|
||||
<MudButton Variant="Variant.Outlined" Disabled="@(!_cookieImportTextValid)"
|
||||
OnClick="ParseCookies">Import
|
||||
</MudButton>
|
||||
</MudForm>
|
||||
</MudPaper>
|
||||
|
||||
<MudDataGrid Items="Client.CookieContainer.GetAllCookies()" Dense Elevation="0" Outlined>
|
||||
<Header>
|
||||
<MudStack Class="ma-2">
|
||||
<MudText>Cookies</MudText>
|
||||
<MudDataGrid Items="ImportCookies" Dense Elevation="0" Outlined Style="width: 50%;">
|
||||
<Header>
|
||||
<MudStack Class="ma-2">
|
||||
<MudText>Cookies</MudText>
|
||||
</MudStack>
|
||||
</Header>
|
||||
<Columns>
|
||||
<TemplateColumn Title="Name">
|
||||
<CellTemplate>
|
||||
<MudTextField Variant="Variant.Text" @bind-Value="@context.Item.Name"
|
||||
Immediate/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn Title="Domain">
|
||||
<CellTemplate>
|
||||
<MudTextField Variant="Variant.Text" @bind-Value="@context.Item.Domain"
|
||||
Immediate/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn Title="Value">
|
||||
<CellTemplate>
|
||||
<MudTextField Variant="Variant.Text" @bind-Value="@context.Item.Value"
|
||||
Immediate/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
</MudStack>
|
||||
</Header>
|
||||
<Columns>
|
||||
<TemplateColumn Title="Name">
|
||||
<CellTemplate>
|
||||
<MudTextField Variant="Variant.Text" @bind-Value="@context.Item.Name" Immediate/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn Title="Domain">
|
||||
<CellTemplate>
|
||||
<MudTextField Variant="Variant.Text" @bind-Value="@context.Item.Domain" Immediate/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn Title="Value">
|
||||
<CellTemplate>
|
||||
<MudTextField Variant="Variant.Text" @bind-Value="@context.Item.Value" Immediate/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<PropertyColumn Title="Expires" Property="x => x.Expires"/>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
break;
|
||||
case AccountImportSteps.Validate:
|
||||
<MudStack Spacing="3">
|
||||
<MudPaper Elevation="0">
|
||||
@if (banner != null)
|
||||
{
|
||||
<MudImage Src="@banner.Url" Height="250" Style="width: 100%;"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div Class="account-banner" Style="height: 250px; width: 100%;"></div>
|
||||
}
|
||||
<MudStack Row Spacing="3" Class="px-4">
|
||||
@if (avatar != null)
|
||||
{
|
||||
<MudImage Src="@avatar.Url" Class="mt-n5" Height="100" Width="100"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div Class="avatar-pattern mt-n6" Style="height: 100px; width: 100px;"></div>
|
||||
}
|
||||
<MudStack Spacing="0">
|
||||
<MudText Typo="Typo.h5">@(channel?.ChannelName ?? client?.Id)</MudText>
|
||||
<MudText Typo="Typo.caption">@(string.IsNullOrWhiteSpace(channel?.Description) ? "No description!" : channel.Description)</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
<MudSimpleTable Bordered Dense Elevation="0" Outlined Square Hover>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Account id:</td>
|
||||
<td>@client?.Id</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Account name:</td>
|
||||
<td>@channel?.ChannelName</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Account handle:</td>
|
||||
<td>@channel?.Handle</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Logged in:</td>
|
||||
<td style="@($"color: {(clientState?.LoggedIn ?? false ? "green" : "red")}")">@clientState?.LoggedIn</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>YouTube Premium:</td>
|
||||
<td style="@($"color: {(clientState?.IsPremiumUser ?? false ? "green" : "red")}")">@clientState?.IsPremiumUser</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>User agent:</td>
|
||||
<td>@client?.UserAgent</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InnerTube client:</td>
|
||||
<td>@clientState?.InnerTubeClient</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InnerTube client version:</td>
|
||||
<td>@clientState?.InnerTubeClientVersion</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InnerTube API key:</td>
|
||||
<td>@clientState?.InnertubeApiKey</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Language:</td>
|
||||
<td>@clientState?.InnerTubeContext?.InnerTubeClient?.HLanguage</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
</MudStack>
|
||||
break;
|
||||
}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Spacing="2" Row>
|
||||
<MudButton Color="Color.Error" OnClick="() => MudDialog?.Cancel()" Variant="Variant.Outlined">Cancel</MudButton>
|
||||
<MudButton Color="Color.Info" Variant="Variant.Outlined" OnClick="ValidateAccount" Disabled="@(!CanValidate())">Validate</MudButton>
|
||||
<MudButton Color="Color.Primary" Variant="Variant.Outlined" Disabled="@(!CanSave())" OnClick="OnSave">Save</MudButton>
|
||||
<MudButton Color="Color.Error" OnClick="() => MudDialog?.Cancel()" Variant="Variant.Outlined">Cancel
|
||||
</MudButton>
|
||||
<MudButton Color="Color.Info" OnClick="ClearPreparedClient" Variant="Variant.Outlined">Reset</MudButton>
|
||||
<MudButton Color="Color.Primary" OnClick="OnNextStep" Disabled="@(!CanContinue())" Variant="Variant.Outlined">@(_steps == AccountImportSteps.Validate ? "Save" : "Next")</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
</MudDialog>
|
||||
|
||||
<style>
|
||||
.account-banner {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
|
||||
/* Pattern background */
|
||||
background: repeating-linear-gradient(
|
||||
135deg,
|
||||
#1976d2, /* MudBlazor Primary */
|
||||
#1976d2 20px,
|
||||
#1565c0 20px,
|
||||
#1565c0 40px
|
||||
);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.avatar-pattern {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
color: white;
|
||||
|
||||
/* Patterned background */
|
||||
background: repeating-linear-gradient(
|
||||
45deg,
|
||||
#1976d2,
|
||||
#1976d2 10px,
|
||||
#1565c0 10px,
|
||||
#1565c0 20px
|
||||
);
|
||||
}
|
||||
</style>
|
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using Manager.App.Models.Library;
|
||||
using Manager.YouTube;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
@@ -9,27 +10,79 @@ namespace Manager.App.Components.Dialogs
|
||||
{
|
||||
[CascadingParameter] private IMudDialogInstance? MudDialog { get; set; }
|
||||
[Parameter] public string DefaultUserAgent { get; set; } = "";
|
||||
|
||||
public YouTubeClient Client { get; set; } = new();
|
||||
|
||||
private bool IsAnonymous { get; set; }
|
||||
private ClientPrep? PreparingClient { get; set; }
|
||||
private CookieCollection ImportCookies { get; set; } = [];
|
||||
private bool _isLoading;
|
||||
private AccountImportSteps _steps = AccountImportSteps.Authenticate;
|
||||
|
||||
private bool _cookieTextValid;
|
||||
private bool _cookieImportTextValid;
|
||||
private string _cookieText = "";
|
||||
private string _cookieDomain = ".youtube.com";
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
Client.UserAgent = DefaultUserAgent;
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
private bool CanSave()
|
||||
{
|
||||
if (IsAnonymous || PreparingClient?.YouTubeClient?.State?.LoggedIn == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CanContinue()
|
||||
{
|
||||
switch (_steps)
|
||||
{
|
||||
case AccountImportSteps.Authenticate:
|
||||
if (IsAnonymous || ImportCookies.Count != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case AccountImportSteps.Validate:
|
||||
if (IsAnonymous || PreparingClient?.YouTubeClient?.State?.LoggedIn == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task OnNextStep()
|
||||
{
|
||||
switch (_steps)
|
||||
{
|
||||
case AccountImportSteps.Authenticate:
|
||||
if (CanContinue())
|
||||
{
|
||||
_steps = AccountImportSteps.Validate;
|
||||
await BuildClient();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
return;
|
||||
}
|
||||
SnackbarService.Add("Cannot continue!", Severity.Warning);
|
||||
break;
|
||||
case AccountImportSteps.Validate:
|
||||
if (CanSave())
|
||||
{
|
||||
MudDialog?.Close(DialogResult.Ok(PreparingClient));
|
||||
await InvokeAsync(StateHasChanged);
|
||||
return;
|
||||
}
|
||||
SnackbarService.Add("Cannot save!", Severity.Warning);
|
||||
break;
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void ParseCookies()
|
||||
{
|
||||
try
|
||||
{
|
||||
var cookies = ParseCookieHeader(_cookieText, _cookieDomain);
|
||||
Client.CookieContainer.Add(cookies);
|
||||
ImportCookies.Clear();
|
||||
ImportCookies.Add(ParseCookieHeader(_cookieText, _cookieDomain));
|
||||
_cookieText = string.Empty;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -39,6 +92,16 @@ namespace Manager.App.Components.Dialogs
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void ClearPreparedClient()
|
||||
{
|
||||
PreparingClient?.YouTubeClient?.Dispose();
|
||||
PreparingClient = null;
|
||||
IsAnonymous = false;
|
||||
ImportCookies.Clear();
|
||||
_steps = AccountImportSteps.Authenticate;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private static string? ValidateCookieText(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
@@ -82,46 +145,41 @@ namespace Manager.App.Components.Dialogs
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
private bool CanValidate()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Client.UserAgent) || Client.CookieContainer.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CanSave()
|
||||
{
|
||||
if (Client.External.State == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Client.Id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Client.SapisidCookie != null && Client.External.State.LoggedIn;
|
||||
}
|
||||
|
||||
private async Task ValidateAccount()
|
||||
|
||||
private async Task BuildClient()
|
||||
{
|
||||
_isLoading = true;
|
||||
var result = await Client.BuildClientAsync();
|
||||
if (!result.IsSuccess)
|
||||
PreparingClient = new ClientPrep();
|
||||
if (IsAnonymous)
|
||||
{
|
||||
SnackbarService.Add(result.Error?.Description ?? "Error validating account.", Severity.Error);
|
||||
ImportCookies.Clear();
|
||||
}
|
||||
var clientResult = await YouTubeClient.CreateAsync(ImportCookies, DefaultUserAgent);
|
||||
if (clientResult.IsSuccess)
|
||||
{
|
||||
PreparingClient.YouTubeClient = clientResult.Value;
|
||||
}
|
||||
|
||||
if (PreparingClient.YouTubeClient == null)
|
||||
{
|
||||
SnackbarService.Add("Failed to get client!", Severity.Error);
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var accountResult = await PreparingClient.YouTubeClient.GetChannelByIdAsync(PreparingClient.YouTubeClient.Id);
|
||||
if (accountResult.IsSuccess)
|
||||
{
|
||||
PreparingClient.Channel = accountResult.Value;
|
||||
}
|
||||
_isLoading = false;
|
||||
}
|
||||
|
||||
private void OnSave()
|
||||
{
|
||||
MudDialog?.Close(DialogResult.Ok(Client));
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
public enum AccountImportSteps
|
||||
{
|
||||
Authenticate,
|
||||
Validate
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user