Skip to content

Commit

Permalink
clarify contact import, use google contact id as NC card URI, update …
Browse files Browse the repository at this point in the history
…contacts with more recent update time

Signed-off-by: Julien Veyssier <[email protected]>
  • Loading branch information
julien-nc committed Dec 29, 2022
1 parent 3ebb66c commit f603db7
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 38 deletions.
89 changes: 52 additions & 37 deletions lib/Service/GoogleContactsAPIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public function getContactList(string $userId): Generator {
* @return array
*/
public function importContacts(string $userId, ?string $uri, int $key, ?string $newAddrBookName): array {
$existingAddressBook = null;
if ($key === 0) {
$addressBooks = $this->contactsManager->getUserAddressBooks();
foreach ($addressBooks as $k => $ab) {
Expand All @@ -180,19 +181,48 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
if (!$addressBook) {
return ['error' => 'no such address book'];
}
$existingAddressBook = $addressBook;
}

$groupsById = $this->getContactGroupsById($userId);
$contacts = $this->getContactList($userId);
$nbAdded = 0;
$nbUpdated = 0;
$totalContactNumber = 0;
foreach ($contacts as $k => $c) {
$totalContactNumber++;
// avoid existing contacts
if ($this->contactExists($c, $key)) {
$this->logger->debug('Skipping contact which already exists', ['contact' => $c, 'app' => Application::APP_ID]);

$googleResourceName = $c['resourceName'] ?? null;
if ($googleResourceName === null) {
$this->logger->debug('Skipping contact with no resourceName', ['contact' => $c, 'app' => Application::APP_ID]);
continue;
}
// contacts are not displayed in the Contacts app if there are slashes in their URI...
$googleResourceName = str_replace('/', '_', $googleResourceName);

// check if contact exists and needs to be updated
$existingContact = null;
if ($existingAddressBook !== null) {
$existingContact = $this->cdBackend->getCard($key, $googleResourceName);
if ($existingContact) {
$googleUpdateTime = $c['metadata']['sources'][0]['updateTime'] ?? null;
if ($googleUpdateTime === null) {
$googleUpdateTimestamp = 0;
} else {
try {
$googleUpdateTimestamp = (new Datetime($googleUpdateTime))->getTimestamp();
} catch (Exception | Throwable $e) {
$googleUpdateTimestamp = 0;
}
}

if ($googleUpdateTimestamp <= $existingContact['lastmodified']) {
$this->logger->debug('Skipping existing contact which is up-to-date', ['contact' => $c, 'app' => Application::APP_ID]);
continue;
}
}
}

$vCard = new VCard();

$displayName = '';
Expand Down Expand Up @@ -406,11 +436,20 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
}
}

try {
$this->cdBackend->createCard($key, 'goog' . $k, $vCard->serialize());
$nbAdded++;
} catch (Throwable | Exception $e) {
$this->logger->warning('Error when creating contact', ['exception' => $e, 'app' => Application::APP_ID]);
if ($existingContact === null || $existingContact === false) {
try {
$this->cdBackend->createCard($key, $googleResourceName, $vCard->serialize());
$nbAdded++;
} catch (Throwable|Exception $e) {
$this->logger->warning('Error when creating contact', ['exception' => $e, 'contact' => $c, 'app' => Application::APP_ID]);
}
} else {
try {
$this->cdBackend->updateCard($key, $googleResourceName, $vCard->serialize());
$nbUpdated++;
} catch (Throwable|Exception $e) {
$this->logger->warning('Error when updating contact', ['exception' => $e, 'contact' => $c, 'app' => Application::APP_ID]);
}
}
}
$this->logger->debug($totalContactNumber . ' contacts seen', ['app' => Application::APP_ID]);
Expand All @@ -419,34 +458,10 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
if (isset($contactGeneratorReturn['error'])) {
return $contactGeneratorReturn;
}
return ['nbAdded' => $nbAdded];
}

/**
* @param array $contact
* @param int $addressBookKey
* @return bool
*/
private function contactExists(array $contact, int $addressBookKey): bool {
$displayName = null;
// $familyName = null;
// $firstName = null;
if (isset($contact['names']) && is_array($contact['names'])) {
foreach ($contact['names'] as $n) {
$displayName = $n['displayName'] ?? '';
// $familyName = $n['familyName'] ?? '';
// $firstName = $n['givenName'] ?? '';
break;
}
if ($displayName) {
$searchResult = $this->contactsManager->search($displayName, ['FN']);
foreach ($searchResult as $resContact) {
if ($resContact['FN'] === $displayName && (int)$resContact['addressbook-key'] === $addressBookKey) {
return true;
}
}
}
}
return false;
return [
'nbSeen' => $totalContactNumber,
'nbAdded' => $nbAdded,
'nbUpdated' => $nbUpdated,
];
}
}
10 changes: 9 additions & 1 deletion src/components/PersonalSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -640,9 +640,17 @@ export default {
const url = generateUrl('/apps/integration_google/import-contacts')
axios.get(url, req)
.then((response) => {
const nbSeen = response.data.nbSeen
const nbAdded = response.data.nbAdded
const nbUpdated = response.data.nbUpdated
showSuccess(
this.n('integration_google', '{number} contact successfully imported in {name}', '{number} contacts successfully imported in {name}', nbAdded, { number: nbAdded, name: this.selectedAddressBookName })
this.n(
'integration_google',
'{nbSeen} Google contact seen. {nbAdded} added, {nbUpdated} updated in {name}',
'{nbSeen} Google contacts seen. {nbAdded} added, {nbUpdated} updated in {name}',
nbSeen,
{ nbAdded, nbSeen, nbUpdated, name: this.selectedAddressBookName }
)
)
this.showAddressBooks = false
})
Expand Down

0 comments on commit f603db7

Please sign in to comment.