Synchronizing calendars for gmail and some events.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Apis.Calendar.v3.Data;
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
@@ -32,28 +34,28 @@ namespace Wino.Core.Integration.Processors
|
||||
Task DeleteFolderAsync(Guid accountId, string remoteFolderId);
|
||||
Task InsertFolderAsync(MailItemFolder folder);
|
||||
Task UpdateFolderAsync(MailItemFolder folder);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of folders that are available for account.
|
||||
/// </summary>
|
||||
/// <param name="accountId">Account id to get folders for.</param>
|
||||
/// <returns>All folders.</returns>
|
||||
Task<List<MailItemFolder>> GetLocalFoldersAsync(Guid accountId);
|
||||
|
||||
|
||||
Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(MailSynchronizationOptions options);
|
||||
|
||||
Task<bool> MapLocalDraftAsync(Guid accountId, Guid localDraftCopyUniqueId, string newMailCopyId, string newDraftId, string newThreadId);
|
||||
Task UpdateFolderLastSyncDateAsync(Guid folderId);
|
||||
|
||||
Task<List<MailItemFolder>> GetExistingFoldersAsync(Guid accountId);
|
||||
Task UpdateRemoteAliasInformationAsync(MailAccount account, List<RemoteAccountAlias> remoteAccountAliases);
|
||||
|
||||
// Calendar
|
||||
Task<List<AccountCalendar>> GetAccountCalendarsAsync(Guid accountId);
|
||||
|
||||
Task DeleteCalendarItemAsync(Guid calendarItemId);
|
||||
|
||||
Task DeleteAccountCalendarAsync(AccountCalendar accountCalendar);
|
||||
Task InsertAccountCalendarAsync(AccountCalendar accountCalendar);
|
||||
Task UpdateAccountCalendarAsync(AccountCalendar accountCalendar);
|
||||
}
|
||||
|
||||
public interface IGmailChangeProcessor : IDefaultChangeProcessor
|
||||
{
|
||||
Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId);
|
||||
Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
|
||||
Task<CalendarItem> CreateCalendarItemAsync(Event calendarEvent, AccountCalendar assignedCalendar, MailAccount organizerAccount);
|
||||
}
|
||||
|
||||
public interface IOutlookChangeProcessor : IDefaultChangeProcessor
|
||||
@@ -115,13 +117,15 @@ namespace Wino.Core.Integration.Processors
|
||||
public class DefaultChangeProcessor(IDatabaseService databaseService,
|
||||
IFolderService folderService,
|
||||
IMailService mailService,
|
||||
ICalendarService calendarService,
|
||||
IAccountService accountService,
|
||||
IMimeFileService mimeFileService) : BaseDatabaseService(databaseService), IDefaultChangeProcessor
|
||||
{
|
||||
protected IMailService MailService = mailService;
|
||||
|
||||
protected ICalendarService CalendarService = calendarService;
|
||||
protected IFolderService FolderService = folderService;
|
||||
protected IAccountService AccountService = accountService;
|
||||
|
||||
private readonly IMimeFileService _mimeFileService = mimeFileService;
|
||||
|
||||
public Task<string> UpdateAccountDeltaSynchronizationIdentifierAsync(Guid accountId, string synchronizationDeltaIdentifier)
|
||||
@@ -179,5 +183,20 @@ namespace Wino.Core.Integration.Processors
|
||||
|
||||
public Task UpdateRemoteAliasInformationAsync(MailAccount account, List<RemoteAccountAlias> remoteAccountAliases)
|
||||
=> AccountService.UpdateRemoteAliasInformationAsync(account, remoteAccountAliases);
|
||||
|
||||
public Task<List<AccountCalendar>> GetAccountCalendarsAsync(Guid accountId)
|
||||
=> CalendarService.GetAccountCalendarsAsync(accountId);
|
||||
|
||||
public Task DeleteCalendarItemAsync(Guid calendarItemId)
|
||||
=> CalendarService.DeleteCalendarItemAsync(calendarItemId);
|
||||
|
||||
public Task DeleteAccountCalendarAsync(AccountCalendar accountCalendar)
|
||||
=> CalendarService.DeleteAccountCalendarAsync(accountCalendar);
|
||||
|
||||
public Task InsertAccountCalendarAsync(AccountCalendar accountCalendar)
|
||||
=> CalendarService.InsertAccountCalendarAsync(accountCalendar);
|
||||
|
||||
public Task UpdateAccountCalendarAsync(AccountCalendar accountCalendar)
|
||||
=> CalendarService.UpdateAccountCalendarAsync(accountCalendar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Apis.Calendar.v3.Data;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Extensions;
|
||||
using Wino.Services;
|
||||
using CalendarEventAttendee = Wino.Core.Domain.Entities.Calendar.CalendarEventAttendee;
|
||||
using CalendarItem = Wino.Core.Domain.Entities.Calendar.CalendarItem;
|
||||
|
||||
namespace Wino.Core.Integration.Processors
|
||||
{
|
||||
public class GmailChangeProcessor : DefaultChangeProcessor, IGmailChangeProcessor
|
||||
{
|
||||
public GmailChangeProcessor(IDatabaseService databaseService, IFolderService folderService, IMailService mailService, IAccountService accountService, IMimeFileService mimeFileService) : base(databaseService, folderService, mailService, accountService, mimeFileService)
|
||||
public GmailChangeProcessor(IDatabaseService databaseService,
|
||||
IFolderService folderService,
|
||||
IMailService mailService,
|
||||
ICalendarService calendarService,
|
||||
IAccountService accountService,
|
||||
IMimeFileService mimeFileService) : base(databaseService, folderService, mailService, calendarService, accountService, mimeFileService)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId)
|
||||
@@ -16,5 +30,116 @@ namespace Wino.Core.Integration.Processors
|
||||
|
||||
public Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
|
||||
=> MailService.CreateAssignmentAsync(accountId, mailCopyId, remoteFolderId);
|
||||
|
||||
public async Task<CalendarItem> CreateCalendarItemAsync(Event calendarEvent, AccountCalendar assignedCalendar, MailAccount organizerAccount)
|
||||
{
|
||||
var calendarItem = new CalendarItem()
|
||||
{
|
||||
CalendarId = assignedCalendar.Id,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
Description = calendarEvent.Description,
|
||||
StartTime = GoogleIntegratorExtensions.GetEventStartDateTimeOffset(calendarEvent) ?? throw new Exception("Event without a start time."),
|
||||
DurationInMinutes = GoogleIntegratorExtensions.GetEventDurationInMinutes(calendarEvent) ?? throw new Exception("Event without a duration."),
|
||||
Id = Guid.NewGuid(),
|
||||
Location = calendarEvent.Location,
|
||||
Recurrence = GoogleIntegratorExtensions.GetRecurrenceString(calendarEvent),
|
||||
Status = GetStatus(calendarEvent.Status),
|
||||
Title = calendarEvent.Summary,
|
||||
UpdatedAt = DateTimeOffset.UtcNow,
|
||||
Visibility = GetVisibility(calendarEvent.Visibility),
|
||||
};
|
||||
|
||||
// TODO: There are some edge cases with cancellation here.
|
||||
CalendarItemStatus GetStatus(string status)
|
||||
{
|
||||
return status switch
|
||||
{
|
||||
"confirmed" => CalendarItemStatus.Confirmed,
|
||||
"tentative" => CalendarItemStatus.Tentative,
|
||||
"cancelled" => CalendarItemStatus.Cancelled,
|
||||
_ => CalendarItemStatus.Confirmed
|
||||
};
|
||||
}
|
||||
|
||||
CalendarItemVisibility GetVisibility(string visibility)
|
||||
{
|
||||
/// Visibility of the event. Optional. Possible values are: - "default" - Uses the default visibility for
|
||||
/// events on the calendar. This is the default value. - "public" - The event is public and event details are
|
||||
/// visible to all readers of the calendar. - "private" - The event is private and only event attendees may
|
||||
/// view event details. - "confidential" - The event is private. This value is provided for compatibility
|
||||
/// reasons.
|
||||
|
||||
return visibility switch
|
||||
{
|
||||
"default" => CalendarItemVisibility.Default,
|
||||
"public" => CalendarItemVisibility.Public,
|
||||
"private" => CalendarItemVisibility.Private,
|
||||
"confidential" => CalendarItemVisibility.Confidential,
|
||||
_ => CalendarItemVisibility.Default
|
||||
};
|
||||
}
|
||||
|
||||
// Attendees
|
||||
var attendees = new List<CalendarEventAttendee>();
|
||||
|
||||
if (calendarEvent.Attendees == null)
|
||||
{
|
||||
// Self-only event.
|
||||
|
||||
attendees.Add(new CalendarEventAttendee()
|
||||
{
|
||||
CalendarItemId = calendarItem.Id,
|
||||
IsOrganizer = true,
|
||||
Email = organizerAccount.Address,
|
||||
Name = organizerAccount.SenderName,
|
||||
AttendenceStatus = AttendeeStatus.Accepted,
|
||||
Id = Guid.NewGuid(),
|
||||
IsOptionalAttendee = false,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var attendee in calendarEvent.Attendees)
|
||||
{
|
||||
if (attendee.Self == true)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(attendee.Email))
|
||||
{
|
||||
AttendeeStatus GetAttendenceStatus(string responseStatus)
|
||||
{
|
||||
return responseStatus switch
|
||||
{
|
||||
"accepted" => AttendeeStatus.Accepted,
|
||||
"declined" => AttendeeStatus.Declined,
|
||||
"tentative" => AttendeeStatus.Tentative,
|
||||
"needsAction" => AttendeeStatus.NeedsAction,
|
||||
_ => AttendeeStatus.NeedsAction
|
||||
};
|
||||
}
|
||||
|
||||
var eventAttendee = new CalendarEventAttendee()
|
||||
{
|
||||
CalendarItemId = calendarItem.Id,
|
||||
IsOrganizer = attendee.Organizer ?? false,
|
||||
Comment = attendee.Comment,
|
||||
Email = attendee.Email,
|
||||
Name = attendee.DisplayName,
|
||||
AttendenceStatus = GetAttendenceStatus(attendee.ResponseStatus),
|
||||
Id = Guid.NewGuid(),
|
||||
IsOptionalAttendee = attendee.Optional ?? false,
|
||||
};
|
||||
|
||||
attendees.Add(eventAttendee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await CalendarService.CreateNewCalendarItemAsync(calendarItem, attendees);
|
||||
|
||||
return calendarItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace Wino.Core.Integration.Processors
|
||||
IFolderService folderService,
|
||||
IMailService mailService,
|
||||
IAccountService accountService,
|
||||
IMimeFileService mimeFileService) : base(databaseService, folderService, mailService, accountService, mimeFileService)
|
||||
ICalendarService calendarService,
|
||||
IMimeFileService mimeFileService) : base(databaseService, folderService, mailService, calendarService, accountService, mimeFileService)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,10 @@ namespace Wino.Core.Integration.Processors
|
||||
{
|
||||
public class OutlookChangeProcessor(IDatabaseService databaseService,
|
||||
IFolderService folderService,
|
||||
ICalendarService calendarService,
|
||||
IMailService mailService,
|
||||
IAccountService accountService,
|
||||
IMimeFileService mimeFileService) : DefaultChangeProcessor(databaseService, folderService, mailService, accountService, mimeFileService)
|
||||
IMimeFileService mimeFileService) : DefaultChangeProcessor(databaseService, folderService, mailService, calendarService, accountService, mimeFileService)
|
||||
, IOutlookChangeProcessor
|
||||
{
|
||||
public Task<bool> IsMailExistsAsync(string messageId)
|
||||
|
||||
Reference in New Issue
Block a user