using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using MimeKit; using Serilog; using SqlKata; using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Interfaces; using Wino.Services.Extensions; namespace Wino.Services; public class ContactService : BaseDatabaseService, IContactService { public ContactService(IDatabaseService databaseService) : base(databaseService) { } public async Task CreateNewContactAsync(string address, string displayName) { var contact = new AccountContact() { Address = address, Name = displayName }; await Connection.InsertAsync(contact, typeof(AccountContact)).ConfigureAwait(false); return contact; } public Task> GetAddressInformationAsync(string queryText) { if (queryText == null || queryText.Length < 2) return Task.FromResult>(null); var query = new Query(nameof(AccountContact)); query.WhereContains("Address", queryText); query.OrWhereContains("Name", queryText); var rawLikeQuery = query.GetRawQuery(); return Connection.QueryAsync(rawLikeQuery); } public Task GetAddressInformationByAddressAsync(string address) => Connection.Table().FirstOrDefaultAsync(a => a.Address == address); public async Task SaveAddressInformationAsync(MimeMessage message) { var recipients = message .GetRecipients(true) .Where(a => !string.IsNullOrEmpty(a.Name) && !string.IsNullOrEmpty(a.Address)); var addressInformations = recipients.Select(a => new AccountContact() { Name = a.Name, Address = a.Address }); foreach (var info in addressInformations) { var currentContact = await GetAddressInformationByAddressAsync(info.Address).ConfigureAwait(false); try { if (currentContact == null) { await Connection.InsertAsync(info, typeof(AccountContact)).ConfigureAwait(false); } else if (!currentContact.IsRootContact && !currentContact.IsOverridden) // Don't update root contacts or overridden contacts. { await Connection.InsertOrReplaceAsync(info, typeof(AccountContact)).ConfigureAwait(false); } } catch (Exception ex) { Log.Error("Failed to add contact information to the database.", ex); } } } public Task> GetAllContactsAsync() { return Connection.Table().ToListAsync(); } public Task> SearchContactsAsync(string searchQuery) { if (string.IsNullOrWhiteSpace(searchQuery)) return GetAllContactsAsync(); var query = new Query(nameof(AccountContact)); query.WhereContains("Address", searchQuery.Trim()); query.OrWhereContains("Name", searchQuery.Trim()); var rawLikeQuery = query.GetRawQuery(); return Connection.QueryAsync(rawLikeQuery); } public async Task UpdateContactAsync(AccountContact contact) { // Mark the contact as overridden when manually updated contact.IsOverridden = true; await Connection.UpdateAsync(contact, typeof(AccountContact)).ConfigureAwait(false); return contact; } public async Task DeleteContactAsync(string address) { var contact = await GetAddressInformationByAddressAsync(address).ConfigureAwait(false); if (contact != null && !contact.IsRootContact) { await Connection.DeleteAsync(contact).ConfigureAwait(false); } } public async Task DeleteContactsAsync(IEnumerable addresses) { foreach (var address in addresses) { await DeleteContactAsync(address).ConfigureAwait(false); } } }