Edit SanitizeUrl to handle also query parameters

modified:   Jellyfin.Plugin.TubeArchivistMetadata/Tasks/TAToJellyfinPlaylistsSyncTask.cs
	modified:   Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs
	modified:   Jellyfin.Plugin.TubeArchivistMetadata/Utils/Utils.cs
This commit is contained in:
REPLYNET\l.consoli
2025-12-02 12:31:44 +01:00
parent c2eebbe1a9
commit bc343dd0c8
3 changed files with 69 additions and 12 deletions
@@ -170,7 +170,15 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
} }
processedVideosCount += currentPlaylistVideos; processedVideosCount += currentPlaylistVideos;
progress.Report(processedVideosCount * 100 / totalVideosCount);
if (totalVideosCount == 0)
{
progress.Report(100);
}
else
{
progress.Report(processedVideosCount * 100 / totalVideosCount);
}
} }
} }
} }
@@ -219,7 +219,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
{ {
url = response.Headers.Location; url = response.Headers.Location;
_logger.LogInformation("{Message}", "Received redirect to: " + url); _logger.LogInformation("{Message}", "Received redirect to: " + url);
response = await client.GetAsync(url).ConfigureAwait(true); response = await client.GetAsync(Utils.SanitizeUrl(Plugin.Instance?.Configuration.TubeArchivistUrl + url)).ConfigureAwait(true);
} }
_logger.LogInformation("{Message}", url + ": " + response.StatusCode); _logger.LogInformation("{Message}", url + ": " + response.StatusCode);
@@ -238,6 +238,13 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
var nextPage = playlists.Paginate.CurrentPage + 1; var nextPage = playlists.Paginate.CurrentPage + 1;
var pagedUrl = new Uri(Utils.SanitizeUrl(Plugin.Instance?.Configuration.TubeArchivistUrl + playlistsEndpoint + "?page=" + nextPage)); var pagedUrl = new Uri(Utils.SanitizeUrl(Plugin.Instance?.Configuration.TubeArchivistUrl + playlistsEndpoint + "?page=" + nextPage));
response = await client.GetAsync(pagedUrl).ConfigureAwait(true); response = await client.GetAsync(pagedUrl).ConfigureAwait(true);
while (response.StatusCode == HttpStatusCode.Moved)
{
url = response.Headers.Location;
_logger.LogInformation("{Message}", "Received redirect to: " + url);
response = await client.GetAsync(Utils.SanitizeUrl(Plugin.Instance?.Configuration.TubeArchivistUrl + url)).ConfigureAwait(true);
}
_logger.LogInformation("{Message}", pagedUrl + ": " + response.StatusCode); _logger.LogInformation("{Message}", pagedUrl + ": " + response.StatusCode);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
@@ -258,6 +265,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
_logger.LogInformation("Pagination info: Current page {CurrentPage} / Last page {LastPage}, Total hits: {TotalHits}", playlists.Paginate.CurrentPage, playlists.Paginate.LastPage, playlists.Paginate.TotalHits); _logger.LogInformation("Pagination info: Current page {CurrentPage} / Last page {LastPage}, Total hits: {TotalHits}", playlists.Paginate.CurrentPage, playlists.Paginate.LastPage, playlists.Paginate.TotalHits);
} }
} }
else
{
_logger.LogCritical("Failed to retrieve page {PageNumber} of playlists during pagination.", nextPage);
break;
}
} }
} }
} }
@@ -1,8 +1,6 @@
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities
{ {
@@ -22,20 +20,59 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities
/// <returns>The URL string without spaces, doubled slashes and with a trailing slash.</returns> /// <returns>The URL string without spaces, doubled slashes and with a trailing slash.</returns>
public static string SanitizeUrl(string inputUrl) public static string SanitizeUrl(string inputUrl)
{ {
// Extract the schema part if (string.IsNullOrWhiteSpace(inputUrl))
Match schemaMatch = Regex.Match(inputUrl, @"^(?<schema>https?://)"); {
return string.Empty;
}
// Remove double slashes and spaces from the remaining part of the URL // Extract the schema part (http:// or https://)
string cleanedPath = Regex.Replace(inputUrl.Substring(schemaMatch.Length), @"[/\s]+", "/"); Match schemaMatch = Regex.Match(inputUrl, @"^(?<schema>https?://)", RegexOptions.IgnoreCase);
// If no schema found, treat whole string as the rest
int schemaLength = schemaMatch.Success ? schemaMatch.Length : 0;
// Separate the main part from query (?) and fragment (#)
string rest = inputUrl.Substring(schemaLength);
string pathPart = rest;
string queryAndFragment = string.Empty;
int qIndex = rest.IndexOf('?', StringComparison.Ordinal);
int fIndex = rest.IndexOf('#', StringComparison.Ordinal);
int splitIndex = -1;
if (qIndex >= 0 && fIndex >= 0)
{
splitIndex = Math.Min(qIndex, fIndex);
}
else if (qIndex >= 0)
{
splitIndex = qIndex;
}
else if (fIndex >= 0)
{
splitIndex = fIndex;
}
if (splitIndex >= 0)
{
pathPart = rest.Substring(0, splitIndex);
queryAndFragment = rest.Substring(splitIndex);
}
// Remove double slashes and spaces from the path part
string cleanedPath = Regex.Replace(pathPart, @"[/\s]+", "/");
// Remove slashes at the start // Remove slashes at the start
cleanedPath = cleanedPath.TrimStart('/'); cleanedPath = cleanedPath.TrimStart('/');
// Add a trailing slash if not already present // Add a trailing slash only when there are no query or fragment parts
cleanedPath = cleanedPath.TrimEnd('/') + "/"; if (string.IsNullOrEmpty(queryAndFragment))
{
cleanedPath = cleanedPath.TrimEnd('/') + "/";
}
// Combine the schema and cleaned path // Combine the schema and cleaned path and re-append query/fragment
string cleanedUrl = schemaMatch.Groups["schema"].Value + cleanedPath; string cleanedUrl = (schemaMatch.Success ? schemaMatch.Groups["schema"].Value : string.Empty) + cleanedPath + queryAndFragment;
return cleanedUrl; return cleanedUrl;
} }