starface-outlook-sync-addin/src/StarfaceOutlookSync/Services/SyncEngine.cs

228 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using StarfaceOutlookSync.Models;
namespace StarfaceOutlookSync.Services
{
public class SyncEngine
{
private readonly ProfileManager _profileManager = new ProfileManager();
private readonly OutlookContactsService _outlookService = new OutlookContactsService();
public event Action<string> OnProgress;
private void Log(string message) => OnProgress?.Invoke(message);
private static UnifiedContact FindMatch(UnifiedContact contact, List<UnifiedContact> candidates)
{
// Erst E-Mail-Match
if (!string.IsNullOrEmpty(contact.Email))
{
var byEmail = candidates.FirstOrDefault(c =>
!string.IsNullOrEmpty(c.Email) &&
c.Email.Equals(contact.Email, StringComparison.OrdinalIgnoreCase));
if (byEmail != null) return byEmail;
}
// Dann Name-Match
if (!string.IsNullOrEmpty(contact.FirstName) || !string.IsNullOrEmpty(contact.LastName))
{
var byName = candidates.FirstOrDefault(c =>
c.FirstName.Equals(contact.FirstName, StringComparison.OrdinalIgnoreCase) &&
c.LastName.Equals(contact.LastName, StringComparison.OrdinalIgnoreCase) &&
(!string.IsNullOrEmpty(c.FirstName) || !string.IsNullOrEmpty(c.LastName)));
if (byName != null) return byName;
}
return null;
}
public async Task<SyncResult> SyncProfileAsync(SyncProfile profile)
{
var result = new SyncResult
{
ProfileName = profile.Name,
Timestamp = DateTime.Now.ToString("o")
};
try
{
// Starface verbinden
Log("Verbinde mit Starface...");
using (var starface = new StarfaceApiClient(profile.StarfaceConnection))
{
starface.OnDebug += (msg) => Log(msg);
var loginOk = await starface.LoginAsync();
if (!loginOk)
{
result.ErrorMessages.Add("Starface-Login fehlgeschlagen");
result.Errors++;
return result;
}
var mappings = _profileManager.GetMappings(profile.Id);
var mappingByOutlook = mappings.ToDictionary(m => m.OutlookEntryId, m => m);
var mappingByStarface = mappings.ToDictionary(m => m.StarfaceId, m => m);
// Kontakte laden
Log("Lade Outlook-Kontakte...");
var outlookContacts = _outlookService.GetContacts(profile.OutlookFolderPath);
Log($"{outlookContacts.Count} Outlook-Kontakte geladen");
Log("Lade Starface-Kontakte...");
var starfaceContacts = await starface.GetContactsAsync(profile.StarfaceAddressBook);
Log($"{starfaceContacts.Count} Starface-Kontakte geladen");
// Outlook -> Starface
if (profile.SyncDirection == SyncDirection.Both ||
profile.SyncDirection == SyncDirection.OutlookToStarface)
{
Log("Synchronisiere Outlook -> Starface...");
foreach (var oc in outlookContacts)
{
try
{
SyncMapping existing = null;
if (!string.IsNullOrEmpty(oc.OutlookEntryId))
mappingByOutlook.TryGetValue(oc.OutlookEntryId, out existing);
if (existing != null)
{
var hash = oc.GetHash();
if (hash != existing.LastSyncHash)
{
if (await starface.UpdateContactAsync(existing.StarfaceId, oc, profile.StarfaceAddressBook))
{
existing.LastSyncHash = hash;
result.Updated++;
}
}
}
else
{
var match = FindMatch(oc, starfaceContacts);
if (match != null && !string.IsNullOrEmpty(match.StarfaceId))
{
if (await starface.UpdateContactAsync(match.StarfaceId, oc, profile.StarfaceAddressBook))
{
_profileManager.AddOrUpdateMapping(new SyncMapping
{
ProfileId = profile.Id,
OutlookEntryId = oc.OutlookEntryId,
StarfaceId = match.StarfaceId,
LastSyncHash = oc.GetHash()
});
result.Updated++;
}
}
else
{
var created = await starface.CreateContactAsync(oc, profile.StarfaceAddressBook);
if (created != null && !string.IsNullOrEmpty(created.StarfaceId))
{
_profileManager.AddOrUpdateMapping(new SyncMapping
{
ProfileId = profile.Id,
OutlookEntryId = oc.OutlookEntryId,
StarfaceId = created.StarfaceId,
LastSyncHash = oc.GetHash()
});
result.Created++;
}
}
}
}
catch (Exception ex)
{
result.Errors++;
result.ErrorMessages.Add($"{oc.DisplayName}: {ex.Message}");
}
}
}
// Starface -> Outlook
if (profile.SyncDirection == SyncDirection.Both ||
profile.SyncDirection == SyncDirection.StarfaceToOutlook)
{
Log("Synchronisiere Starface -> Outlook...");
foreach (var sc in starfaceContacts)
{
try
{
SyncMapping existing = null;
if (!string.IsNullOrEmpty(sc.StarfaceId))
mappingByStarface.TryGetValue(sc.StarfaceId, out existing);
if (existing != null)
{
var hash = sc.GetHash();
if (hash != existing.LastSyncHash)
{
if (_outlookService.UpdateContact(existing.OutlookEntryId, sc))
{
existing.LastSyncHash = hash;
result.Updated++;
}
}
}
else
{
var match = FindMatch(sc, outlookContacts);
if (match != null && !string.IsNullOrEmpty(match.OutlookEntryId))
{
if (_outlookService.UpdateContact(match.OutlookEntryId, sc))
{
_profileManager.AddOrUpdateMapping(new SyncMapping
{
ProfileId = profile.Id,
OutlookEntryId = match.OutlookEntryId,
StarfaceId = sc.StarfaceId,
LastSyncHash = sc.GetHash()
});
result.Updated++;
}
}
else
{
var created = _outlookService.CreateContact(sc, profile.OutlookFolderPath);
if (created != null && !string.IsNullOrEmpty(created.OutlookEntryId))
{
_profileManager.AddOrUpdateMapping(new SyncMapping
{
ProfileId = profile.Id,
OutlookEntryId = created.OutlookEntryId,
StarfaceId = sc.StarfaceId,
LastSyncHash = sc.GetHash()
});
result.Created++;
}
}
}
}
catch (Exception ex)
{
result.Errors++;
result.ErrorMessages.Add($"{sc.DisplayName}: {ex.Message}");
}
}
}
_profileManager.UpdateLastSync(profile.Id);
_profileManager.SaveMappings(profile.Id, mappings);
await starface.LogoutAsync();
Log("Synchronisation abgeschlossen!");
}
}
catch (Exception ex)
{
result.Errors++;
result.ErrorMessages.Add($"Allgemeiner Fehler: {ex.Message}");
}
return result;
}
}
}