diff --git a/Katheryne.Tests/Modules/WeatherModuleTests.cs b/Katheryne.Tests/Modules/WeatherModuleTests.cs new file mode 100644 index 0000000..757e30e --- /dev/null +++ b/Katheryne.Tests/Modules/WeatherModuleTests.cs @@ -0,0 +1,26 @@ +using Katheryne.Modules; +using Xunit.Abstractions; + +namespace Katheryne.Tests.Modules; + +public class WeatherModuleTests +{ + private readonly ITestOutputHelper _output; + + public WeatherModuleTests(ITestOutputHelper output) + { + _output = output; + } + + [Fact] + public void WeatherModuleTest() + { + var weather = new WeatherModule(); + + Assert.True(weather.ContainsParam("text")); + Assert.True(weather.ContainsParam("temp")); + + _output.WriteLine(weather["text"]); + _output.WriteLine(weather["temp"]); + } +} \ No newline at end of file diff --git a/Katheryne/Exceptions/ModuleException.cs b/Katheryne/Exceptions/ModuleException.cs new file mode 100644 index 0000000..41dbf10 --- /dev/null +++ b/Katheryne/Exceptions/ModuleException.cs @@ -0,0 +1,22 @@ +namespace Katheryne.Exceptions; + +/// +/// 调用模块中发生的异常 +/// +public class ModuleException : Exception +{ + public ModuleException() : base() + { + + } + + public ModuleException(string message) : base(message) + { + + } + + public ModuleException(string message, Exception innerException) : base(message, innerException) + { + + } +} \ No newline at end of file diff --git a/Katheryne/Modules/ModuleBase.cs b/Katheryne/Modules/ModuleBase.cs new file mode 100644 index 0000000..61553c3 --- /dev/null +++ b/Katheryne/Modules/ModuleBase.cs @@ -0,0 +1,30 @@ +using System.Text.Json; +using Katheryne.Abstractions; + +namespace Katheryne.Modules; + +public abstract class ModuleBase : IParamsModule +{ + protected readonly Dictionary> Functions = new(); + + protected readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNameCaseInsensitive = true + }; + + public abstract string ModuleName { get; } + + public string this[string param] + { + get + { + Func func = Functions[param]; + return func(); + } + } + + public bool ContainsParam(string param) + { + return Functions.ContainsKey(param); + } +} \ No newline at end of file diff --git a/Katheryne/Modules/WeatherModule.cs b/Katheryne/Modules/WeatherModule.cs new file mode 100644 index 0000000..4fb79dc --- /dev/null +++ b/Katheryne/Modules/WeatherModule.cs @@ -0,0 +1,67 @@ +using System.Net.Http.Json; +using System.Text.Json.Serialization; +using Katheryne.Exceptions; + +namespace Katheryne.Modules; + +public class WeatherModule : ModuleBase +{ + private static readonly HttpClient s_httpClient = new(); + + private const string WeatherApi = + "https://api.seniverse.com/v3/weather/now.json?key=S7s93MkxJ1q7mgHoj&location=beijing&language=zh-Hans&unit=c"; + + private WeatherDto? _weatherDto; + + public override string ModuleName => "weather"; + + public WeatherModule() + { + Functions.Add("text", () => FetchWeatherDate().Now.Text); + Functions.Add("temp", () => FetchWeatherDate().Now.Temperature); + } + + private WeatherDto FetchWeatherDate() + { + if (_weatherDto is not null) + { + if (DateTime.Now - _weatherDto.LastUpdate < TimeSpan.FromMinutes(5)) + { + return _weatherDto; + } + } + + try + { + Task>?> task = s_httpClient.GetFromJsonAsync>>( + WeatherApi, JsonOptions); + task.Wait(); + Dictionary>? response = task.Result; + WeatherDto? weather = response?["results"][0]; + + _weatherDto = weather ?? throw new ModuleException("Failed to fetch weather data."); + return _weatherDto; + } + catch (HttpRequestException e) + { + throw new ModuleException("Failed to fetch weather data.", e); + } + } + + private class WeatherNowDto + { + public required string Text { get; set; } + + public required string Code { get; set; } + + public required string Temperature { get; set; } + } + + private class WeatherDto + { + public required WeatherNowDto Now { get; set; } + + [JsonPropertyName("last_update")] + public DateTime LastUpdate { get; set; } + } +} \ No newline at end of file