public async Task <ConversationStateEntity> GetCurrentUserStatus() { return(await _conversationStateRepo.GetStatusByUserId(_currentUser?.UserId ?? string.Empty)); }
public void Send(bool disableFilter) { var appId = ConfigurationManager.AppSettings["MicrosoftAppId"]; var appPassword = ConfigurationManager.AppSettings["MicrosoftAppPassword"]; var nowUtc = DateTime.Now.ToUniversalTime(); Log($"UTC現在時刻- {nowUtc}"); var usersRepo = new UsersRepository(); var users = usersRepo.GetAllUsers().RunAsSync(); var conversationStateRepo = new ConversationStateRepository(); Log($"処理ユーザー数: {users.Count()}"); foreach (var user in users) { try { Log($"ユーザー: {user.NickName}({user.UserId}) ---"); var startHhmm = Hhmm.Parse(user.AskEndOfWorkStartTime); var endHhmm = Hhmm.Parse(user.AskEndOfWorkEndTime); // 24時超過分をオフセットして比較する // 19:00~26:00 の設定だった時に、翌日の深夜1時(25時)も送信対象となるように。 var offsetHour = endHhmm.Hour - 23; if (offsetHour < 0) { offsetHour = 0; } Log($"オフセット時間: {offsetHour}h"); var tzUser = TimeZoneInfo.FindSystemTimeZoneById(user.TimeZoneId); var nowUserTz = TimeZoneInfo.ConvertTimeFromUtc(nowUtc, tzUser); // ユーザーのタイムゾーンでの現在時刻 Log($"ユーザータイムゾーンの現在時刻(オフセット前): {nowUserTz}"); nowUserTz = nowUserTz.AddHours(-offsetHour); var nowHour = nowUserTz.Hour + offsetHour; var nowStepedMinute = nowUserTz.Minute / 30 * 30; Log($"ユーザータイムゾーンの現在時刻(オフセット前、丸め後): {nowHour}時{nowStepedMinute:00}分"); var startTotalMinute = (startHhmm.Hour - offsetHour) * 60 + startHhmm.Minute; var endTotalMinute = (endHhmm.Hour - offsetHour) * 60 + endHhmm.Minute; var nowTotalMinute = (nowHour - offsetHour) * 60 + nowStepedMinute; Log($"ユーザータイムゾーンの現在時刻(オフセット後、丸め後): {(nowHour - offsetHour)}時{nowStepedMinute:00}分"); Log($"判定時刻範囲(オフセット前): {startHhmm.Hour}時{startHhmm.Minute:00}分~{endHhmm.Hour}時{endHhmm.Minute:00}分"); Log($"判定時刻範囲(オフセット後): {(startHhmm.Hour - offsetHour)}時{startHhmm.Minute:00}分~{(endHhmm.Hour - offsetHour)}時{endHhmm.Minute:00}分"); if (startTotalMinute >= endTotalMinute) { Log($"{user.UserId} は、開始時刻({user.AskEndOfWorkStartTime})と終了時刻({user.AskEndOfWorkEndTime})が逆転しているので何もしない。"); continue; } var nowUserTzDateText = $"{nowUserTz.Year:0000}/{nowUserTz.Month:00}/{nowUserTz.Day:00}"; // ユーザーTZ現在時刻を文字列化 var stateEntity = conversationStateRepo.GetStatusByUserId(user.UserId).RunAsSync(); var currentTargetDate = stateEntity?.TargetDate ?? "2000/01/01"; // ターゲット日付と現在時刻が同じで、 // 打刻済/今日はもう聞かないで/休日だったら何もしない var currentState = stateEntity?.State ?? AskingState.None; if (!disableFilter) { if (string.Equals(nowUserTzDateText, currentTargetDate) && (currentState == AskingState.DoNotAskToday || currentState == AskingState.Punched || currentState == AskingState.TodayIsOff)) { Log($"ターゲット日付({currentTargetDate})とユーザーTZ現在日付({nowUserTzDateText})が同じで、State が {currentState} なので何もしない"); continue; } // 今日の曜日はユーザー設定で有効か? var enableDayOfWeek = (user.DayOfWeekEnables?.Length ?? 0) - 1 > (int)nowUserTz.DayOfWeek ? (user.DayOfWeekEnables[(int)nowUserTz.DayOfWeek] == '1') : true; if (!enableDayOfWeek) { Log($"ユーザーTZ現在日付({nowUserTzDateText})の曜日は仕事が休みなので何もしない"); continue; } // FIXME 毎年ある祝日か、単発の休日かの管理が面倒なので、とりまオミットしておく //// 祝日か?(面倒だからJson文字列のまま検索しちゃう) //var isHoliday = user.HolidaysJson?.Contains($"\"{nowUserTz:M/d}\"") ?? false; // "6/1" みたいにダブルコートして検索すればいいっしょ //if (isHoliday) //{ // Log($"ユーザーTZ現在日付({nowUserTzText})の休日に設定されている何もしない"); // continue; //} var containsTimeRange = startTotalMinute <= nowTotalMinute && nowTotalMinute <= endTotalMinute; // 聞き取り終了時刻を過ぎていたらStateをNoneにする // AskingEoW のまま y を打たれると打刻できてしまうので。 if (startTotalMinute > endTotalMinute) { conversationStateRepo.UpsertState( user.PartitionKey, user.UserId, AskingState.None, $"{endHhmm.Hour:00}{endHhmm.Minute:00}", nowUserTzDateText).RunAsSync(); } if (!containsTimeRange) { Log($"現在時刻({nowUserTz}) が {user.AskEndOfWorkStartTime} から {user.AskEndOfWorkEndTime} の範囲外なので何もしない"); continue; } } var conversationRef = JsonConvert.DeserializeObject <ConversationReference>(user.ConversationRef); MicrosoftAppCredentials.TrustServiceUrl(conversationRef.ServiceUrl); var connector = new ConnectorClient(new Uri(conversationRef.ServiceUrl), appId, appPassword); var userAccount = new ChannelAccount(id: user.UserId); var res = connector.Conversations.CreateDirectConversation(conversationRef.Bot, userAccount); // conversationRef.GetPostToUserMessage() では Slack にポストできなかったので、 // 普通に CreateMessageActivity した。 var message = Activity.CreateMessageActivity(); message.From = conversationRef.Bot; message.Recipient = userAccount; message.Conversation = new ConversationAccount(id: res.Id); message.Text = $"{user.NickName} さん、お疲れさまです。{nowHour}時{nowStepedMinute:00}分 です、今日のお仕事は終わりましたか?\n\n" + $"--\n\ny:終わった\n\nn:終わってない\n\nd:今日は徹夜"; message.Locale = "ja-Jp"; //message.Attachments.Add(new Attachment() //{ // ContentType = AdaptiveCard.ContentType, // Content = MakeAdaptiveCard() //}); connector.Conversations.SendToConversation((Activity)message); conversationStateRepo.UpsertState( user.PartitionKey, conversationRef.User.Id, AskingState.AskingEoW, $"{nowHour:00}{nowStepedMinute:00}", nowUserTzDateText).RunAsSync(); Log($"メッセージを送信しました。 ({message.Text})"); } catch (Exception ex) { Log($"メッセージ送信に失敗しました。 ({ex.Message} - {ex.StackTrace})"); } } }