mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-01-06 14:49:30 -06:00
stupid anilist
This commit is contained in:
63
MetaNodes/AniList/AniListAiringSchedule.cs
Normal file
63
MetaNodes/AniList/AniListAiringSchedule.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace MetaNodes.AniList;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the airing schedule for a specific anime, containing a list of episodes and their air dates.
|
||||
/// </summary>
|
||||
public class AniListAirScheduleResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the airing schedule for the anime.
|
||||
/// </summary>
|
||||
public AniListAiringSchedule AiringSchedule { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the airing schedule for a specific anime, containing a list of episodes and their air dates.
|
||||
/// </summary>
|
||||
public class AniListAiringSchedule
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the list of edges, where each edge contains information about an episode's airing schedule.
|
||||
/// </summary>
|
||||
public List<AniListAiringScheduleEdge> Edges { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an edge in the airing schedule, containing a node with the episode information.
|
||||
/// </summary>
|
||||
public class AniListAiringScheduleEdge
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node that contains information about a specific episode.
|
||||
/// </summary>
|
||||
public AniListAiringScheduleNode Node { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an individual episode's airing information.
|
||||
/// </summary>
|
||||
public class AniListAiringScheduleNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the episode number.
|
||||
/// </summary>
|
||||
public int Episode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Unix timestamp representing the airing time of the episode.
|
||||
/// </summary>
|
||||
public long AiringAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the airing date and time of the episode as a <see cref="DateTimeOffset"/> object, based on the Unix timestamp <see cref="AiringAt"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Converts the <see cref="AiringAt"/> Unix timestamp to a <see cref="DateTimeOffset"/> in UTC format.
|
||||
/// </remarks>
|
||||
public DateTimeOffset AirDate => DateTimeOffset.FromUnixTimeSeconds(AiringAt);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class AniListInterface(NodeParameters _args)
|
||||
/// </summary>
|
||||
/// <param name="showName">The name of the anime show to look up.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="AniListShowInfo"/> object.</returns>
|
||||
public async Task<AniListShowInfo> FetchShowInfo(string showName)
|
||||
public async Task<AniListShowInfo?> FetchShowInfo(string showName)
|
||||
{
|
||||
var query = @"
|
||||
query ($search: String) {
|
||||
@@ -47,34 +47,25 @@ public class AniListInterface(NodeParameters _args)
|
||||
var response = await _HttpClient.PostAsync(AniListGraphQLUrl, content);
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var data = JsonSerializer.Deserialize<AniListShowResponse>(jsonResponse, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
});
|
||||
|
||||
var media = data?.Data?.Media;
|
||||
|
||||
if (media != null)
|
||||
{
|
||||
return new AniListShowInfo
|
||||
{
|
||||
Title = media.Title.English?.EmptyAsNull() ??
|
||||
media.Title.Native?.EmptyAsNull() ?? media.Title.Romaji,
|
||||
TitleRomaji = media.Title.Romaji,
|
||||
TitleEnglish = media.Title.English,
|
||||
TitleNative = media.Title.Native,
|
||||
Description = media.Description,
|
||||
Year = media.StartDate.Year,
|
||||
Score = media.AverageScore
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
if (response.IsSuccessStatusCode == false)
|
||||
{
|
||||
_args.Logger?.ELog($"Error fetching data from AniList: {jsonResponse}");
|
||||
return null;
|
||||
}
|
||||
|
||||
var media = UnwrapResponse<AniListShowInfoResponse>(jsonResponse);
|
||||
|
||||
return new AniListShowInfo
|
||||
{
|
||||
Title = media.Title.English?.EmptyAsNull() ??
|
||||
media.Title.Native?.EmptyAsNull() ?? media.Title.Romaji,
|
||||
TitleRomaji = media.Title.Romaji,
|
||||
TitleEnglish = media.Title.English,
|
||||
TitleNative = media.Title.Native,
|
||||
Description = media.Description,
|
||||
Year = media.StartDate.Year,
|
||||
Score = media.AverageScore
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -83,118 +74,142 @@ public class AniListInterface(NodeParameters _args)
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches episode information from AniList based on the provided show name.
|
||||
/// </summary>
|
||||
/// <param name="showName">The name of the anime show.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="AniListEpisodeInfo"/> objects.</returns>
|
||||
public async Task<List<AniListEpisodeInfo>> FetchEpisode(string showName)
|
||||
{
|
||||
var queryAiringSchedule = @"
|
||||
query ($search: String) {
|
||||
Media(search: $search, type: ANIME) {
|
||||
airingSchedule {
|
||||
edges {
|
||||
node {
|
||||
episode
|
||||
airingAt
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Fetches episode information from AniList based on the provided show name.
|
||||
/// </summary>
|
||||
/// <param name="showName">The name of the anime show.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="AniListEpisodeInfo"/> objects.</returns>
|
||||
public async Task<List<AniListEpisodeInfo>> FetchEpisode(string showName)
|
||||
{
|
||||
var queryAiringSchedule = @"
|
||||
query ($search: String) {
|
||||
Media(search: $search, type: ANIME) {
|
||||
airingSchedule {
|
||||
edges {
|
||||
node {
|
||||
episode
|
||||
airingAt
|
||||
}
|
||||
id
|
||||
}
|
||||
}";
|
||||
|
||||
var variablesAiringSchedule = new { search = showName };
|
||||
var jsonRequestAiringSchedule = JsonSerializer.Serialize(new { query = queryAiringSchedule, variables = variablesAiringSchedule });
|
||||
|
||||
var episodeDetails = new List<AniListEpisodeInfo>();
|
||||
|
||||
try
|
||||
{
|
||||
var content = new StringContent(jsonRequestAiringSchedule, Encoding.UTF8, "application/json");
|
||||
var responseAiringSchedule = await _HttpClient.PostAsync(AniListGraphQLUrl, content);
|
||||
var jsonResponseAiringSchedule = await responseAiringSchedule.Content.ReadAsStringAsync();
|
||||
|
||||
if (responseAiringSchedule.IsSuccessStatusCode)
|
||||
{
|
||||
// var dataAiringSchedule = JsonSerializer.Deserialize<AniListAiringScheduleResponse>(jsonResponseAiringSchedule, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
//
|
||||
// var media = dataAiringSchedule?.Data?.Media;
|
||||
//
|
||||
// if (media != null)
|
||||
// {
|
||||
// int mediaId = media.Id;
|
||||
//
|
||||
// var queryEpisodeDetails = @"
|
||||
// query ($id: Int) {
|
||||
// Media(id: $id) {
|
||||
// episodes {
|
||||
// episode
|
||||
// title {
|
||||
// romaji
|
||||
// english
|
||||
// native
|
||||
// }
|
||||
// description
|
||||
// }
|
||||
// }
|
||||
// }";
|
||||
//
|
||||
// var variablesEpisodeDetails = new { id = mediaId };
|
||||
// var jsonRequestEpisodeDetails = JsonSerializer.Serialize(new { query = queryEpisodeDetails, variables = variablesEpisodeDetails });
|
||||
//
|
||||
// var contentEpisodeDetails = new StringContent(jsonRequestEpisodeDetails, Encoding.UTF8, "application/json");
|
||||
// var responseEpisodeDetails = await _HttpClient.PostAsync(AniListGraphQLUrl, contentEpisodeDetails);
|
||||
// var jsonResponseEpisodeDetails = await responseEpisodeDetails.Content.ReadAsStringAsync();
|
||||
//
|
||||
// if (responseEpisodeDetails.IsSuccessStatusCode)
|
||||
// {
|
||||
// var dataEpisodeDetails = JsonSerializer.Deserialize<AniListEpisodeResponse>(jsonResponseEpisodeDetails, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
//
|
||||
// var episodes = dataEpisodeDetails?.Data?.Media?.Episodes;
|
||||
// if (episodes != null)
|
||||
// {
|
||||
// foreach (var episode in episodes)
|
||||
// {
|
||||
// episodeDetails.Add(new AniListEpisodeInfo
|
||||
// {
|
||||
// EpisodeNumber = episode.Episode,
|
||||
// Title = episode.Title?.Romaji ?? episode.Title?.English ?? episode.Title?.Native,
|
||||
// Description = episode.Description
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
_args.Logger?.ELog($"Error fetching data from AniList: {jsonResponseAiringSchedule}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
id
|
||||
}
|
||||
}";
|
||||
|
||||
var variablesAiringSchedule = new { search = showName };
|
||||
var jsonRequestAiringSchedule = JsonSerializer.Serialize(new { query = queryAiringSchedule, variables = variablesAiringSchedule });
|
||||
|
||||
var episodeDetails = new List<AniListEpisodeInfo>();
|
||||
|
||||
try
|
||||
{
|
||||
// Send the request to AniList for the airing schedule
|
||||
var content = new StringContent(jsonRequestAiringSchedule, Encoding.UTF8, "application/json");
|
||||
var responseAiringSchedule = await _HttpClient.PostAsync(AniListGraphQLUrl, content);
|
||||
var jsonResponseAiringSchedule = await responseAiringSchedule.Content.ReadAsStringAsync();
|
||||
|
||||
if (responseAiringSchedule.IsSuccessStatusCode == false)
|
||||
{
|
||||
_args.Logger?.ELog($"Exception occurred: {ex.Message}");
|
||||
_args.Logger?.ELog($"Error fetching data from AniList: {jsonResponseAiringSchedule}");
|
||||
return new List<AniListEpisodeInfo>();
|
||||
}
|
||||
|
||||
return episodeDetails;
|
||||
// Use UnwrapResponse to directly extract AniListAiringSchedule from the JSON response
|
||||
var airSchedule = UnwrapResponse<AniListAirScheduleResponse>(jsonResponseAiringSchedule);
|
||||
|
||||
|
||||
// Now we can fetch the Media Id
|
||||
var mediaId = airSchedule.Id;
|
||||
|
||||
if (mediaId == 0)
|
||||
{
|
||||
_args.Logger?.ELog("No media ID found for the show.");
|
||||
return new List<AniListEpisodeInfo>();
|
||||
}
|
||||
|
||||
if (airSchedule?.AiringSchedule?.Edges == null)
|
||||
{
|
||||
_args.Logger?.ELog("Failed to deserialize the airing schedule data.");
|
||||
return new List<AniListEpisodeInfo>();
|
||||
}
|
||||
|
||||
// Query episode details based on the media ID
|
||||
var queryEpisodeDetails = @"
|
||||
query ($id: Int) {
|
||||
Media(id: $id) {
|
||||
episodes {
|
||||
episode
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
native
|
||||
}
|
||||
description
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
var variablesEpisodeDetails = new { id = mediaId };
|
||||
var jsonRequestEpisodeDetails = JsonSerializer.Serialize(new { query = queryEpisodeDetails, variables = variablesEpisodeDetails });
|
||||
|
||||
var contentEpisodeDetails = new StringContent(jsonRequestEpisodeDetails, Encoding.UTF8, "application/json");
|
||||
var responseEpisodeDetails = await _HttpClient.PostAsync(AniListGraphQLUrl, contentEpisodeDetails);
|
||||
var jsonResponseEpisodeDetails = await responseEpisodeDetails.Content.ReadAsStringAsync();
|
||||
|
||||
if (responseEpisodeDetails.IsSuccessStatusCode == false)
|
||||
{
|
||||
_args.Logger?.ELog($"Error fetching episode details from AniList: {jsonResponseEpisodeDetails}");
|
||||
return new List<AniListEpisodeInfo>();
|
||||
}
|
||||
|
||||
// Deserialize episode details
|
||||
// var dataEpisodeDetails = JsonSerializer.Deserialize<AniListEpisodeResponse>(
|
||||
// jsonResponseEpisodeDetails, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
// var episodes = dataEpisodeDetails?.Data?.Media?.Episodes;
|
||||
//
|
||||
// if (episodes != null)
|
||||
// {
|
||||
// foreach (var episode in episodes)
|
||||
// {
|
||||
// episodeDetails.Add(new AniListEpisodeInfo
|
||||
// {
|
||||
// EpisodeNumber = episode.Episode,
|
||||
// Title = episode.Title?.Romaji ?? episode.Title?.English ?? episode.Title?.Native,
|
||||
// Description = episode.Description
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Response class for show information.
|
||||
/// </summary>
|
||||
public class AniListShowResponse
|
||||
catch (Exception ex)
|
||||
{
|
||||
public AniListShowData Data { get; set; }
|
||||
_args.Logger?.ELog($"Exception occurred: {ex.Message}");
|
||||
}
|
||||
|
||||
return episodeDetails;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Data class for show information.
|
||||
/// Unwraps a nested JSON response from AniList API, automatically finding the object under data.Media.
|
||||
/// </summary>
|
||||
public class AniListShowData
|
||||
/// <typeparam name="T">The type to deserialize the unwrapped JSON into.</typeparam>
|
||||
/// <param name="json">The raw JSON string.</param>
|
||||
/// <returns>The unwrapped object of type <typeparamref name="T"/>.</returns>
|
||||
public static T UnwrapResponse<T>(string json)
|
||||
{
|
||||
public AniListMediaData Media { get; set; }
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
|
||||
// Navigate to data.Media
|
||||
if (!doc.RootElement.TryGetProperty("data", out var dataElement) ||
|
||||
!dataElement.TryGetProperty("Media", out var mediaElement))
|
||||
{
|
||||
throw new InvalidOperationException("JSON does not contain 'data.Media' structure.");
|
||||
}
|
||||
|
||||
return mediaElement.Deserialize<T>(new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace MetaNodes.AniList;
|
||||
/// <summary>
|
||||
/// Represents the media data of an anime show from AniList API.
|
||||
/// </summary>
|
||||
public class AniListMediaData
|
||||
public class AniListShowInfoResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the title information of the media.
|
||||
|
||||
Reference in New Issue
Block a user