142 lines
No EOL
5.6 KiB
C#
142 lines
No EOL
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using autoteams.Models;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace autoteams
|
|
{
|
|
public class MeetingScheduler
|
|
{
|
|
public MeetingScheduler(TeamsController controller)
|
|
{
|
|
_controller = controller;
|
|
ScheduledMeetings = new();
|
|
_ticker = new((_) => SchedulerTick(), null, Timeout.Infinite, Timeout.Infinite);
|
|
}
|
|
|
|
private readonly Timer _ticker;
|
|
|
|
public HashSet<ScheduledMeeting> ScheduledMeetings { get; private set; }
|
|
|
|
private bool _init;
|
|
|
|
public void Initialize()
|
|
{
|
|
if (_init) return;
|
|
_init = true;
|
|
|
|
LoadMeetingsFromDb();
|
|
_ = Task.Run(async () =>
|
|
{
|
|
int scheduledSecond = ConfigurationManager.CONFIG.SchedulerSyncOnSecond;
|
|
|
|
//Use second synchronization if valid config
|
|
if (scheduledSecond is >= 0 and < 60)
|
|
{
|
|
var now = DateTime.Now;
|
|
|
|
//Set the trigger date that is either in the current minute or in the next minute, if the desired seconds has passed
|
|
var trigger = now.AddSeconds(scheduledSecond - now.Second < 0 ? 60 - now.Second + scheduledSecond : scheduledSecond);
|
|
await Task.Delay(trigger - now);
|
|
|
|
Logger.Info($"Waiting to synchronize with time (on {trigger}).");
|
|
}
|
|
|
|
_ticker.Change(TimeSpan.Zero, TimeSpan.FromMinutes(1));
|
|
Logger.Info($"Started scheduler timer at {DateTime.Now}.");
|
|
});
|
|
}
|
|
|
|
public void LoadMeetingsFromDb()
|
|
{
|
|
ScheduledMeetings.Clear();
|
|
|
|
Logger.Info("Loading scheduled meetings...");
|
|
|
|
using var db = new StorageContext();
|
|
|
|
var now = DateTime.Now;
|
|
|
|
foreach (ScheduledMeeting meeting in db.Meetings.AsNoTracking().Include(s => s.Channel).AsEnumerable())
|
|
{
|
|
try
|
|
{
|
|
meeting.Time = new DateTime(now.Year, now.Month, now.Day, meeting.StartHour, meeting.StartMinute, 0);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Logger.Warn($"Corrupted meeting: {meeting.Channel.ClassroomName}, {meeting.Channel.Name}. Discarding...");
|
|
continue;
|
|
}
|
|
|
|
Logger.Debug($"Found meeting in {meeting.Channel.ClassroomName}, {meeting.Channel.Name} on {meeting.DayOfWeek}s, {meeting.StartHour}:{meeting.StartMinute}");
|
|
ScheduledMeetings.Add(meeting);
|
|
}
|
|
}
|
|
|
|
private readonly TeamsController _controller;
|
|
|
|
private ScheduledMeeting _currentMeeting;
|
|
private DateTime _lastMeetingStart;
|
|
|
|
public void SchedulerTick()
|
|
{
|
|
if (_currentMeeting != null)
|
|
{
|
|
var now = DateTime.Now;
|
|
if (now.CompareTo(_currentMeeting.Time.Add(TimeSpan.FromMinutes(_currentMeeting.DurationMinutes))) >= 0)
|
|
{
|
|
Logger.Info($"Meeting in {_currentMeeting.Channel.Name}, {_currentMeeting.Channel.ClassroomName} ends now ({now}), after {(int)(now - _lastMeetingStart).TotalMinutes} minutes.");
|
|
_controller.LeaveMeeting();
|
|
_currentMeeting = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lock (ScheduledMeetings)
|
|
{
|
|
foreach (ScheduledMeeting meeting in ScheduledMeetings)
|
|
{
|
|
DateTime time = DateTime.Now;
|
|
if (meeting.DayOfWeek.Equals(time.DayOfWeek.ToString(), StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
DateTime target = new(time.Year, time.Month, time.Day, meeting.StartHour, meeting.StartMinute, 0);
|
|
|
|
if (time.CompareTo(target) > 0)
|
|
{
|
|
var difference = time - target;
|
|
var timeToBreak = (int)meeting.DurationMinutes / 3;
|
|
|
|
if (difference.TotalMinutes <= (timeToBreak < 15 ? meeting.DurationMinutes : timeToBreak / 3))
|
|
{
|
|
Logger.Info($"Meeting in {meeting.Channel.Name}, {meeting.Channel.ClassroomName} starts now ({time}) for {meeting.DurationMinutes} minutes.");
|
|
|
|
var minuteDifference = (int)difference.TotalMinutes;
|
|
|
|
if (minuteDifference > 0)
|
|
{
|
|
Logger.Info($"We are {minuteDifference} minute{(minuteDifference > 1 ? "s" : "")} late.");
|
|
}
|
|
bool isSuccess = _controller.JoinMeeting(meeting.Channel);
|
|
if (isSuccess)
|
|
{
|
|
_currentMeeting = meeting;
|
|
_lastMeetingStart = time;
|
|
Logger.Info("Successfully joined the meeting.");
|
|
}
|
|
else
|
|
Logger.Error("Cannot join meeting.");
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |