From 1ed8a47ce66ac598c56f5122c1163bbb1b601def Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 24 Dec 2024 10:28:02 +0530 Subject: [PATCH 1/7] added command to delete contact for certain date range --- lib/Command/DeleteSendgridContact.php | 68 ++++++++++++++++++++++ lib/Service/SendGridService.php | 83 +++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 lib/Command/DeleteSendgridContact.php create mode 100644 lib/Service/SendGridService.php diff --git a/lib/Command/DeleteSendgridContact.php b/lib/Command/DeleteSendgridContact.php new file mode 100644 index 00000000..70c612bd --- /dev/null +++ b/lib/Command/DeleteSendgridContact.php @@ -0,0 +1,68 @@ +sendGridService = $sendGridService; + parent::__construct(); + } + + protected function configure(): void { + $this + ->setName('ecloud-accounts:delete-sendgrid-contacts') + ->setDescription('Delete SendGrid contacts within a specified date range.') + ->addOption( + 'start-date', + null, + InputOption::VALUE_REQUIRED, + 'Start date in format Y-m-d H:i:s', + '' + ) + ->addOption( + 'end-date', + null, + InputOption::VALUE_REQUIRED, + 'End date in format Y-m-d H:i:s', + '' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $startDate = $input->getOption('start-date'); + $endDate = $input->getOption('end-date'); + + if (empty($startDate) || empty($endDate)) { + $output->writeln('Both start-date and end-date options are required.'); + return Command::FAILURE; + } + + try { + $contacts = $this->sendGridService->fetchContactsByDateRange($startDate, $endDate); + $contactIds = array_column($contacts, 'id'); + + if (empty($contactIds)) { + $output->writeln('No contacts found within the specified date range.'); + return Command::SUCCESS; + } + + $this->sendGridService->deleteContacts($contactIds); + $output->writeln('Successfully deleted ' . count($contactIds) . ' contacts.'); + return Command::SUCCESS; + } catch (Exception $e) { + $output->writeln('Error: ' . $e->getMessage()); + return Command::FAILURE; + } + } +} diff --git a/lib/Service/SendGridService.php b/lib/Service/SendGridService.php new file mode 100644 index 00000000..9eb7bbcd --- /dev/null +++ b/lib/Service/SendGridService.php @@ -0,0 +1,83 @@ +config = $config; + $apiKey = $this->config->getSystemValue('sendgrid_api_key', ''); + $this->sendGridClient = new \SendGrid($apiKey); + } + + /** + * Fetch contacts created between the specified date range. + * + * @param string $startDate Format: 'Y-m-d H:i:s' + * @param string $endDate Format: 'Y-m-d H:i:s' + * @return array + * @throws Exception + */ + public function fetchContactsByDateRange(string $startDate, string $endDate): array { + $startTimestamp = strtotime($startDate); + $endTimestamp = strtotime($endDate); + + $contacts = []; + $page = 1; + $pageSize = 100; + + do { + $response = $this->sendGridClient->client->marketing()->contacts()->get(null, $page, $pageSize); + if ($response->statusCode() !== 200) { + throw new Exception("Error fetching contacts: " . $response->body()); + } + + $result = json_decode($response->body(), true); + $fetchedContacts = $result['result'] ?? []; + + foreach ($fetchedContacts as $contact) { + $createdTimestamp = strtotime($contact['created_at']); + if ($createdTimestamp >= $startTimestamp && $createdTimestamp <= $endTimestamp) { + $contacts[] = $contact; + } + } + + if (count($fetchedContacts) < $pageSize) { + break; + } + + $page++; + } while (true); + + return $contacts; + } + + /** + * Delete contacts by their IDs. + * + * @param array $contactIds + * @return void + * @throws Exception + */ + public function deleteContacts(array $contactIds): void { + if (empty($contactIds)) { + throw new Exception("No contacts provided for deletion."); + } + + $requestBody = ['ids' => $contactIds]; + $response = $this->sendGridClient->client->marketing()->contacts()->delete(null, $requestBody); + + if ($response->statusCode() !== 202) { + throw new Exception("Failed to delete contacts. HTTP Code: " . $response->statusCode() . ". Response: " . $response->body()); + } + } +} -- GitLab From d554c76674789d26a91e21b52f36b20fc25f2aa6 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 24 Dec 2024 10:38:29 +0530 Subject: [PATCH 2/7] added command to delete contact for certain date range --- lib/Command/DeleteSendgridContact.php | 34 ++++++++------- lib/Service/SendGridService.php | 59 ++++++++++++++++----------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/lib/Command/DeleteSendgridContact.php b/lib/Command/DeleteSendgridContact.php index 70c612bd..490c6f0b 100644 --- a/lib/Command/DeleteSendgridContact.php +++ b/lib/Command/DeleteSendgridContact.php @@ -11,7 +11,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class DeleteSendGridContactsCommand extends Command { +class DeleteSendgridContactCommand extends Command { private SendGridService $sendGridService; public function __construct(SendGridService $sendGridService) { @@ -21,47 +21,53 @@ class DeleteSendGridContactsCommand extends Command { protected function configure(): void { $this - ->setName('ecloud-accounts:delete-sendgrid-contacts') - ->setDescription('Delete SendGrid contacts within a specified date range.') + ->setName('ecloud-accounts:delete-sendgrid-contact') + ->setDescription('Delete SendGrid contacts within a segment and date range') + ->addOption( + 'segment-id', + null, + InputOption::VALUE_REQUIRED, + 'The ID of the SendGrid segment' + ) ->addOption( 'start-date', null, InputOption::VALUE_REQUIRED, - 'Start date in format Y-m-d H:i:s', - '' + 'Start date in YYYY-MM-DD format' ) ->addOption( 'end-date', null, InputOption::VALUE_REQUIRED, - 'End date in format Y-m-d H:i:s', - '' + 'End date in YYYY-MM-DD format' ); } protected function execute(InputInterface $input, OutputInterface $output): int { + $segmentId = $input->getOption('segment-id'); $startDate = $input->getOption('start-date'); $endDate = $input->getOption('end-date'); - if (empty($startDate) || empty($endDate)) { - $output->writeln('Both start-date and end-date options are required.'); + if (!$segmentId || !$startDate || !$endDate) { + $output->writeln('All options --segment-id, --start-date, and --end-date are required.'); return Command::FAILURE; } try { - $contacts = $this->sendGridService->fetchContactsByDateRange($startDate, $endDate); - $contactIds = array_column($contacts, 'id'); + $contacts = $this->sendGridService->fetchContactsFromSegment($segmentId); + $filteredContacts = $this->sendGridService->filterContactsByDateRange($contacts, $startDate, $endDate); + $contactIds = array_column($filteredContacts, 'id'); if (empty($contactIds)) { - $output->writeln('No contacts found within the specified date range.'); + $output->writeln('No contacts found within the specified date range.'); return Command::SUCCESS; } $this->sendGridService->deleteContacts($contactIds); - $output->writeln('Successfully deleted ' . count($contactIds) . ' contacts.'); + $output->writeln('Successfully deleted ' . count($contactIds) . ' contacts.'); return Command::SUCCESS; } catch (Exception $e) { - $output->writeln('Error: ' . $e->getMessage()); + $output->writeln('Error: ' . $e->getMessage() . ''); return Command::FAILURE; } } diff --git a/lib/Service/SendGridService.php b/lib/Service/SendGridService.php index 9eb7bbcd..99678c72 100644 --- a/lib/Service/SendGridService.php +++ b/lib/Service/SendGridService.php @@ -20,38 +20,31 @@ class SendGridService { } /** - * Fetch contacts created between the specified date range. + * Fetch contacts from a specific segment. * - * @param string $startDate Format: 'Y-m-d H:i:s' - * @param string $endDate Format: 'Y-m-d H:i:s' + * @param string $segmentId * @return array * @throws Exception */ - public function fetchContactsByDateRange(string $startDate, string $endDate): array { - $startTimestamp = strtotime($startDate); - $endTimestamp = strtotime($endDate); - + public function fetchContactsFromSegment(string $segmentId): array { $contacts = []; $page = 1; $pageSize = 100; do { - $response = $this->sendGridClient->client->marketing()->contacts()->get(null, $page, $pageSize); + $response = $this->sendGridClient->client->contactdb()->segments()->_($segmentId)->recipients()->get(null, [ + 'page' => $page, + 'page_size' => $pageSize, + ]); + if ($response->statusCode() !== 200) { - throw new Exception("Error fetching contacts: " . $response->body()); + throw new Exception("Failed to fetch contacts: " . $response->body()); } - $result = json_decode($response->body(), true); - $fetchedContacts = $result['result'] ?? []; + $data = json_decode($response->body(), true); + $contacts = array_merge($contacts, $data['recipients'] ?? []); - foreach ($fetchedContacts as $contact) { - $createdTimestamp = strtotime($contact['created_at']); - if ($createdTimestamp >= $startTimestamp && $createdTimestamp <= $endTimestamp) { - $contacts[] = $contact; - } - } - - if (count($fetchedContacts) < $pageSize) { + if (count($data['recipients'] ?? []) < $pageSize) { break; } @@ -62,10 +55,27 @@ class SendGridService { } /** - * Delete contacts by their IDs. + * Filter contacts by creation date range. + * + * @param array $contacts + * @param string $startDate + * @param string $endDate + * @return array + */ + public function filterContactsByDateRange(array $contacts, string $startDate, string $endDate): array { + $startTimestamp = strtotime($startDate); + $endTimestamp = strtotime($endDate); + + return array_filter($contacts, function ($contact) use ($startTimestamp, $endTimestamp) { + $createdTimestamp = isset($contact['created_at']) ? strtotime($contact['created_at']) : null; + return $createdTimestamp && $createdTimestamp >= $startTimestamp && $createdTimestamp <= $endTimestamp; + }); + } + + /** + * Delete contacts by IDs. * * @param array $contactIds - * @return void * @throws Exception */ public function deleteContacts(array $contactIds): void { @@ -73,11 +83,12 @@ class SendGridService { throw new Exception("No contacts provided for deletion."); } - $requestBody = ['ids' => $contactIds]; - $response = $this->sendGridClient->client->marketing()->contacts()->delete(null, $requestBody); + $response = $this->sendGridClient->client->marketing()->contacts()->delete(null, [ + 'ids' => implode(',', $contactIds), + ]); if ($response->statusCode() !== 202) { - throw new Exception("Failed to delete contacts. HTTP Code: " . $response->statusCode() . ". Response: " . $response->body()); + throw new Exception("Failed to delete contacts: " . $response->body()); } } } -- GitLab From 33d5ebc3e8f30ffb36d2d6ac0a4538ced2be56aa Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 24 Dec 2024 10:54:26 +0530 Subject: [PATCH 3/7] rate limit removed for GET method --- appinfo/info.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/appinfo/info.xml b/appinfo/info.xml index 35a9b216..ed938f4f 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -28,5 +28,6 @@ OCA\EcloudAccounts\Command\Migrate2FASecrets OCA\EcloudAccounts\Command\MigrateWebmailAddressbooks OCA\EcloudAccounts\Command\MapActiveAttributetoLDAP + OCA\EcloudAccounts\Command\DeleteSendgridContact -- GitLab From a5a212bdda46882ae9d78a2c5ce5a1880ee300b3 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 24 Dec 2024 10:54:54 +0530 Subject: [PATCH 4/7] rate limit removed for GET method --- lib/Command/DeleteSendgridContact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Command/DeleteSendgridContact.php b/lib/Command/DeleteSendgridContact.php index 490c6f0b..58da34d7 100644 --- a/lib/Command/DeleteSendgridContact.php +++ b/lib/Command/DeleteSendgridContact.php @@ -11,7 +11,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class DeleteSendgridContactCommand extends Command { +class DeleteSendgridContact extends Command { private SendGridService $sendGridService; public function __construct(SendGridService $sendGridService) { -- GitLab From 6a91a7e5a86611835521bd9a6674e499e27e5927 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 24 Dec 2024 11:19:18 +0530 Subject: [PATCH 5/7] added static apikey --- lib/Service/SendGridService.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/Service/SendGridService.php b/lib/Service/SendGridService.php index 99678c72..82bca049 100644 --- a/lib/Service/SendGridService.php +++ b/lib/Service/SendGridService.php @@ -15,7 +15,7 @@ class SendGridService { public function __construct(IConfig $config) { $this->config = $config; - $apiKey = $this->config->getSystemValue('sendgrid_api_key', ''); + $apiKey = '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'; $this->sendGridClient = new \SendGrid($apiKey); } @@ -62,16 +62,28 @@ class SendGridService { * @param string $endDate * @return array */ - public function filterContactsByDateRange(array $contacts, string $startDate, string $endDate): array { - $startTimestamp = strtotime($startDate); - $endTimestamp = strtotime($endDate); + public function filterContactsByDateRange($contacts, $startDate, $endDate) { + $startTimestamp = is_int($startDate) ? $startDate : strtotime($startDate); + $endTimestamp = is_int($endDate) ? $endDate : strtotime($endDate); return array_filter($contacts, function ($contact) use ($startTimestamp, $endTimestamp) { - $createdTimestamp = isset($contact['created_at']) ? strtotime($contact['created_at']) : null; - return $createdTimestamp && $createdTimestamp >= $startTimestamp && $createdTimestamp <= $endTimestamp; + // Check if `created_at` exists and is numeric + if (!isset($contact['created_at']) || !is_numeric($contact['created_at'])) { + echo "Skipping: Missing or non-numeric created_at.\n"; + return false; + } + + $createdTimestamp = (int) $contact['created_at']; + // Check if the timestamp falls within the range + if ($createdTimestamp >= $startTimestamp && $createdTimestamp <= $endTimestamp) { + return true; + } else { + return false; + } }); } + /** * Delete contacts by IDs. * -- GitLab From 8f598172f5cd994f4840ab7264cf91f75333e756 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 24 Dec 2024 11:34:09 +0530 Subject: [PATCH 6/7] refresh segment added --- appinfo/info.xml | 1 + lib/Command/RefreshSendGridSegment.php | 65 ++++++++++++++++++++++++++ lib/Service/SendGridService.php | 25 ++++++++++ 3 files changed, 91 insertions(+) create mode 100644 lib/Command/RefreshSendGridSegment.php diff --git a/appinfo/info.xml b/appinfo/info.xml index ed938f4f..7ccd4f7b 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -29,5 +29,6 @@ OCA\EcloudAccounts\Command\MigrateWebmailAddressbooks OCA\EcloudAccounts\Command\MapActiveAttributetoLDAP OCA\EcloudAccounts\Command\DeleteSendgridContact + OCA\EcloudAccounts\Command\RefreshSendGridSegment diff --git a/lib/Command/RefreshSendGridSegment.php b/lib/Command/RefreshSendGridSegment.php new file mode 100644 index 00000000..2b8b7e9e --- /dev/null +++ b/lib/Command/RefreshSendGridSegment.php @@ -0,0 +1,65 @@ +sendGridService = $sendGridService; + parent::__construct(); + } + + protected function configure(): void { + $this + ->setName('ecloud-accounts:refresh-sendgrid-segment') + ->setDescription('Refreshes the SendGrid segment') + ->addOption( + 'segment-id', + null, + InputOption::VALUE_REQUIRED, + 'The ID of the SendGrid segment' + ) + ->addOption( + 'refresh', + null, + InputOption::VALUE_NONE, + 'Trigger the refresh of the SendGrid segment' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + + if ($input->getOption('refresh')) { + $segmentId = $input->getOption('segment-id'); + + if (!$segmentId) { + $output->writeln('option --segment-id is required.'); + return Command::FAILURE; + } + try { + $success = $this->sendGridService->refreshSendGridSegment($segmentId); + if ($success) { + $output->writeln('Segment refreshed successfully.'); + return Command::SUCCESS; + } + } catch (Exception $e) { + $output->writeln('Error: ' . $e->getMessage() . ''); + return Command::FAILURE; + } + return 0; + } + + $output->writeln('No action taken.'); + return 0; + } + +} diff --git a/lib/Service/SendGridService.php b/lib/Service/SendGridService.php index 82bca049..5e0c8437 100644 --- a/lib/Service/SendGridService.php +++ b/lib/Service/SendGridService.php @@ -12,10 +12,12 @@ use OCP\IConfig; class SendGridService { private \SendGrid $sendGridClient; private $config; + private $apiKey; public function __construct(IConfig $config) { $this->config = $config; $apiKey = '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'; + $this->apiKey = $apiKey; $this->sendGridClient = new \SendGrid($apiKey); } @@ -103,4 +105,27 @@ class SendGridService { throw new Exception("Failed to delete contacts: " . $response->body()); } } + + public function refreshSendGridSegment($segmentId) { + $data = [ + 'user_time_zone' => 'America/Chicago' + ]; + + try { + $response = $this->sendGridClient->client + ->marketing() + ->segments() + ->_($segmentId) + ->refresh() + ->post($data); + + if ($response->statusCode() === 202) { + return true; + } else { + throw new Exception("Failed to delete contacts: " . $response->body()); + } + } catch (Exception $e) { + throw new Exception('Caught exception: ' . $e->getMessage()); + } + } } -- GitLab From 181dba658a9e199645a3d5b06dbd159d9764c8e7 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Tue, 24 Dec 2024 12:14:40 +0530 Subject: [PATCH 7/7] msg updated --- lib/Service/SendGridService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/SendGridService.php b/lib/Service/SendGridService.php index 5e0c8437..1e835d2e 100644 --- a/lib/Service/SendGridService.php +++ b/lib/Service/SendGridService.php @@ -122,7 +122,7 @@ class SendGridService { if ($response->statusCode() === 202) { return true; } else { - throw new Exception("Failed to delete contacts: " . $response->body()); + throw new Exception("Failed to refresh contacts: " . $response->body()); } } catch (Exception $e) { throw new Exception('Caught exception: ' . $e->getMessage()); -- GitLab