diff --git a/VQCalendarAttention/Program.cs b/VQCalendarAttention/Program.cs index 0a5cac5..66c84eb 100644 --- a/VQCalendarAttention/Program.cs +++ b/VQCalendarAttention/Program.cs @@ -38,6 +38,23 @@ string CredentialsFilePath = DotNetEnv.Env.GetString("CREDENTIALS_FILE_PATH"); return new NextDayCalendarAttentionService(cronExpression, timeZoneInfo, serviceProvider, CredentialsFilePath, calendarId); }); + + // 重要な予定を通知する + services.AddHostedService(serviceProvider => + { + // Cron式を設定 (例: 毎日午前9時に実行) + //var cronExpression = CronExpression.Parse("0 9 * * *"); + // 毎晩21時2分に実行 + var cronExpression = CronExpression.Parse("2 21 * * *"); + //var cronExpression = CronExpression.Parse("* * * * *"); + + // タイムゾーンを東京に設定 + var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); + + string calendarId = DotNetEnv.Env.GetString("CALENDAR_ID"); + string CredentialsFilePath = DotNetEnv.Env.GetString("CREDENTIALS_FILE_PATH"); + return new ImportantCalendarAttentionService(cronExpression, timeZoneInfo, serviceProvider, CredentialsFilePath, calendarId); + }); }); } } diff --git a/VQCalendarAttention/Services/ImportantCalendarAttentionService.cs b/VQCalendarAttention/Services/ImportantCalendarAttentionService.cs new file mode 100644 index 0000000..a899909 --- /dev/null +++ b/VQCalendarAttention/Services/ImportantCalendarAttentionService.cs @@ -0,0 +1,105 @@ +using System; +using System.Text; +using Cronos; +using Google.Apis.Calendar.v3; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using ServiceWorkerCronJobDemo.Services; + +namespace VestalisQuintet.VQCalendarAttention +{ + /// + /// 説明に[重要]という文字列がついている予定について、 + /// 今からちょうど3日後か7日後である場合に、指定のロールに + /// メンションを送りつつDiscordのwebhookに通知するタスク + /// + public class ImportantCalendarAttentionService : CronJobService + { + private readonly IServiceProvider _serviceProvider; + + /// + /// Googleカレンダー用の認証情報 + /// + private string _credentialsFilePath; + + /// + /// 取得先のカレンダーID + /// + private string _calendarId; + + public ImportantCalendarAttentionService(CronExpression expression, TimeZoneInfo timeZoneInfo, IServiceProvider serviceProvider, + string credentialsFilePath, string calendarId) + : base(expression, timeZoneInfo) + { + _serviceProvider = serviceProvider; + _credentialsFilePath = credentialsFilePath; + _calendarId = calendarId; + } + + public override async Task DoWork(CancellationToken cancellationToken) + { + Console.WriteLine("Cron job executed at: " + DateTimeOffset.Now); + + // カレンダーから予定を取得して、3日後と7日後に行われる予定を抽出する + CalendarService service = CalendarApiTest.getCalendarService(_credentialsFilePath); + + // タイムゾーンを指定してUTCからJSTへ変換 + TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); + DateTime jst = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi); + + // イベントリストのリクエストを作成 + var request = service.Events.List(_calendarId); + request.TimeMin = jst; + request.TimeMax = jst.AddDays(8); // 7日後までのイベントを取得 + request.ShowDeleted = false; + request.SingleEvents = true; + request.MaxResults = 250; + request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime; + + // イベントリストのリクエストを実行 + var events = await request.ExecuteAsync(); + + // 3日後と7日後に行われる[重要]な予定を抽出する + var importantEvents = events.Items + .Where(e => e.Description != null && e.Description.Contains("[重要]") && + ( + (e.Start.DateTime.HasValue && + (e.Start.DateTime.Value.Date == jst.AddDays(3).Date || + e.Start.DateTime.Value.Date == jst.AddDays(7).Date)) || + (e.Start.Date != null && + (DateTime.Parse(e.Start.Date).Date == jst.AddDays(3).Date || + DateTime.Parse(e.Start.Date).Date == jst.AddDays(7).Date)) + ) + ) + .ToList(); + + // [重要]な予定をDiscordに送信 + if (importantEvents.Count > 0) + { + // DiscordWebhook インスタンスを作成 + string webhookUrl = DotNetEnv.Env.GetString("DISCORD_WEBHOOK_URL"); + var discordWebhook = new DiscordWebhook(webhookUrl); + + // 通知先ロールIDを指定 + string roleId = DotNetEnv.Env.GetString("DISCORD_ROLE_ID"); + + // [重要]な予定をメッセージとして組み立て + var sb = new StringBuilder("重要な予定が迫っています:\n"); + foreach (var importantEvent in importantEvents) + { + string startTime = importantEvent.Start.DateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? DateTime.Parse(importantEvent.Start.Date).ToString("yyyy-MM-dd"); + sb.AppendLine($"<@&{roleId}> {importantEvent.Summary}: {startTime}"); // ロールIDを使用したメンションを作成 + } + + // メッセージをDiscordに送信 + await discordWebhook.SendMessageAsync(sb.ToString()); + } + else + { + Console.WriteLine("重要な予定はありません。"); + } + + await Task.CompletedTask; + } + } +}