From cd25a34a55167baf6add27cc2dfc7b65cafc9cf3 Mon Sep 17 00:00:00 2001 From: OLC Date: Sun, 21 Sep 2025 20:18:58 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0OpenApi=E7=B1=BB=E4=BB=A5?= =?UTF-8?q?=E6=94=AF=E6=8C=81Baidu=E5=92=8CPixiv=20API=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=8E=B7=E5=8F=96=E6=97=A5=E5=8E=86=E5=92=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=BF=A1=E6=81=AF=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E6=9B=B4=E6=96=B0=E7=9B=B8=E5=85=B3=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E9=A1=B9=E5=92=8C=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RitsukageBotForDiscord.sln.DotSettings | 3 + .../OpenApi/{ => Baidu}/OpenApi.Baidu.cs | 19 +- .../{ => Baidu/Structs}/BaiduCalendarData.cs | 2 +- .../Library/OpenApi/OpenApi.cs | 32 ++- .../Library/OpenApi/Pixiv/OpenApi.Pixiv.cs | 126 +++++++++ .../OpenApi/Pixiv/Structs/PixivIllustData.cs | 248 ++++++++++++++++++ .../OpenApi/Pixiv/Structs/PixivUserData.cs | 74 ++++++ .../AI/AiInteractions.Preprocessing.cs | 80 +++++- .../Modules/ImageInteractions.cs | 6 +- .../AutoBroadcastTimeScheduleTask.cs | 4 +- .../Modules/TimeInteractions.cs | 4 +- src/RitsukageBotForDiscord/Program.cs | 4 +- .../RitsukageBotForDiscord.csproj | 60 ++--- 13 files changed, 610 insertions(+), 52 deletions(-) rename src/RitsukageBotForDiscord/Library/OpenApi/{ => Baidu}/OpenApi.Baidu.cs (79%) rename src/RitsukageBotForDiscord/Library/OpenApi/{ => Baidu/Structs}/BaiduCalendarData.cs (98%) create mode 100644 src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs create mode 100644 src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivIllustData.cs create mode 100644 src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivUserData.cs diff --git a/RitsukageBotForDiscord.sln.DotSettings b/RitsukageBotForDiscord.sln.DotSettings index a8397d5..33bcc64 100644 --- a/RitsukageBotForDiscord.sln.DotSettings +++ b/RitsukageBotForDiscord.sln.DotSettings @@ -1,14 +1,17 @@  True True + True True True True True + True True True True True + True True True True diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.Baidu.cs b/src/RitsukageBotForDiscord/Library/OpenApi/Baidu/OpenApi.Baidu.cs similarity index 79% rename from src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.Baidu.cs rename to src/RitsukageBotForDiscord/Library/OpenApi/Baidu/OpenApi.Baidu.cs index 021c436..9c61c8a 100644 --- a/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.Baidu.cs +++ b/src/RitsukageBotForDiscord/Library/OpenApi/Baidu/OpenApi.Baidu.cs @@ -1,25 +1,30 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using RitsukageBot.Library.OpenApi.Baidu.Structs; using RitsukageBot.Library.Utils; -namespace RitsukageBot.Library.OpenApi +namespace RitsukageBot.Library.OpenApi.Baidu { - public partial class OpenApi + /// + /// OpenApi.Baidu + /// + public static class OpenApiBaidu { /// /// Get calendar information from Baidu /// Return the calendar information from the previous month to the next month /// + /// /// /// /// - public static async Task GetCalendarAsync(DateTimeOffset date, + public static async Task GetCalendarAsync(this OpenApi instance, DateTimeOffset date, HttpClient? httpClient = null) { var cacheKey = $"Baidu_Calendar_{date.ToLocalTime():yyyy_MM}"; - if (_cacheProvider is not null) + if (instance.CacheProvider is not null) { - var recordInfo = await _cacheProvider.GetOrDefaultAsync(cacheKey).ConfigureAwait(false); + var recordInfo = await instance.CacheProvider.GetOrDefaultAsync(cacheKey).ConfigureAwait(false); if (recordInfo is not null) return JsonConvert.DeserializeObject(recordInfo)!; } @@ -45,8 +50,8 @@ public static async Task GetCalendarAsync(DateTimeOffset dat var calendar = almanac.ToObject(); var resultData = calendar is not { Length: > 0 } ? [] : calendar; - if (_cacheProvider is not null) - await _cacheProvider.SetAsync(cacheKey, JsonConvert.SerializeObject(resultData), new() + if (instance.CacheProvider is not null) + await instance.CacheProvider.SetAsync(cacheKey, JsonConvert.SerializeObject(resultData), new() { Duration = TimeSpan.FromDays(1), FailSafeMaxDuration = TimeSpan.FromDays(3), diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/BaiduCalendarData.cs b/src/RitsukageBotForDiscord/Library/OpenApi/Baidu/Structs/BaiduCalendarData.cs similarity index 98% rename from src/RitsukageBotForDiscord/Library/OpenApi/BaiduCalendarData.cs rename to src/RitsukageBotForDiscord/Library/OpenApi/Baidu/Structs/BaiduCalendarData.cs index e69dc64..e0f5577 100644 --- a/src/RitsukageBotForDiscord/Library/OpenApi/BaiduCalendarData.cs +++ b/src/RitsukageBotForDiscord/Library/OpenApi/Baidu/Structs/BaiduCalendarData.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace RitsukageBot.Library.OpenApi +namespace RitsukageBot.Library.OpenApi.Baidu.Structs { /// /// Baidu calendar day diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs b/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs index 076273c..3b54dc7 100644 --- a/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs +++ b/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs @@ -1,3 +1,4 @@ +using Microsoft.Extensions.Logging; using ZiggyCreatures.Caching.Fusion; namespace RitsukageBot.Library.OpenApi @@ -5,21 +6,42 @@ namespace RitsukageBot.Library.OpenApi /// /// OpenApi /// - public partial class OpenApi + public class OpenApi { - private static IFusionCache? _cacheProvider; + private static readonly Lazy OpenApiInstance = new(); private OpenApi() { } /// - /// Get cache provider + /// Cache provider + /// + public IFusionCache? CacheProvider { get; private set; } + + public ILogger Logger { get; private set; } + + /// + /// Instance of OpenApi + /// + public static OpenApi Instance => OpenApiInstance.Value; + + /// + /// Set cache provider /// /// - public static void SetCacheProvider(IFusionCache cacheProvider) + public void SetCacheProvider(IFusionCache cacheProvider) + { + CacheProvider = cacheProvider; + } + + /// + /// Set logger + /// + /// + public void SetLogger(ILogger logger) { - _cacheProvider = cacheProvider; + Logger = logger; } } } \ No newline at end of file diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs new file mode 100644 index 0000000..665ce3f --- /dev/null +++ b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs @@ -0,0 +1,126 @@ +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using RitsukageBot.Library.OpenApi.Pixiv.Structs; +using RitsukageBot.Library.Utils; + +namespace RitsukageBot.Library.OpenApi.Pixiv +{ + /// + /// OpenApi.Pixiv + /// + public static class OpenApiPixiv + { + /// + /// 获取Pixiv用户信息 + /// + /// OpenApi实例 + /// 用户ID + /// HTTP客户端 + /// 用户信息 + public static async Task GetPixivUserAsync(this OpenApi instance, string userId, + HttpClient? httpClient = null) + { + var cacheKey = $"Pixiv_User_{userId}"; + if (instance.CacheProvider is not null) + { + var recordInfo = await instance.CacheProvider.GetOrDefaultAsync(cacheKey).ConfigureAwait(false); + if (recordInfo is not null) + { + var cachedResponse = JsonConvert.DeserializeObject(recordInfo); + if (cachedResponse is not null && !cachedResponse.Error) + return cachedResponse.Body; + } + } + + httpClient ??= NetworkUtility.GetHttpClient(); + + if (!httpClient.DefaultRequestHeaders.Contains("Referer")) + httpClient.DefaultRequestHeaders.Add("Referer", "https://www.pixiv.net/"); + + try + { + var response = await httpClient.GetAsync($"https://www.pixiv.net/ajax/user/{userId}") + .ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var pixivResponse = JsonConvert.DeserializeObject(responseString); + + if (pixivResponse is not null && !pixivResponse.Error) + { + if (instance.CacheProvider is not null) + await instance.CacheProvider.SetAsync(cacheKey, responseString, new() + { + Duration = TimeSpan.FromHours(6), + FailSafeMaxDuration = TimeSpan.FromDays(1), + }).ConfigureAwait(false); + + return pixivResponse.Body; + } + } + catch (Exception ex) + { + instance.Logger.LogError( + "Failed to get Pixiv user info (ID: {UserId}): {Message}", userId, ex.Message); + } + + return null; + } + + /// + /// 获取Pixiv插画信息 + /// + /// OpenApi实例 + /// 插画ID + /// HTTP客户端 + /// 插画信息 + public static async Task GetPixivIllustAsync(this OpenApi instance, string illustId, + HttpClient? httpClient = null) + { + var cacheKey = $"Pixiv_Illust_{illustId}"; + if (instance.CacheProvider is not null) + { + var recordInfo = await instance.CacheProvider.GetOrDefaultAsync(cacheKey).ConfigureAwait(false); + if (recordInfo is not null) + { + var cachedResponse = JsonConvert.DeserializeObject(recordInfo); + if (cachedResponse is not null && !cachedResponse.Error) + return cachedResponse.Body; + } + } + + httpClient ??= NetworkUtility.GetHttpClient(); + + if (!httpClient.DefaultRequestHeaders.Contains("Referer")) + httpClient.DefaultRequestHeaders.Add("Referer", "https://www.pixiv.net/"); + + try + { + var response = await httpClient.GetAsync($"https://www.pixiv.net/ajax/illust/{illustId}") + .ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var pixivResponse = JsonConvert.DeserializeObject(responseString); + + if (pixivResponse is not null && !pixivResponse.Error) + { + if (instance.CacheProvider is not null) + await instance.CacheProvider.SetAsync(cacheKey, responseString, new() + { + Duration = TimeSpan.FromHours(12), + FailSafeMaxDuration = TimeSpan.FromDays(3), + }).ConfigureAwait(false); + + return pixivResponse.Body; + } + } + catch (Exception ex) + { + instance.Logger.LogError( + "Failed to get Pixiv illust info (ID: {IllustId}): {Message}", illustId, ex.Message); + } + + return null; + } + } +} + diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivIllustData.cs b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivIllustData.cs new file mode 100644 index 0000000..836fafd --- /dev/null +++ b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivIllustData.cs @@ -0,0 +1,248 @@ +using Newtonsoft.Json; + +namespace RitsukageBot.Library.OpenApi.Pixiv.Structs +{ + /// + /// Pixiv插画信息响应 + /// + /// + /// + /// + public record PixivIllustResponse( + [property: JsonProperty("error")] bool Error, + [property: JsonProperty("message")] string Message, + [property: JsonProperty("body")] PixivIllustData Body + ); + + /// + /// Pixiv插画数据 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public record PixivIllustData( + [property: JsonProperty("illustId")] string IllustId, + [property: JsonProperty("illustTitle")] string IllustTitle, + [property: JsonProperty("illustComment")] string IllustComment, + [property: JsonProperty("id")] string Id, + [property: JsonProperty("title")] string Title, + [property: JsonProperty("description")] string Description, + [property: JsonProperty("illustType")] int IllustType, + [property: JsonProperty("createDate")] string CreateDate, + [property: JsonProperty("uploadDate")] string UploadDate, + [property: JsonProperty("restrict")] int Restrict, + [property: JsonProperty("xRestrict")] int XRestrict, + [property: JsonProperty("sl")] int Sl, + [property: JsonProperty("urls")] PixivIllustUrls Urls, + [property: JsonProperty("tags")] PixivIllustTags Tags, + [property: JsonProperty("alt")] string Alt, + [property: JsonProperty("userId")] string UserId, + [property: JsonProperty("userName")] string UserName, + [property: JsonProperty("userAccount")] string UserAccount, + [property: JsonProperty("userIllusts")] Dictionary UserIllusts, + [property: JsonProperty("likeData")] bool LikeData, + [property: JsonProperty("width")] int Width, + [property: JsonProperty("height")] int Height, + [property: JsonProperty("pageCount")] int PageCount, + [property: JsonProperty("bookmarkCount")] int BookmarkCount, + [property: JsonProperty("likeCount")] int LikeCount, + [property: JsonProperty("commentCount")] int CommentCount, + [property: JsonProperty("responseCount")] int ResponseCount, + [property: JsonProperty("viewCount")] int ViewCount, + [property: JsonProperty("bookStyle")] string BookStyle, + [property: JsonProperty("isHowto")] bool IsHowto, + [property: JsonProperty("isOriginal")] bool IsOriginal, + [property: JsonProperty("imageResponseOutData")] object[] ImageResponseOutData, + [property: JsonProperty("imageResponseData")] object[] ImageResponseData, + [property: JsonProperty("imageResponseCount")] int ImageResponseCount, + [property: JsonProperty("pollData")] object? PollData, + [property: JsonProperty("seriesNavData")] object? SeriesNavData, + [property: JsonProperty("descriptionBoothId")] object? DescriptionBoothId, + [property: JsonProperty("descriptionYoutubeId")] object? DescriptionYoutubeId, + [property: JsonProperty("comicPromotion")] object? ComicPromotion, + [property: JsonProperty("fanboxPromotion")] object? FanboxPromotion, + [property: JsonProperty("contestBanners")] object[] ContestBanners, + [property: JsonProperty("isBookmarkable")] bool IsBookmarkable, + [property: JsonProperty("bookmarkData")] object? BookmarkData, + [property: JsonProperty("contestData")] object? ContestData, + [property: JsonProperty("zoneConfig")] object? ZoneConfig, + [property: JsonProperty("extraData")] object? ExtraData, + [property: JsonProperty("titleCaptionTranslation")] PixivTitleCaptionTranslation TitleCaptionTranslation, + [property: JsonProperty("isUnlisted")] bool IsUnlisted, + [property: JsonProperty("request")] object? Request, + [property: JsonProperty("commentOff")] int CommentOff, + [property: JsonProperty("aiType")] int AiType, + [property: JsonProperty("reuploadDate")] object? ReuploadDate, + [property: JsonProperty("locationMask")] bool LocationMask, + [property: JsonProperty("commissionLinkHidden")] bool CommissionLinkHidden, + [property: JsonProperty("isLoginOnly")] bool IsLoginOnly, + [property: JsonProperty("noLoginData")] object? NoLoginData + ); + + /// + /// Pixiv插画URL信息 + /// + /// + /// + /// + /// + /// + public record PixivIllustUrls( + [property: JsonProperty("mini")] string? Mini, + [property: JsonProperty("thumb")] string? Thumb, + [property: JsonProperty("small")] string? Small, + [property: JsonProperty("regular")] string? Regular, + [property: JsonProperty("original")] string? Original + ); + + /// + /// Pixiv插画标签信息 + /// + /// + /// + /// + /// + public record PixivIllustTags( + [property: JsonProperty("authorId")] string AuthorId, + [property: JsonProperty("isLocked")] bool IsLocked, + [property: JsonProperty("tags")] PixivTag[] Tags, + [property: JsonProperty("writable")] bool Writable + ); + + /// + /// Pixiv标签 + /// + /// + /// + /// + /// + /// + /// + public record PixivTag( + [property: JsonProperty("tag")] string Tag, + [property: JsonProperty("locked")] bool Locked, + [property: JsonProperty("deletable")] bool Deletable, + [property: JsonProperty("userId")] string? UserId, + [property: JsonProperty("userName")] string? UserName, + [property: JsonProperty("translation")] Dictionary? Translation + ); + + /// + /// Pixiv用户插画信息 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public record PixivUserIllust( + [property: JsonProperty("id")] string Id, + [property: JsonProperty("title")] string Title, + [property: JsonProperty("illustType")] int IllustType, + [property: JsonProperty("xRestrict")] int XRestrict, + [property: JsonProperty("restrict")] int Restrict, + [property: JsonProperty("sl")] int Sl, + [property: JsonProperty("url")] string Url, + [property: JsonProperty("description")] string Description, + [property: JsonProperty("tags")] string[] Tags, + [property: JsonProperty("userId")] string UserId, + [property: JsonProperty("userName")] string UserName, + [property: JsonProperty("width")] int Width, + [property: JsonProperty("height")] int Height, + [property: JsonProperty("pageCount")] int PageCount, + [property: JsonProperty("isBookmarkable")] bool IsBookmarkable, + [property: JsonProperty("bookmarkData")] object? BookmarkData, + [property: JsonProperty("alt")] string Alt, + [property: JsonProperty("titleCaptionTranslation")] PixivTitleCaptionTranslation TitleCaptionTranslation, + [property: JsonProperty("createDate")] string CreateDate, + [property: JsonProperty("updateDate")] string UpdateDate, + [property: JsonProperty("isUnlisted")] bool IsUnlisted, + [property: JsonProperty("isMasked")] bool IsMasked, + [property: JsonProperty("aiType")] int AiType, + [property: JsonProperty("profileImageUrl")] string? ProfileImageUrl + ); + + /// + /// Pixiv标题描述翻译 + /// + /// + /// + public record PixivTitleCaptionTranslation( + [property: JsonProperty("workTitle")] string? WorkTitle, + [property: JsonProperty("workCaption")] string? WorkCaption + ); +} + + diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivUserData.cs b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivUserData.cs new file mode 100644 index 0000000..55d4bef --- /dev/null +++ b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/Structs/PixivUserData.cs @@ -0,0 +1,74 @@ +using Newtonsoft.Json; + +namespace RitsukageBot.Library.OpenApi.Pixiv.Structs +{ + /// + /// Pixiv用户信息响应 + /// + /// + /// + /// + public record PixivUserResponse( + [property: JsonProperty("error")] bool Error, + [property: JsonProperty("message")] string Message, + [property: JsonProperty("body")] PixivUserData Body + ); + + /// + /// Pixiv用户数据 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public record PixivUserData( + [property: JsonProperty("userId")] string UserId, + [property: JsonProperty("name")] string Name, + [property: JsonProperty("image")] string Image, + [property: JsonProperty("imageBig")] string ImageBig, + [property: JsonProperty("premium")] bool Premium, + [property: JsonProperty("isFollowed")] bool IsFollowed, + [property: JsonProperty("isMypixiv")] bool IsMypixiv, + [property: JsonProperty("isBlocking")] bool IsBlocking, + [property: JsonProperty("background")] PixivUserBackground Background, + [property: JsonProperty("sketchLiveId")] string? SketchLiveId, + [property: JsonProperty("partial")] int Partial, + [property: JsonProperty("sketchLives")] object[] SketchLives, + [property: JsonProperty("commission")] PixivUserCommission Commission + ); + + /// + /// Pixiv用户背景信息 + /// + /// + /// + /// + /// + public record PixivUserBackground( + [property: JsonProperty("repeat")] string? Repeat, + [property: JsonProperty("color")] string? Color, + [property: JsonProperty("url")] string Url, + [property: JsonProperty("isPrivate")] bool IsPrivate + ); + + /// + /// Pixiv用户委托信息 + /// + /// + /// + public record PixivUserCommission( + [property: JsonProperty("acceptRequest")] bool AcceptRequest, + [property: JsonProperty("isSubscribedReopenNotification")] bool IsSubscribedReopenNotification + ); +} + + diff --git a/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs b/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs index 2187461..419f15e 100644 --- a/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs +++ b/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs @@ -7,6 +7,9 @@ using Richasy.BiliKernel.Bili.User; using RitsukageBot.Library.Bilibili.Convertors; using RitsukageBot.Library.OpenApi; +using RitsukageBot.Library.OpenApi.Baidu; +using RitsukageBot.Library.OpenApi.Baidu.Structs; +using RitsukageBot.Library.OpenApi.Pixiv; using RitsukageBot.Library.Utils; using RitsukageBot.Services.Providers; using ChatMessage = Microsoft.Extensions.AI.ChatMessage; @@ -99,6 +102,8 @@ private async Task ProgressPreprocessingActions(strin "weather_now" => await PreprocessingQWeatherQueryWeatherNow(data).ConfigureAwait(false), "weather_forecast" => await PreprocessingQWeatherQueryWeatherForecast(data) .ConfigureAwait(false), + "pixiv_user_info" => await PreprocessingPixivQueryUserInfo(data).ConfigureAwait(false), + "pixiv_illust_info" => await PreprocessingPixivQueryIllustInfo(data).ConfigureAwait(false), _ => null, }; @@ -143,7 +148,7 @@ private static async Task PreprocessingDateBaseInfo(JOb var param = paramToken.ToObject() ?? throw new InvalidDataException("Invalid JSON data for date base info action"); var time = param.Date.AsSettingsOffset(); - var days = await OpenApi.GetCalendarAsync(time).ConfigureAwait(false); + var days = await OpenApi.Instance.GetCalendarAsync(time).ConfigureAwait(false); var today = days.FirstOrDefault(x => x.ODate.ConvertToSettingsOffset() == time); var holiday = today?.FestivalInfoList is { Length: > 0 } ? string.Join(", ", today.FestivalInfoList.Select(x => x.Name)) @@ -183,7 +188,7 @@ private static async Task PreprocessingRangeDateBaseInf var query = from; while (query <= end) { - var dayInfo = await OpenApi.GetCalendarAsync(query).ConfigureAwait(false); + var dayInfo = await OpenApi.Instance.GetCalendarAsync(query).ConfigureAwait(false); days.AddRange(dayInfo); query = query.AddMonths(1); } @@ -321,6 +326,67 @@ private async Task PreprocessingQWeatherQueryWeatherFor return new($"Get Weather Forecast: {param.Location}", sb.ToString()); } + private async Task PreprocessingPixivQueryUserInfo(JObject? data) + { + if (data is null || !data.TryGetValue("param", out var paramValue) || paramValue is not JObject paramToken) + throw new InvalidDataException("Invalid JSON data for Pixiv user info action"); + var param = paramToken.ToObject() + ?? throw new InvalidDataException( + "Invalid JSON data for Pixiv user info action"); + if (string.IsNullOrWhiteSpace(param.Id)) + throw new InvalidDataException("Invalid ID for Pixiv user info action"); + var result = await OpenApi.Instance.GetPixivUserAsync(param.Id); + if (result is null) + throw new InvalidDataException($"Unable to find Pixiv user: {param.Id}"); + var sb = new StringBuilder(); + sb.AppendLine($"[Pixiv User Info: {param.Id}]"); + sb.AppendLine($"用户名:{result.Name}"); + return new($"Get Pixiv User Info: {param.Id}", sb.ToString()); + } + + private async Task PreprocessingPixivQueryIllustInfo(JObject? data) + { + if (data is null || !data.TryGetValue("param", out var paramValue) || paramValue is not JObject paramToken) + throw new InvalidDataException("Invalid JSON data for Pixiv illust info action"); + var param = paramToken.ToObject() + ?? throw new InvalidDataException( + "Invalid JSON data for Pixiv illust info action"); + if (string.IsNullOrWhiteSpace(param.Id)) + throw new InvalidDataException("Invalid ID for Pixiv illust info action"); + var result = await OpenApi.Instance.GetPixivIllustAsync(param.Id); + if (result is null) + throw new InvalidDataException($"Unable to find Pixiv illust: {param.Id}"); + var sb = new StringBuilder(); + sb.AppendLine($"[Pixiv Illust Info: {param.Id}]"); + sb.AppendLine($"标题:{result.Title}"); + sb.AppendLine($"作者:{result.UserName}"); + sb.AppendLine($"描述:{result.IllustComment}"); + sb.AppendLine($"标签:{string.Join(", ", result.Tags?.Tags?.Select(x => x.Tag) ?? [])}"); + sb.AppendLine($"创建时间:{result.CreateDate:yyyy-MM-dd HH:mm:ss}"); + sb.AppendLine($"页数:{result.PageCount}"); + sb.AppendLine($"浏览数:{result.ViewCount}"); + sb.AppendLine($"收藏数:{result.BookmarkCount}"); + sb.AppendLine($"点赞数:{result.LikeCount}"); + sb.AppendLine($"评论数:{result.CommentCount}"); + + var otherArtworks = result.UserIllusts?.Where(x => x.Value != null).Select(x => + { + var illust = x.Value!; + var stringBuilder = new StringBuilder(); + stringBuilder.AppendLine($"[{illust.Id}] {illust.Title}"); + stringBuilder.AppendLine(illust.Description); + stringBuilder.AppendLine($"Tags: {string.Join(", ", illust.Tags)}"); + stringBuilder.AppendLine($"Created At: {illust.CreateDate:yyyy-MM-dd HH:mm:ss}"); + stringBuilder.AppendLine($"Page Count: {illust.PageCount}"); + return sb.ToString(); + }).ToArray() ?? []; + if (otherArtworks.Length == 0) return new($"Get Pixiv Illust Info: {param.Id}", sb.ToString()); + sb.AppendLine("其他作品:"); + sb.AppendLine(string.Join("\n", otherArtworks)); + + return new($"Get Pixiv Illust Info: {param.Id}", sb.ToString()); + } + private record PreprocessingActionData(string Action, string Result); private static class PreprocessingActionParam @@ -385,6 +451,16 @@ internal class QWeatherQueryWeatherForecastActionParam { [JsonProperty("location")] public string Location { get; set; } = string.Empty; } + + internal class PixivIllustInfoActionParam + { + [JsonProperty("id")] public string Id { get; set; } = string.Empty; + } + + internal class PixivUserInfoActionParam + { + [JsonProperty("id")] public string Id { get; set; } = string.Empty; + } } } } \ No newline at end of file diff --git a/src/RitsukageBotForDiscord/Modules/ImageInteractions.cs b/src/RitsukageBotForDiscord/Modules/ImageInteractions.cs index 4d2179f..0d13a57 100644 --- a/src/RitsukageBotForDiscord/Modules/ImageInteractions.cs +++ b/src/RitsukageBotForDiscord/Modules/ImageInteractions.cs @@ -674,8 +674,7 @@ public async Task CancelAndPublishAsync() [ComponentInteraction($"{ImageInteractions.CustomId}:last_page")] public async Task LastPageAsync() { - var firstComponent = Context.Interaction.Message.Components?.FirstOrDefault()?.Components?.FirstOrDefault(); - if (firstComponent is not null) + if (Context.Interaction.Message.Components?.FirstOrDefault() is ButtonComponent firstComponent) { var componentInteraction = ImageInteractions.AllowedInteractions.FirstOrDefault(x => x.Id == firstComponent.CustomId); @@ -696,8 +695,7 @@ await Context.Interaction [ComponentInteraction($"{ImageInteractions.CustomId}:next_page")] public async Task NextPageAsync() { - var firstComponent = Context.Interaction.Message.Components?.FirstOrDefault()?.Components?.FirstOrDefault(); - if (firstComponent is not null) + if (Context.Interaction.Message.Components?.FirstOrDefault() is ButtonComponent firstComponent) { var componentInteraction = ImageInteractions.AllowedInteractions.FirstOrDefault(x => x.Id == firstComponent.CustomId); diff --git a/src/RitsukageBotForDiscord/Modules/Schedules/AutoBroadcastTimeScheduleTask.cs b/src/RitsukageBotForDiscord/Modules/Schedules/AutoBroadcastTimeScheduleTask.cs index d6e4551..5f53c8d 100644 --- a/src/RitsukageBotForDiscord/Modules/Schedules/AutoBroadcastTimeScheduleTask.cs +++ b/src/RitsukageBotForDiscord/Modules/Schedules/AutoBroadcastTimeScheduleTask.cs @@ -10,6 +10,8 @@ using RitsukageBot.Library.Data; using RitsukageBot.Library.Modules.Schedules; using RitsukageBot.Library.OpenApi; +using RitsukageBot.Library.OpenApi.Baidu; +using RitsukageBot.Library.OpenApi.Baidu.Structs; using RitsukageBot.Library.Utils; using RitsukageBot.Services.Providers; using ZiggyCreatures.Caching.Fusion; @@ -227,7 +229,7 @@ await _cacheProvider.SetAsync(cacheKey, content, options => private async Task CreateTimeMessageRequireMessage(DateTimeOffset targetTime, string prompt) { var time = targetTime.ConvertToSettingsOffset(); - var days = await OpenApi.GetCalendarAsync(time).ConfigureAwait(false); + var days = await OpenApi.Instance.GetCalendarAsync(time).ConfigureAwait(false); var minDay = time.Date.AddDays(-1); var maxDay = time.Date.AddDays(7); days = [.. days.Where(x => x.ODate >= minDay && x.ODate <= maxDay)]; diff --git a/src/RitsukageBotForDiscord/Modules/TimeInteractions.cs b/src/RitsukageBotForDiscord/Modules/TimeInteractions.cs index d582a43..92224db 100644 --- a/src/RitsukageBotForDiscord/Modules/TimeInteractions.cs +++ b/src/RitsukageBotForDiscord/Modules/TimeInteractions.cs @@ -4,6 +4,8 @@ using Microsoft.Extensions.Logging; using RitsukageBot.Library.Custom.Structs.Times; using RitsukageBot.Library.OpenApi; +using RitsukageBot.Library.OpenApi.Baidu; +using RitsukageBot.Library.OpenApi.Baidu.Structs; using RitsukageBot.Library.Utils; namespace RitsukageBot.Modules @@ -117,7 +119,7 @@ public async Task GetCalendar() await DeferAsync().ConfigureAwait(false); var date = DateTimeOffset.Now.ConvertToSettingsOffset(); - var days = await OpenApi.GetCalendarAsync(date).ConfigureAwait(false); + var days = await OpenApi.Instance.GetCalendarAsync(date).ConfigureAwait(false); var today = days.FirstOrDefault(x => x.ODate.ConvertToSettingsOffset().Date == date.Date); if (today is null) { diff --git a/src/RitsukageBotForDiscord/Program.cs b/src/RitsukageBotForDiscord/Program.cs index 3f558d1..3594daa 100644 --- a/src/RitsukageBotForDiscord/Program.cs +++ b/src/RitsukageBotForDiscord/Program.cs @@ -128,6 +128,8 @@ logger.LogInformation("Network default User-Agent: {UserAgent}", UserAgent.Default); NetworkUtility.SetHttpClientFactory(host.Services.GetRequiredService()); -OpenApi.SetCacheProvider(host.Services.GetRequiredService()); +OpenApi.Instance.SetCacheProvider(host.Services.GetRequiredService()); +OpenApi.Instance.SetLogger(host.Services.GetRequiredService>()); + await host.RunAsync(HostCancellationToken.Token).ConfigureAwait(false); \ No newline at end of file diff --git a/src/RitsukageBotForDiscord/RitsukageBotForDiscord.csproj b/src/RitsukageBotForDiscord/RitsukageBotForDiscord.csproj index 41a85d7..8b938dc 100644 --- a/src/RitsukageBotForDiscord/RitsukageBotForDiscord.csproj +++ b/src/RitsukageBotForDiscord/RitsukageBotForDiscord.csproj @@ -65,44 +65,44 @@ - - - - + + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + @@ -154,7 +154,7 @@ ..\bili-kernel-dll-build\bin\Richasy.BiliKernel.Services.User.dll - + From 81805d3577c992d3dc560184e4ac0b13634cbf12 Mon Sep 17 00:00:00 2001 From: OLC Date: Sun, 21 Sep 2025 20:21:03 +0800 Subject: [PATCH 2/4] fix ci --- .github/workflows/ci.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index becdc20..4518fd8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,16 @@ name: CI Build -on: { push, pull_request, workflow_dispatch } +#on: { push, pull_request, workflow_dispatch } +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + workflow_dispatch: env: DOTNET_ROLL_FORWARD: "Major" From 3f3f117da0a3561388a809a1bd41f4743ab5e867 Mon Sep 17 00:00:00 2001 From: OLC Date: Sun, 21 Sep 2025 20:23:17 +0800 Subject: [PATCH 3/4] fix issue --- src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs | 5 ++++- .../Library/OpenApi/Pixiv/OpenApi.Pixiv.cs | 4 ++-- .../Modules/AI/AiInteractions.Preprocessing.cs | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs b/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs index 3b54dc7..14eb40c 100644 --- a/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs +++ b/src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs @@ -19,7 +19,10 @@ private OpenApi() /// public IFusionCache? CacheProvider { get; private set; } - public ILogger Logger { get; private set; } + /// + /// Logger + /// + public ILogger? Logger { get; private set; } /// /// Instance of OpenApi diff --git a/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs index 665ce3f..95cf00a 100644 --- a/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs +++ b/src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs @@ -59,7 +59,7 @@ public static class OpenApiPixiv } catch (Exception ex) { - instance.Logger.LogError( + instance.Logger?.LogError( "Failed to get Pixiv user info (ID: {UserId}): {Message}", userId, ex.Message); } @@ -115,7 +115,7 @@ public static class OpenApiPixiv } catch (Exception ex) { - instance.Logger.LogError( + instance.Logger?.LogError( "Failed to get Pixiv illust info (ID: {IllustId}): {Message}", illustId, ex.Message); } diff --git a/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs b/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs index 419f15e..f9c3e3b 100644 --- a/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs +++ b/src/RitsukageBotForDiscord/Modules/AI/AiInteractions.Preprocessing.cs @@ -378,7 +378,7 @@ private async Task PreprocessingPixivQueryIllustInfo(JO stringBuilder.AppendLine($"Tags: {string.Join(", ", illust.Tags)}"); stringBuilder.AppendLine($"Created At: {illust.CreateDate:yyyy-MM-dd HH:mm:ss}"); stringBuilder.AppendLine($"Page Count: {illust.PageCount}"); - return sb.ToString(); + return stringBuilder.ToString(); }).ToArray() ?? []; if (otherArtworks.Length == 0) return new($"Get Pixiv Illust Info: {param.Id}", sb.ToString()); sb.AppendLine("其他作品:"); From f6cde6df122ee19ba128e1d66ec84a6f01a98300 Mon Sep 17 00:00:00 2001 From: OLC Date: Sun, 21 Sep 2025 20:25:31 +0800 Subject: [PATCH 4/4] fix gitversion --- src/RitsukageBotForDiscord/GitVersion.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RitsukageBotForDiscord/GitVersion.yml b/src/RitsukageBotForDiscord/GitVersion.yml index 6fbc97f..badb69f 100644 --- a/src/RitsukageBotForDiscord/GitVersion.yml +++ b/src/RitsukageBotForDiscord/GitVersion.yml @@ -72,7 +72,7 @@ branches: prevent-increment: of-merged-branch: true when-current-commit-tagged: false - label-number-pattern: '[/-](?\d+)' + #label-number-pattern: '[/-](?\d+)' track-merge-message: true regex: ^(pull|pull\-requests|pr)[/-] source-branches: