Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
3 changes: 3 additions & 0 deletions RitsukageBotForDiscord.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=An_0020enumerable_0020of/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=appsettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=baike/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bakaolc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bilibili/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=codespaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=danmaku/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Illust/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=modid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=modinfo/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=motd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ollama/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pixiv/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=richasy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ritsukage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=taskkill/@EntryIndexedValue">True</s:Boolean>
Expand Down
2 changes: 1 addition & 1 deletion src/RitsukageBotForDiscord/GitVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ branches:
prevent-increment:
of-merged-branch: true
when-current-commit-tagged: false
label-number-pattern: '[/-](?<number>\d+)'
#label-number-pattern: '[/-](?<number>\d+)'
track-merge-message: true
regex: ^(pull|pull\-requests|pr)[/-]
source-branches:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
/// <summary>
/// OpenApi.Baidu
/// </summary>
public static class OpenApiBaidu
{
/// <summary>
/// Get calendar information from Baidu
/// Return the calendar information from the previous month to the next month
/// </summary>
/// <param name="instance"></param>
/// <param name="date"></param>
/// <param name="httpClient"></param>
/// <returns></returns>
public static async Task<BaiduCalendarDay[]> GetCalendarAsync(DateTimeOffset date,
public static async Task<BaiduCalendarDay[]> 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<string>(cacheKey).ConfigureAwait(false);
var recordInfo = await instance.CacheProvider.GetOrDefaultAsync<string>(cacheKey).ConfigureAwait(false);
if (recordInfo is not null)
return JsonConvert.DeserializeObject<BaiduCalendarDay[]>(recordInfo)!;
}
Expand All @@ -45,8 +50,8 @@ public static async Task<BaiduCalendarDay[]> GetCalendarAsync(DateTimeOffset dat
var calendar = almanac.ToObject<BaiduCalendarDay[]>();
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),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Newtonsoft.Json;

namespace RitsukageBot.Library.OpenApi
namespace RitsukageBot.Library.OpenApi.Baidu.Structs
{
/// <summary>
/// Baidu calendar day
Expand Down
35 changes: 30 additions & 5 deletions src/RitsukageBotForDiscord/Library/OpenApi/OpenApi.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
using Microsoft.Extensions.Logging;
using ZiggyCreatures.Caching.Fusion;

namespace RitsukageBot.Library.OpenApi
{
/// <summary>
/// OpenApi
/// </summary>
public partial class OpenApi
public class OpenApi
{
private static IFusionCache? _cacheProvider;
private static readonly Lazy<OpenApi> OpenApiInstance = new();

private OpenApi()
{
}

/// <summary>
/// Get cache provider
/// Cache provider
/// </summary>
public IFusionCache? CacheProvider { get; private set; }

/// <summary>
/// Logger
/// </summary>
public ILogger<OpenApi>? Logger { get; private set; }

/// <summary>
/// Instance of OpenApi
/// </summary>
public static OpenApi Instance => OpenApiInstance.Value;

/// <summary>
/// Set cache provider
/// </summary>
/// <param name="cacheProvider"></param>
public static void SetCacheProvider(IFusionCache cacheProvider)
public void SetCacheProvider(IFusionCache cacheProvider)
{
CacheProvider = cacheProvider;
}

/// <summary>
/// Set logger
/// </summary>
/// <param name="logger"></param>
public void SetLogger(ILogger<OpenApi> logger)
{
_cacheProvider = cacheProvider;
Logger = logger;
}
}
}
126 changes: 126 additions & 0 deletions src/RitsukageBotForDiscord/Library/OpenApi/Pixiv/OpenApi.Pixiv.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// OpenApi.Pixiv
/// </summary>
public static class OpenApiPixiv
{
/// <summary>
/// 获取Pixiv用户信息
/// </summary>
/// <param name="instance">OpenApi实例</param>
/// <param name="userId">用户ID</param>
/// <param name="httpClient">HTTP客户端</param>
/// <returns>用户信息</returns>
public static async Task<PixivUserData?> 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<string>(cacheKey).ConfigureAwait(false);
if (recordInfo is not null)
{
var cachedResponse = JsonConvert.DeserializeObject<PixivUserResponse>(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<PixivUserResponse>(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;
}

/// <summary>
/// 获取Pixiv插画信息
/// </summary>
/// <param name="instance">OpenApi实例</param>
/// <param name="illustId">插画ID</param>
/// <param name="httpClient">HTTP客户端</param>
/// <returns>插画信息</returns>
public static async Task<PixivIllustData?> 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<string>(cacheKey).ConfigureAwait(false);
if (recordInfo is not null)
{
var cachedResponse = JsonConvert.DeserializeObject<PixivIllustResponse>(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<PixivIllustResponse>(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;
}
}
}

Loading
Loading