CalDav synchronizer, new IMAP setup/edit page.
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
public class CalendarIcsFileService : ICalendarIcsFileService
|
||||
{
|
||||
private readonly INativeAppService _nativeAppService;
|
||||
private readonly ILogger _logger = Log.ForContext<CalendarIcsFileService>();
|
||||
|
||||
public CalendarIcsFileService(INativeAppService nativeAppService)
|
||||
{
|
||||
_nativeAppService = nativeAppService;
|
||||
}
|
||||
|
||||
public async Task SaveCalendarItemIcsAsync(Guid accountId, Guid calendarId, Guid calendarItemId, string remoteEventId, string remoteResourceHref, string eTag, string icsContent)
|
||||
{
|
||||
if (accountId == Guid.Empty || calendarId == Guid.Empty || calendarItemId == Guid.Empty || string.IsNullOrWhiteSpace(icsContent))
|
||||
return;
|
||||
|
||||
var folderPath = await GetCalendarItemFolderPathAsync(accountId, calendarId, calendarItemId).ConfigureAwait(false);
|
||||
var icsPath = Path.Combine(folderPath, "event.ics");
|
||||
var metaPath = Path.Combine(folderPath, "event.meta.json");
|
||||
|
||||
try
|
||||
{
|
||||
await File.WriteAllTextAsync(icsPath, icsContent).ConfigureAwait(false);
|
||||
|
||||
var metadataContent = string.Join(
|
||||
Environment.NewLine,
|
||||
$"CalendarItemId={calendarItemId:N}",
|
||||
$"RemoteEventId={remoteEventId ?? string.Empty}",
|
||||
$"RemoteResourceHref={remoteResourceHref ?? string.Empty}",
|
||||
$"ETag={eTag ?? string.Empty}",
|
||||
$"UpdatedAtUtc={DateTime.UtcNow:O}");
|
||||
|
||||
await File.WriteAllTextAsync(metaPath, metadataContent).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Failed to save ICS file for account {AccountId} and calendar item {CalendarItemId}", accountId, calendarItemId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteCalendarItemIcsAsync(Guid accountId, Guid calendarItemId)
|
||||
{
|
||||
if (accountId == Guid.Empty || calendarItemId == Guid.Empty)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var accountRootPath = await GetAccountCalendarsRootPathAsync(accountId).ConfigureAwait(false);
|
||||
if (!Directory.Exists(accountRootPath))
|
||||
return;
|
||||
|
||||
var calendarDirectories = Directory.GetDirectories(accountRootPath);
|
||||
|
||||
foreach (var calendarDirectory in calendarDirectories)
|
||||
{
|
||||
var itemPath = Path.Combine(calendarDirectory, calendarItemId.ToString("N"));
|
||||
if (Directory.Exists(itemPath))
|
||||
{
|
||||
Directory.Delete(itemPath, recursive: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Failed to delete ICS folder for account {AccountId} and calendar item {CalendarItemId}", accountId, calendarItemId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteCalendarIcsForCalendarAsync(Guid accountId, Guid calendarId)
|
||||
{
|
||||
if (accountId == Guid.Empty || calendarId == Guid.Empty)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var calendarPath = await GetCalendarFolderPathAsync(accountId, calendarId).ConfigureAwait(false);
|
||||
if (Directory.Exists(calendarPath))
|
||||
{
|
||||
Directory.Delete(calendarPath, recursive: true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Failed to delete ICS folder for account {AccountId} and calendar {CalendarId}", accountId, calendarId);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetCalendarItemFolderPathAsync(Guid accountId, Guid calendarId, Guid calendarItemId)
|
||||
{
|
||||
var calendarPath = await GetCalendarFolderPathAsync(accountId, calendarId).ConfigureAwait(false);
|
||||
var itemDirectory = Path.Combine(calendarPath, calendarItemId.ToString("N"));
|
||||
Directory.CreateDirectory(itemDirectory);
|
||||
return itemDirectory;
|
||||
}
|
||||
|
||||
private async Task<string> GetCalendarFolderPathAsync(Guid accountId, Guid calendarId)
|
||||
{
|
||||
var accountRootPath = await GetAccountCalendarsRootPathAsync(accountId).ConfigureAwait(false);
|
||||
var calendarDirectory = Path.Combine(accountRootPath, calendarId.ToString("N"));
|
||||
Directory.CreateDirectory(calendarDirectory);
|
||||
return calendarDirectory;
|
||||
}
|
||||
|
||||
private async Task<string> GetAccountCalendarsRootPathAsync(Guid accountId)
|
||||
{
|
||||
var root = await GetIcsRootPathAsync().ConfigureAwait(false);
|
||||
var accountPath = Path.Combine(root, accountId.ToString("N"), "calendars");
|
||||
Directory.CreateDirectory(accountPath);
|
||||
return accountPath;
|
||||
}
|
||||
|
||||
private async Task<string> GetIcsRootPathAsync()
|
||||
{
|
||||
var mimeRootPath = await _nativeAppService.GetMimeMessageStoragePath().ConfigureAwait(false);
|
||||
var icsRootPath = Path.Combine(mimeRootPath, "CalendarIcs");
|
||||
Directory.CreateDirectory(icsRootPath);
|
||||
return icsRootPath;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user