Skip to content

Commit

Permalink
Merge branch 'kookxiang:master' into feat-collection
Browse files Browse the repository at this point in the history
  • Loading branch information
chu-shen authored Nov 21, 2024
2 parents 6f1dd98 + c21a37f commit 829e894
Show file tree
Hide file tree
Showing 41 changed files with 1,263 additions and 224 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/jellyfin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: 'Jellyfin Plugin'

on:
push:
branches:
- master
branches-ignore:
- release

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<PackageVersion Include="AnitomySharp.NET6" Version="0.5.1"/>
<PackageVersion Include="Fastenshtein" Version="1.0.10" />
<PackageVersion Include="FuzzySharp" Version="2.0.2" />
<PackageVersion Include="Jellyfin.Controller" Version="10.9.11" />
<PackageVersion Include="Jellyfin.Controller" Version="10.9.0" />
<PackageVersion Include="MediaBrowser.Server.Core" Version="4.9.0.14-beta" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.3.1" />
Expand Down
69 changes: 56 additions & 13 deletions Emby.Plugin.Bangumi/BangumiApi.Emby.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
Expand All @@ -13,19 +14,14 @@ namespace Jellyfin.Plugin.Bangumi;

public partial class BangumiApi(IHttpClient httpClient, OAuthStore store)
{
private static readonly JsonSerializerOptions Options = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

private static Plugin Plugin => Plugin.Instance!;

public IHttpClient GetHttpClient()
{
return httpClient;
}

private async Task<string> SendRequest(string method, HttpRequestOptions options)
private async Task<string> Send(string method, HttpRequestOptions options)
{
options.UserAgent = $"Jellyfin.Plugin.Bangumi/{Plugin.Version} (https://github.com/kookxiang/jellyfin-plugin-bangumi)";
options.TimeoutMs = Plugin.Configuration.RequestTimeout;
Expand All @@ -36,23 +32,70 @@ private async Task<string> SendRequest(string method, HttpRequestOptions options
return await stream.ReadToEndAsync();
}

private Task<T?> SendRequest<T>(string url, CancellationToken token)
private Task<T?> Get<T>(string url, CancellationToken token)
{
return SendRequest<T>(url, store.GetAvailable()?.AccessToken, token);
return Get<T>(url, store.GetAvailable()?.AccessToken, token);
}

private async Task<T?> SendRequest<T>(string url, string? accessToken, CancellationToken token)
private async Task<T?> Get<T>(string url, string? accessToken, CancellationToken token)
{
var options = new HttpRequestOptions { Url = url };
if (accessToken != null)
options.RequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var jsonString = await SendRequest("GET", options);
return JsonSerializer.Deserialize<T>(jsonString, Options);
var jsonString = await Send("GET", options);
return JsonSerializer.Deserialize<T>(jsonString, Constants.JsonSerializerOptions);
}

private async Task<string> Post(string url, HttpContent content, string? accessToken, CancellationToken token)
{
using var response = await httpClient.SendAsync(new HttpRequestOptions
{
Url = url,
RequestHttpContent = content,
RequestHeaders =
{
{ "Authorization", "Bearer " + accessToken }
},
UserAgent = $"Jellyfin.Plugin.Bangumi/{Plugin.Version} (https://github.com/kookxiang/jellyfin-plugin-bangumi)",
TimeoutMs = Plugin.Configuration.RequestTimeout,
ThrowOnErrorResponse = false
}, "POST");
if (response.StatusCode >= HttpStatusCode.MovedPermanently) await ServerException.ThrowFrom(response);
using var stream = new StreamReader(response.Content);
return await stream.ReadToEndAsync(token);
}

private Task<T?> Post<T>(string url, HttpContent content)
{
return Post<T>(url, content, null);
}

private Task<T?> Post<T>(string url, HttpContent content, string? accessToken)
{
return Post<T>(url, content, accessToken, CancellationToken.None);
}

private Task<T?> Post<T>(string url, HttpContent content, CancellationToken token)
{
return Post<T>(url, content, null, token);
}

private async Task<T?> Post<T>(string url, HttpContent content, string? accessToken, CancellationToken token)
{
var jsonString = await Post(url, content, accessToken, token);
return JsonSerializer.Deserialize<T>(jsonString, Constants.JsonSerializerOptions);
}

private async Task<string?> FollowRedirection(string url, CancellationToken token)
{
var options = new HttpRequestOptions { Url = url };
using var response = await httpClient.SendAsync(options, "GET");
return response.StatusCode is HttpStatusCode.MovedPermanently or HttpStatusCode.Redirect ? response.Headers.GetValueOrDefault("Location") : null;
}

public class JsonContent : StringContent
{
public JsonContent(object obj) : base(JsonSerializer.Serialize(obj, Options), Encoding.UTF8, "application/json")
public JsonContent(object obj) : base(JsonSerializer.Serialize(obj, Constants.JsonSerializerOptions), Encoding.UTF8, "application/json")
{
Headers.ContentType!.CharSet = null;
}
Expand Down
7 changes: 1 addition & 6 deletions Emby.Plugin.Bangumi/BangumiApi.Exception.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ public partial class BangumiApi
{
private class ServerException : Exception
{
private static readonly JsonSerializerOptions Options = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

public readonly HttpStatusCode StatusCode;

private ServerException(HttpStatusCode status, string message) : base(message)
Expand All @@ -31,7 +26,7 @@ public static async Task ThrowFrom(HttpResponseInfo response)
{
using var stream = new StreamReader(response.Content);
content = await stream.ReadToEndAsync();
var result = JsonSerializer.Deserialize<Response>(content, Options);
var result = JsonSerializer.Deserialize<Response>(content, Constants.JsonSerializerOptions);
if (result?.Title != null)
exception = new ServerException(response.StatusCode, $"{result.Title}: {result.Description}");
}
Expand Down
7 changes: 6 additions & 1 deletion Emby.Plugin.Bangumi/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Text.Json;

namespace Jellyfin.Plugin.Bangumi;

public static class Constants
Expand All @@ -10,5 +12,8 @@ public static class Constants

public const string Language = "zh";

public const string HtmlLineBreak = "<br>";
public static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
}
2 changes: 1 addition & 1 deletion Emby.Plugin.Bangumi/Emby.Plugin.Bangumi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<Compile Include="..\Jellyfin.Plugin.Bangumi\OAuth\*.cs" Exclude="..\Jellyfin.Plugin.Bangumi\OAuth\OAuthController.cs">
<Link>OAuth\*.cs</Link>
</Compile>
<Compile Include="..\Jellyfin.Plugin.Bangumi\ScheduledTask\*.cs">
<Compile Include="..\Jellyfin.Plugin.Bangumi\ScheduledTask\*.cs" Exclude="..\Jellyfin.Plugin.Bangumi\ScheduledTask\ArchiveDownloadTask.cs">
<Link>ScheduledTask\*.cs</Link>
</Compile>
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Emby.Plugin.Bangumi/OAuth/OAuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class OAuthController(BangumiApi api, OAuthStore store, ILogger log, ISes

private static string? _oAuthPath;

public IRequest Request { get; set; }
public IRequest Request { get; set; } = null!;

public async Task<object?> Get(OAuthState oAuthState)
{
Expand Down Expand Up @@ -164,7 +164,7 @@ public async Task Get(OAuth oAuth)
return;
}

var result = JsonSerializer.Deserialize<OAuthUser>(responseBody)!;
var result = JsonSerializer.Deserialize<OAuthUser>(responseBody, Constants.JsonSerializerOptions)!;
result.EffectiveTime = DateTime.Now;
await result.GetProfile(api);
log.Info($"UserName: {result.NickName}, ProfileUrl: {result.ProfileUrl}");
Expand Down
48 changes: 48 additions & 0 deletions Jellyfin.Plugin.Bangumi/Archive/ArchiveController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Jellyfin.Plugin.Bangumi.Archive;

[ApiController]
[Route("Plugins/Bangumi/Archive")]
public class OAuthController(ArchiveData archive)
: ControllerBase
{
[HttpGet("Status")]
[Authorize]
public Dictionary<string, object?> Status()
{
var totalSize = 0L;
DateTime? lastModifyTime = null;

var directory = new DirectoryInfo(archive.BasePath);
foreach (var info in directory.GetFileSystemInfos("*", SearchOption.AllDirectories))
{
if (lastModifyTime == null)
lastModifyTime = info.LastWriteTime;
else if (info.LastWriteTime.CompareTo(lastModifyTime) > 0)
lastModifyTime = info.LastWriteTime;
if (info is FileInfo fileInfo)
totalSize += fileInfo.Length;
}

return new Dictionary<string, object?>
{
["path"] = archive.BasePath,
["size"] = totalSize,
["time"] = lastModifyTime
};
}

[HttpDelete("Store")]
[Authorize]
public bool Delete()
{
Directory.Delete(archive.BasePath, true);
Directory.CreateDirectory(archive.BasePath);
return false;
}
}
32 changes: 32 additions & 0 deletions Jellyfin.Plugin.Bangumi/Archive/ArchiveData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.IO;
using Jellyfin.Plugin.Bangumi.Archive.Data;
using Jellyfin.Plugin.Bangumi.Archive.Relation;
using MediaBrowser.Common.Configuration;

namespace Jellyfin.Plugin.Bangumi.Archive;

public class ArchiveData(IApplicationPaths paths)
{
public readonly string BasePath = Path.Join(paths.DataPath, "bangumi", "archive");

public readonly string TempPath = Path.Join(paths.DataPath, "bangumi", "archive", "temp");

public List<IArchiveStore> Stores =>
[
Character,
Subject,
Episode,
Person
];

public ArchiveStore<Character> Character => new(BasePath, "character.jsonlines");

public ArchiveStore<Subject> Subject => new(BasePath, "subject.jsonlines");

public ArchiveStore<Episode> Episode => new(BasePath, "episode.jsonlines");

public ArchiveStore<Person> Person => new(BasePath, "person.jsonlines");

public SubjectEpisodeRelation SubjectEpisode => new(this);
}
Loading

0 comments on commit 829e894

Please sign in to comment.