Creating events.
This commit is contained in:
@@ -35,6 +35,7 @@ using Wino.Core.Extensions;
|
||||
using Wino.Core.Http;
|
||||
using Wino.Core.Integration.Processors;
|
||||
using Wino.Core.Requests.Bundles;
|
||||
using Wino.Core.Requests.Calendar;
|
||||
using Wino.Core.Requests.Folder;
|
||||
using Wino.Core.Requests.Mail;
|
||||
using Wino.Messaging.UI;
|
||||
@@ -1627,6 +1628,76 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
||||
|
||||
#endregion
|
||||
|
||||
#region Calendar Operations
|
||||
|
||||
public override List<IRequestBundle<IClientServiceRequest>> CreateCalendarEvent(CreateCalendarEventRequest request)
|
||||
{
|
||||
var calendarItem = request.Item;
|
||||
var attendees = request.Attendees;
|
||||
|
||||
// Get the calendar for this event
|
||||
var calendar = calendarItem.AssignedCalendar;
|
||||
if (calendar == null)
|
||||
{
|
||||
throw new InvalidOperationException("Calendar item must have an assigned calendar");
|
||||
}
|
||||
|
||||
// Convert CalendarItem to Google Event
|
||||
var googleEvent = new Event
|
||||
{
|
||||
Summary = calendarItem.Title,
|
||||
Description = calendarItem.Description,
|
||||
Location = calendarItem.Location,
|
||||
Status = calendarItem.Status == CalendarItemStatus.Confirmed ? "confirmed" : "tentative"
|
||||
};
|
||||
|
||||
// Set start and end time
|
||||
if (calendarItem.IsAllDayEvent)
|
||||
{
|
||||
// All-day events use Date instead of DateTime
|
||||
googleEvent.Start = new EventDateTime
|
||||
{
|
||||
Date = calendarItem.StartDate.ToString("yyyy-MM-dd")
|
||||
};
|
||||
googleEvent.End = new EventDateTime
|
||||
{
|
||||
Date = calendarItem.EndDate.ToString("yyyy-MM-dd")
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular events with time
|
||||
googleEvent.Start = new EventDateTime
|
||||
{
|
||||
DateTimeDateTimeOffset = new DateTimeOffset(calendarItem.StartDate, TimeSpan.Zero),
|
||||
TimeZone = calendarItem.StartTimeZone
|
||||
};
|
||||
googleEvent.End = new EventDateTime
|
||||
{
|
||||
DateTimeDateTimeOffset = new DateTimeOffset(calendarItem.EndDate, TimeSpan.Zero),
|
||||
TimeZone = calendarItem.EndTimeZone
|
||||
};
|
||||
}
|
||||
|
||||
// Add attendees if any
|
||||
if (attendees != null && attendees.Count > 0)
|
||||
{
|
||||
googleEvent.Attendees = attendees.Select(a => new EventAttendee
|
||||
{
|
||||
Email = a.Email,
|
||||
DisplayName = a.Name,
|
||||
Optional = a.IsOptionalAttendee
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
// Create the insert request
|
||||
var insertRequest = _calendarService.Events.Insert(googleEvent, calendar.RemoteCalendarId);
|
||||
|
||||
return [new HttpRequestBundle<IClientServiceRequest>(insertRequest, request)];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override async Task KillSynchronizerAsync()
|
||||
{
|
||||
await base.KillSynchronizerAsync();
|
||||
|
||||
@@ -39,6 +39,7 @@ using Wino.Core.Http;
|
||||
using Wino.Core.Integration.Processors;
|
||||
using Wino.Core.Misc;
|
||||
using Wino.Core.Requests.Bundles;
|
||||
using Wino.Core.Requests.Calendar;
|
||||
using Wino.Core.Requests.Folder;
|
||||
using Wino.Core.Requests.Mail;
|
||||
|
||||
@@ -1804,6 +1805,89 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
return !localCalendarName.Equals(remoteCalendarName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
#region Calendar Operations
|
||||
|
||||
public override List<IRequestBundle<RequestInformation>> CreateCalendarEvent(CreateCalendarEventRequest request)
|
||||
{
|
||||
var calendarItem = request.Item;
|
||||
var attendees = request.Attendees;
|
||||
|
||||
// Get the calendar for this event
|
||||
var calendar = calendarItem.AssignedCalendar;
|
||||
if (calendar == null)
|
||||
{
|
||||
throw new InvalidOperationException("Calendar item must have an assigned calendar");
|
||||
}
|
||||
|
||||
// Convert CalendarItem to Outlook Event
|
||||
var outlookEvent = new Microsoft.Graph.Models.Event
|
||||
{
|
||||
Subject = calendarItem.Title,
|
||||
Body = new Microsoft.Graph.Models.ItemBody
|
||||
{
|
||||
ContentType = Microsoft.Graph.Models.BodyType.Text,
|
||||
Content = calendarItem.Description
|
||||
},
|
||||
Location = new Microsoft.Graph.Models.Location
|
||||
{
|
||||
DisplayName = calendarItem.Location
|
||||
}
|
||||
};
|
||||
|
||||
// Set start and end time using DateTimeTimeZone
|
||||
if (calendarItem.IsAllDayEvent)
|
||||
{
|
||||
// All-day events
|
||||
outlookEvent.IsAllDay = true;
|
||||
outlookEvent.Start = new Microsoft.Graph.Models.DateTimeTimeZone
|
||||
{
|
||||
DateTime = calendarItem.StartDate.ToString("yyyy-MM-dd"),
|
||||
TimeZone = "UTC"
|
||||
};
|
||||
outlookEvent.End = new Microsoft.Graph.Models.DateTimeTimeZone
|
||||
{
|
||||
DateTime = calendarItem.EndDate.ToString("yyyy-MM-dd"),
|
||||
TimeZone = "UTC"
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular events with time
|
||||
outlookEvent.IsAllDay = false;
|
||||
outlookEvent.Start = new Microsoft.Graph.Models.DateTimeTimeZone
|
||||
{
|
||||
DateTime = calendarItem.StartDate.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
TimeZone = calendarItem.StartTimeZone ?? "UTC"
|
||||
};
|
||||
outlookEvent.End = new Microsoft.Graph.Models.DateTimeTimeZone
|
||||
{
|
||||
DateTime = calendarItem.EndDate.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
TimeZone = calendarItem.EndTimeZone ?? "UTC"
|
||||
};
|
||||
}
|
||||
|
||||
// Add attendees if any
|
||||
if (attendees != null && attendees.Count > 0)
|
||||
{
|
||||
outlookEvent.Attendees = attendees.Select(a => new Microsoft.Graph.Models.Attendee
|
||||
{
|
||||
EmailAddress = new Microsoft.Graph.Models.EmailAddress
|
||||
{
|
||||
Address = a.Email,
|
||||
Name = a.Name
|
||||
},
|
||||
Type = a.IsOptionalAttendee ? Microsoft.Graph.Models.AttendeeType.Optional : Microsoft.Graph.Models.AttendeeType.Required
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
// Create the event using Graph API
|
||||
var createRequest = _graphClient.Me.Calendars[calendar.RemoteCalendarId].Events.ToPostRequestInformation(outlookEvent);
|
||||
|
||||
return [new HttpRequestBundle<RequestInformation>(createRequest, request)];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override async Task KillSynchronizerAsync()
|
||||
{
|
||||
await base.KillSynchronizerAsync();
|
||||
|
||||
@@ -18,6 +18,7 @@ using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.Requests.Bundles;
|
||||
using Wino.Core.Requests.Calendar;
|
||||
using Wino.Core.Requests.Folder;
|
||||
using Wino.Core.Requests.Mail;
|
||||
using Wino.Messaging.UI;
|
||||
@@ -337,10 +338,67 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
|
||||
/// <param name="options">Synchronization options.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>Synchronization result that contains summary of the sync.</returns>
|
||||
public Task<CalendarSynchronizationResult> SynchronizeCalendarEventsAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
public async Task<CalendarSynchronizationResult> SynchronizeCalendarEventsAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// TODO: Execute requests for calendar events.
|
||||
return SynchronizeCalendarEventsInternalAsync(options, cancellationToken);
|
||||
bool shouldExecuteRequests = changeRequestQueue.Any(r => r is ICalendarActionRequest);
|
||||
bool shouldDelayExecution = false;
|
||||
int maxExecutionDelay = 0;
|
||||
|
||||
if (shouldExecuteRequests)
|
||||
{
|
||||
State = AccountSynchronizerState.ExecutingRequests;
|
||||
|
||||
List<IRequestBundle<TBaseRequest>> nativeRequests = new();
|
||||
List<IRequestBase> requestCopies = new(changeRequestQueue.Where(r => r is ICalendarActionRequest));
|
||||
|
||||
var keys = requestCopies.GroupBy(a => a.GroupingKey());
|
||||
|
||||
foreach (var group in keys)
|
||||
{
|
||||
var key = group.Key;
|
||||
|
||||
if (key is CalendarSynchronizerOperation calendarSynchronizerOperation)
|
||||
{
|
||||
switch (calendarSynchronizerOperation)
|
||||
{
|
||||
case CalendarSynchronizerOperation.CreateEvent:
|
||||
nativeRequests.AddRange(CreateCalendarEvent(group.ElementAt(0) as CreateCalendarEventRequest));
|
||||
break;
|
||||
case CalendarSynchronizerOperation.UpdateEvent:
|
||||
// TODO: Implement UpdateCalendarEvent
|
||||
break;
|
||||
case CalendarSynchronizerOperation.DeleteEvent:
|
||||
// TODO: Implement DeleteCalendarEvent
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove processed calendar requests from queue
|
||||
changeRequestQueue.RemoveAll(r => r is ICalendarActionRequest);
|
||||
|
||||
Console.WriteLine($"Prepared {nativeRequests.Count()} native calendar requests");
|
||||
|
||||
await ExecuteNativeRequestsAsync(nativeRequests, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Let servers to finish their job. Sometimes the servers don't respond immediately.
|
||||
shouldDelayExecution = requestCopies.Any(a => a.ResynchronizationDelay > 0);
|
||||
|
||||
if (shouldDelayExecution)
|
||||
{
|
||||
maxExecutionDelay = requestCopies.Aggregate(0, (max, next) => Math.Max(max, next.ResynchronizationDelay));
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDelayExecution)
|
||||
{
|
||||
await Task.Delay(maxExecutionDelay, cancellationToken);
|
||||
}
|
||||
|
||||
// Execute the actual synchronization
|
||||
return await SynchronizeCalendarEventsInternalAsync(options, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -435,6 +493,7 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
|
||||
|
||||
#region Calendar Operations
|
||||
|
||||
public virtual List<IRequestBundle<TBaseRequest>> CreateCalendarEvent(CreateCalendarEventRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user