mirror of
https://github.com/jellyfin/jellyfin-plugin-opensubtitles.git
synced 2024-11-23 06:09:51 +00:00
114 lines
3.7 KiB
C#
114 lines
3.7 KiB
C#
using System;
|
|
using System.Buffers.Binary;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler;
|
|
|
|
/// <summary>
|
|
/// Http util helper.
|
|
/// </summary>
|
|
public class OpenSubtitlesRequestHelper
|
|
{
|
|
private readonly IHttpClientFactory _clientFactory;
|
|
private readonly string _version;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="OpenSubtitlesRequestHelper"/> class.
|
|
/// </summary>
|
|
/// <param name="factory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
/// <param name="version">The plugin version.</param>
|
|
public OpenSubtitlesRequestHelper(IHttpClientFactory factory, string version)
|
|
{
|
|
_clientFactory = factory;
|
|
_version = version;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the current instance.
|
|
/// </summary>
|
|
public static OpenSubtitlesRequestHelper? Instance { get; set; }
|
|
|
|
/// <summary>
|
|
/// Calculates: size + 64bit chksum of the first and last 64k (even if they overlap because the file is smaller than 128k).
|
|
/// </summary>
|
|
/// <param name="input">The input stream.</param>
|
|
/// <returns>The hash as Hexadecimal string.</returns>
|
|
public static string ComputeHash(Stream input)
|
|
{
|
|
const int HashLength = 8; // 64 bit hash
|
|
const long HashPos = 64 * 1024; // 64k
|
|
|
|
long streamsize = input.Length;
|
|
ulong hash = (ulong)streamsize;
|
|
|
|
Span<byte> buffer = stackalloc byte[HashLength];
|
|
while (input.Position < HashPos && input.Read(buffer) > 0)
|
|
{
|
|
hash += BinaryPrimitives.ReadUInt64LittleEndian(buffer);
|
|
}
|
|
|
|
input.Seek(-HashPos, SeekOrigin.End);
|
|
while (input.Read(buffer) > 0)
|
|
{
|
|
hash += BinaryPrimitives.ReadUInt64LittleEndian(buffer);
|
|
}
|
|
|
|
BinaryPrimitives.WriteUInt64BigEndian(buffer, hash);
|
|
return Convert.ToHexString(buffer).ToLowerInvariant();
|
|
}
|
|
|
|
internal async Task<(string body, Dictionary<string, string> headers, HttpStatusCode statusCode)> SendRequestAsync(
|
|
string url,
|
|
HttpMethod method,
|
|
object? body,
|
|
Dictionary<string, string> headers,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var client = _clientFactory.CreateClient("Default");
|
|
|
|
HttpContent? content = null;
|
|
if (method != HttpMethod.Get && body is not null)
|
|
{
|
|
content = JsonContent.Create(body);
|
|
}
|
|
|
|
using var request = new HttpRequestMessage
|
|
{
|
|
Method = method,
|
|
RequestUri = new Uri(url),
|
|
Content = content,
|
|
Headers =
|
|
{
|
|
UserAgent = { new ProductInfoHeaderValue("Jellyfin-Plugin-OpenSubtitles", _version) },
|
|
Accept = { new MediaTypeWithQualityHeaderValue("*/*") },
|
|
}
|
|
};
|
|
|
|
foreach (var (key, value) in headers)
|
|
{
|
|
if (string.Equals(key, "authorization", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", value);
|
|
}
|
|
else
|
|
{
|
|
request.Headers.Add(key, value);
|
|
}
|
|
}
|
|
|
|
var result = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
|
var resHeaders = result.Headers.ToDictionary(x => x.Key.ToLowerInvariant(), x => x.Value.First());
|
|
var resBody = await result.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
|
|
|
|
return (resBody, resHeaders, result.StatusCode);
|
|
}
|
|
}
|