228 lines
11 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|