Refactor user and media endpoints: remove unused GetUser and GetMedia methods, streamline AdminUserEndpoints and MediaEndpoints, and enhance metadata handling in MetadataEndpoints. Update Program.cs to remove legacy image relocation logic and improve overall code clarity.
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace TeleWave.Infrastructure.Metadata;
|
||||
|
||||
/// <summary>Общие для провайдеров метаданных хелперы: HTTP-загрузка JSON и чтение полей.</summary>
|
||||
internal static class MetadataJson
|
||||
{
|
||||
/// <summary>GET+parse через клиент "metadata"; бросает при не-2xx/сетевой ошибке (для поиска — показать сбой).</summary>
|
||||
public static async Task<JsonDocument> GetAsync(
|
||||
IHttpClientFactory httpFactory,
|
||||
string url,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
var client = httpFactory.CreateClient("metadata");
|
||||
using var response = await client.GetAsync(url, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
return await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>Как <see cref="GetAsync"/>, но глотает ошибки в null (для get/episode — деградируем мягко).</summary>
|
||||
public static async Task<JsonDocument?> TryGetAsync(
|
||||
IHttpClientFactory httpFactory,
|
||||
string url,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await GetAsync(httpFactory, url, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is HttpRequestException or JsonException or TaskCanceledException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string? GetString(JsonElement el, string name) =>
|
||||
el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String
|
||||
? v.GetString()
|
||||
: null;
|
||||
|
||||
public static int? GetInt(JsonElement el, string name) =>
|
||||
el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.Number
|
||||
? v.GetInt32()
|
||||
: null;
|
||||
|
||||
/// <summary>Год из первых 4 символов строки даты/года ("YYYY-MM-DD" или "YYYY").</summary>
|
||||
public static int? YearFrom(string? value) =>
|
||||
value is { Length: >= 4 } && int.TryParse(value.AsSpan(0, 4), out var y) ? y : null;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Text.Json;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
using TeleWave.Application.Metadata;
|
||||
using static TeleWave.Infrastructure.Metadata.MetadataJson;
|
||||
|
||||
namespace TeleWave.Infrastructure.Metadata;
|
||||
|
||||
@@ -23,7 +24,7 @@ public sealed class OmdbMetadataProvider(
|
||||
{
|
||||
var url =
|
||||
$"{_omdb.BaseUrl}/?apikey={_omdb.ApiKey}&type=series&s={Uri.EscapeDataString(query)}";
|
||||
using var doc = await GetJsonAsync(url, cancellationToken);
|
||||
using var doc = await GetAsync(httpFactory, url, cancellationToken);
|
||||
if (!doc.RootElement.TryGetProperty("Search", out var search))
|
||||
return [];
|
||||
|
||||
@@ -52,7 +53,7 @@ public sealed class OmdbMetadataProvider(
|
||||
)
|
||||
{
|
||||
var url = $"{_omdb.BaseUrl}/?apikey={_omdb.ApiKey}&i={Uri.EscapeDataString(externalId)}";
|
||||
using var doc = await TryGetJsonAsync(url, cancellationToken);
|
||||
using var doc = await TryGetAsync(httpFactory, url, cancellationToken);
|
||||
if (doc is null || !IsResponseTrue(doc.RootElement))
|
||||
return null;
|
||||
var root = doc.RootElement;
|
||||
@@ -75,7 +76,7 @@ public sealed class OmdbMetadataProvider(
|
||||
var url =
|
||||
$"{_omdb.BaseUrl}/?apikey={_omdb.ApiKey}&i={Uri.EscapeDataString(externalId)}"
|
||||
+ $"&Season={season}&Episode={episode}";
|
||||
using var doc = await TryGetJsonAsync(url, cancellationToken);
|
||||
using var doc = await TryGetAsync(httpFactory, url, cancellationToken);
|
||||
if (doc is null || !IsResponseTrue(doc.RootElement))
|
||||
return null;
|
||||
var root = doc.RootElement;
|
||||
@@ -95,7 +96,7 @@ public sealed class OmdbMetadataProvider(
|
||||
{
|
||||
var url =
|
||||
$"{_omdb.BaseUrl}/?apikey={_omdb.ApiKey}&i={Uri.EscapeDataString(externalId)}&Season={season}";
|
||||
using var doc = await TryGetJsonAsync(url, cancellationToken);
|
||||
using var doc = await TryGetAsync(httpFactory, url, cancellationToken);
|
||||
if (
|
||||
doc is null
|
||||
|| !IsResponseTrue(doc.RootElement)
|
||||
@@ -106,53 +107,14 @@ public sealed class OmdbMetadataProvider(
|
||||
return episodes.GetArrayLength();
|
||||
}
|
||||
|
||||
/// <summary>GET+parse; бросает при не-2xx/сетевой ошибке (для поиска — чтобы показать сбой).</summary>
|
||||
private async Task<JsonDocument> GetJsonAsync(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
var client = httpFactory.CreateClient("metadata");
|
||||
using var response = await client.GetAsync(url, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
return await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>Как GetJsonAsync, но глотает ошибки в null (для get/episode — деградируем мягко).</summary>
|
||||
private async Task<JsonDocument?> TryGetJsonAsync(
|
||||
string url,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await GetJsonAsync(url, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is HttpRequestException or JsonException or TaskCanceledException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsResponseTrue(JsonElement root) =>
|
||||
GetString(root, "Response") is { } r
|
||||
&& r.Equals("True", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private static string? GetString(JsonElement el, string name) =>
|
||||
el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String
|
||||
? v.GetString()
|
||||
: null;
|
||||
|
||||
/// <summary>OMDb отдаёт «N/A» вместо отсутствующих значений — приводим к null.</summary>
|
||||
private static string? Clean(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value) || value == "N/A" ? null : value;
|
||||
|
||||
private static int? YearFrom(string? year)
|
||||
{
|
||||
if (year is { Length: >= 4 } && int.TryParse(year.AsSpan(0, 4), out var y))
|
||||
return y;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DateOnly? DateFrom(string? released) =>
|
||||
DateTime.TryParse(released, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt)
|
||||
? DateOnly.FromDateTime(dt)
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Text.Json;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
using TeleWave.Application.Metadata;
|
||||
using static TeleWave.Infrastructure.Metadata.MetadataJson;
|
||||
|
||||
namespace TeleWave.Infrastructure.Metadata;
|
||||
|
||||
@@ -26,7 +27,7 @@ public sealed class TmdbMetadataProvider(
|
||||
var url =
|
||||
$"{Tmdb.BaseUrl}/search/tv?api_key={Tmdb.ApiKey}&language={_options.Language}"
|
||||
+ $"&include_adult=false&query={Uri.EscapeDataString(query)}";
|
||||
using var doc = await GetJsonAsync(url, cancellationToken);
|
||||
using var doc = await GetAsync(httpFactory, url, cancellationToken);
|
||||
if (!doc.RootElement.TryGetProperty("results", out var results))
|
||||
return [];
|
||||
|
||||
@@ -56,7 +57,7 @@ public sealed class TmdbMetadataProvider(
|
||||
{
|
||||
var url =
|
||||
$"{Tmdb.BaseUrl}/tv/{externalId}?api_key={Tmdb.ApiKey}&language={_options.Language}";
|
||||
using var doc = await TryGetJsonAsync(url, cancellationToken);
|
||||
using var doc = await TryGetAsync(httpFactory, url, cancellationToken);
|
||||
if (doc is null)
|
||||
return null;
|
||||
var root = doc.RootElement;
|
||||
@@ -79,7 +80,7 @@ public sealed class TmdbMetadataProvider(
|
||||
var url =
|
||||
$"{Tmdb.BaseUrl}/tv/{externalId}/season/{season}/episode/{episode}"
|
||||
+ $"?api_key={Tmdb.ApiKey}&language={_options.Language}";
|
||||
using var doc = await TryGetJsonAsync(url, cancellationToken);
|
||||
using var doc = await TryGetAsync(httpFactory, url, cancellationToken);
|
||||
if (doc is null)
|
||||
return null;
|
||||
var root = doc.RootElement;
|
||||
@@ -100,7 +101,7 @@ public sealed class TmdbMetadataProvider(
|
||||
var url =
|
||||
$"{Tmdb.BaseUrl}/tv/{externalId}/season/{season}"
|
||||
+ $"?api_key={Tmdb.ApiKey}&language={_options.Language}";
|
||||
using var doc = await TryGetJsonAsync(url, cancellationToken);
|
||||
using var doc = await TryGetAsync(httpFactory, url, cancellationToken);
|
||||
if (
|
||||
doc is null
|
||||
|| !doc.RootElement.TryGetProperty("episodes", out var episodes)
|
||||
@@ -116,46 +117,6 @@ public sealed class TmdbMetadataProvider(
|
||||
private string? StillUrl(string? path) =>
|
||||
string.IsNullOrEmpty(path) ? null : $"{Tmdb.ImageBaseUrl}/{Tmdb.StillSize}{path}";
|
||||
|
||||
/// <summary>GET+parse; бросает при не-2xx/сетевой ошибке (для поиска — чтобы показать сбой).</summary>
|
||||
private async Task<JsonDocument> GetJsonAsync(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
var client = httpFactory.CreateClient("metadata");
|
||||
using var response = await client.GetAsync(url, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
return await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>Как GetJsonAsync, но глотает ошибки в null (для get/episode — деградируем мягко).</summary>
|
||||
private async Task<JsonDocument?> TryGetJsonAsync(
|
||||
string url,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await GetJsonAsync(url, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is HttpRequestException or JsonException or TaskCanceledException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetString(JsonElement el, string name) =>
|
||||
el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String
|
||||
? v.GetString()
|
||||
: null;
|
||||
|
||||
private static int? GetInt(JsonElement el, string name) =>
|
||||
el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.Number
|
||||
? v.GetInt32()
|
||||
: null;
|
||||
|
||||
private static int? YearFrom(string? date) =>
|
||||
date is { Length: >= 4 } && int.TryParse(date.AsSpan(0, 4), out var y) ? y : null;
|
||||
|
||||
private static DateOnly? DateFrom(string? date) =>
|
||||
DateOnly.TryParse(date, CultureInfo.InvariantCulture, out var d) ? d : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user