diff --git a/app/lib/helpscout/api.rb b/app/lib/helpscout/api.rb index c0538c7a9..b16585240 100644 --- a/app/lib/helpscout/api.rb +++ b/app/lib/helpscout/api.rb @@ -7,6 +7,8 @@ class Helpscout::API PHONES = 'phones' OAUTH2_TOKEN = 'oauth2/token' + RATELIMIT_KEY = "helpscout-rate-limit-remaining" + def ready? required_secrets = [ Rails.application.secrets.helpscout[:mailbox_id], @@ -42,6 +44,30 @@ class Helpscout::API call_api(:post, CONVERSATIONS, body) end + def list_old_conversations(status, before, page: 1) + body = { + page:, + status:, # active, open, closed, pending, spam. "all" does not work + query: "( + modifiedAt:[* TO #{before.iso8601}] + )", + sortField: "modifiedAt", + sortOrder: "desc" + } + + response = call_api(:get, "#{CONVERSATIONS}?#{body.to_query}") + if !response.success? + raise StandardError, "Error while listing conversations: #{response.response_code} '#{response.body}'" + end + + body = parse_response_body(response) + [body[:_embedded][:conversations], body[:page]] + end + + def delete_conversation(conversation_id) + call_api(:delete, "#{CONVERSATIONS}/#{conversation_id}") + end + def add_phone_number(email, phone) query = CGI.escape("(email:#{email})") response = call_api(:get, "#{CUSTOMERS}?mailbox=#{user_support_mailbox_id}&query=#{query}") @@ -129,6 +155,13 @@ class Helpscout::API body: body.to_json, headers: headers }) + when :delete + Typhoeus.delete(url, { + body: body.to_json, + headers: headers + }) + end.tap do |response| + Rails.cache.write(RATELIMIT_KEY, response.headers["X-Ratelimit-Remaining-Minute"], expires_in: 1.minute) end end diff --git a/app/tasks/maintenance/helpscout_delete_old_conversations_task.rb b/app/tasks/maintenance/helpscout_delete_old_conversations_task.rb new file mode 100644 index 000000000..cbe388fb1 --- /dev/null +++ b/app/tasks/maintenance/helpscout_delete_old_conversations_task.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Maintenance + class HelpscoutDeleteOldConversationsTask < MaintenanceTasks::Task + # Delete Helpscout conversations not modified in the last 2 years, given a status. + # In order to delete all conversations, this task must be invoked 4 times + # for the 4 status: active, closed, spam, pending. + # Respects the Helpscount API rate limit (200 calls per minute). + + attribute :status, :string # active, closed, spam, or pending + validates :status, presence: true + + MODIFIED_BEFORE = 2.years.freeze + + throttle_on do + limit = Rails.cache.read(Helpscout::API::RATELIMIT_KEY) + limit.present? && limit == 0 + end + + def count + _conversations, pagination = api.list_old_conversations(status, modified_before) + + pagination[:totalElements] + end + + # Because conversations are deleted progressively, + # ignore cursor and always pick the first page + def enumerator_builder(cursor:) + Enumerator.new do |yielder| + loop do + conversations, pagination = api.list_old_conversations(status, modified_before) + conversations.each do |conversation| + yielder.yield(conversation[:id], nil) # don't care about cursor parameter + end + + # "number" is the current page (always 1 in our case) + # iterate until there are no remaining pages + break if pagination[:totalPages] == pagination[:number] + end + end + end + + def process(conversation_id) + @api.delete_conversation(conversation_id) + end + + private + + def api + @api ||= Helpscout::API.new + end + + def modified_before + MODIFIED_BEFORE.ago.utc.beginning_of_day + end + end +end diff --git a/spec/fixtures/cassettes/helpscout_list_old_conversations.yml b/spec/fixtures/cassettes/helpscout_list_old_conversations.yml new file mode 100644 index 000000000..e712fbb47 --- /dev/null +++ b/spec/fixtures/cassettes/helpscout_list_old_conversations.yml @@ -0,0 +1,226 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.helpscout.net/v2/oauth2/token + body: + encoding: UTF-8 + string: client_id=1234&client_secret=5678&grant_type=client_credentials + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Date: + - Tue, 11 Jun 2024 14:13:26 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '94' + Server: + - kong/0.14.1 + Cache-Control: + - no-store + Pragma: + - no-cache + Access-Control-Allow-Origin: + - "*" + Access-Control-Expose-Headers: + - Location,Resource-Id + body: + encoding: UTF-8 + string: '{"token_type":"bearer","access_token":"redacted","expires_in":172800}' + recorded_at: Wed, 05 Jun 2024 00:00:00 GMT +- request: + method: get + uri: https://api.helpscout.net/v2/conversations?page=1&query=(%0A%20%20%20%20%20%20%20%20modifiedAt:%5B*%20TO%202022-06-05T00:00:00Z%5D%0A%20%20%20%20%20%20)&sortField=modifiedAt&sortOrder=desc&status=closed + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Authorization: + - Bearer redacted + Content-Type: + - application/json; charset=UTF-8 + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Date: + - Tue, 11 Jun 2024 14:13:27 GMT + Content-Type: + - application/hal+json + X-Ratelimit-Limit-Minute: + - '200' + X-Ratelimit-Remaining-Minute: + - '199' + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - '0' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - '0' + X-Frame-Options: + - DENY + Access-Control-Allow-Origin: + - "*" + Access-Control-Expose-Headers: + - Location,Resource-Id + Correlation-Id: + - a9ca7664-2711-4c36-a092-73203365b474#13211836 + X-Kong-Upstream-Latency: + - '640' + X-Kong-Proxy-Latency: + - '3' + Via: + - kong/0.14.1 + body: + encoding: UTF-8 + string: '{"_embedded":{"conversations":[{"id":1910642153,"number":1978770,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Re: + Demande de création de compte","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T23:34:03Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T23:34:04Z","userUpdatedAt":"2022-06-04T23:34:04Z","customerWaitingSince":{"time":"2022-06-04T23:34:04Z","friendly":"Jun + 5, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910642153"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533578452"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533578452"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910642153/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910642153/1978770"}},"assignee":{}},{"id":1910621183,"number":1978769,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Re: + Demande de création de compte","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T22:52:48Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T22:52:48Z","userUpdatedAt":"2022-06-04T22:52:48Z","customerWaitingSince":{"time":"2022-06-04T22:52:48Z","friendly":"Jun + 5, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910621183"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533578452"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533578452"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910621183/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910621183/1978769"}},"assignee":{}},{"id":1910573873,"number":1978767,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Une demande de transfert de dossier vous est adressée","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T21:20:15Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T21:20:17Z","userUpdatedAt":"2022-06-04T21:20:15Z","customerWaitingSince":{"time":"2022-06-04T21:20:15Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910573873"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533568101"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533568101"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910573873/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910573873/1978767"}},"assignee":{}},{"id":1910547792,"number":1978766,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Votre dossier nº 6988215 a été classé sans suite (Demande de premier titre + de séjour vie privée et familiale)","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T20:34:17Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T20:34:17Z","userUpdatedAt":"2022-06-04T20:34:17Z","customerWaitingSince":{"time":"2022-06-04T20:34:17Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910547792"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/485472353"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/485472353"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910547792/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910547792/1978766"}},"assignee":{}},{"id":1910474797,"number":1978763,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Nouveau message pour votre dossier nº 5172954 « Demande d''un premier titre + de séjour -VIE PRIVEE ET FAMILIALE ------------- -CITOYEN UE ET FAMILLE -REFUGIE, + PROTECTION SUBSIDIAIRE, APATRIDE-- -VISITEUR-- Préfecture de Nanterre »","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T18:30:40Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T18:30:40Z","userUpdatedAt":"2022-06-04T18:30:40Z","customerWaitingSince":{"time":"2022-06-04T18:30:40Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910474797"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533546294"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533546294"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910474797/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910474797/1978763"}},"assignee":{}},{"id":1910462923,"number":1978761,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Faire + une nouvelle demande de titre séjour","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T18:11:21Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T18:11:21Z","userUpdatedAt":"2022-06-04T18:11:21Z","customerWaitingSince":{"time":"2022-06-04T18:11:21Z","friendly":"Jun + 4, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"},{"id":6885035,"color":"#A5B2BD","tag":"other"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910462923"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533543448"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533543448"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910462923/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910462923/1978761"}},"assignee":{}},{"id":1910327544,"number":1978755,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"reactivation + de numero NEPH","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T14:49:14Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T14:49:14Z","userUpdatedAt":"2022-06-04T14:49:14Z","customerWaitingSince":{"time":"2022-06-04T14:49:14Z","friendly":"Jun + 4, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910327544"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533513486"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533513486"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910327544/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910327544/1978755"}},"assignee":{}},{"id":1910270744,"number":1978750,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"[Free + Report] The State of Productivity 2022","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T13:18:23Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T13:18:23Z","userUpdatedAt":"2022-06-04T13:18:23Z","customerWaitingSince":{"time":"2022-06-04T13:18:23Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910270744"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/457241695"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/457241695"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910270744/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910270744/1978750"}},"assignee":{}},{"id":1910265845,"number":1978749,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Titre + de séjour , numéro étranger : 9914064788","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T13:09:52Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T13:09:52Z","userUpdatedAt":"2022-06-04T13:09:52Z","customerWaitingSince":{"time":"2022-06-04T13:09:52Z","friendly":"Jun + 4, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910265845"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533500019"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533500019"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910265845/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910265845/1978749"}},"assignee":{}},{"id":1910174669,"number":1978744,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Votre dossier nº 6779552 a été accepté (CPAM 75 - CONVENTIONNEMENT DES TAXIS + PARISIENS)","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T10:17:58Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T10:17:58Z","userUpdatedAt":"2022-06-04T10:17:58Z","customerWaitingSince":{"time":"2022-06-04T10:17:58Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910174669"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533480456"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533480456"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910174669/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910174669/1978744"}},"assignee":{}},{"id":1910154851,"number":1978743,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re :Nouveau + message pour votre dossier nº 5528204 « ARSIF - Procédure d’autorisation d’exercice + des médecins à diplômes hors UE (PADHUE) »","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T09:35:53Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T09:35:53Z","userUpdatedAt":"2022-06-04T09:35:53Z","customerWaitingSince":{"time":"2022-06-04T09:35:53Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910154851"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533476412"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533476412"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910154851/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910154851/1978743"}},"assignee":{}},{"id":1910119695,"number":1978739,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Demande + de renseignements","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T08:18:32Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T08:18:33Z","userUpdatedAt":"2022-06-04T08:18:32Z","customerWaitingSince":{"time":"2022-06-04T08:18:33Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910119695"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/477844062"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/477844062"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910119695/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910119695/1978739"}},"assignee":{}},{"id":1910118535,"number":1978738,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Demande de rendez-vous en vue du dépôt d''une demande de renouvellement de + la carte de séjour ou du visa long séjour valant titre de séjour","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T08:15:43Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T08:15:43Z","userUpdatedAt":"2022-06-04T08:15:43Z","customerWaitingSince":{"time":"2022-06-04T08:15:43Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910118535"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533468939"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533468939"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910118535/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910118535/1978738"}},"assignee":{}},{"id":1910073903,"number":1978735,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Renouvellement","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T06:45:33Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T06:45:33Z","userUpdatedAt":"2022-06-04T06:45:33Z","customerWaitingSince":{"time":"2022-06-04T06:45:33Z","friendly":"Jun + 4, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"},{"id":6885035,"color":"#A5B2BD","tag":"other"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910073903"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533460330"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533460330"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910073903/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910073903/1978735"}},"assignee":{}},{"id":1910073830,"number":1978734,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Renouvellement","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T06:45:25Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T06:45:25Z","userUpdatedAt":"2022-06-04T06:45:25Z","customerWaitingSince":{"time":"2022-06-04T06:45:25Z","friendly":"Jun + 4, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"},{"id":6885035,"color":"#A5B2BD","tag":"other"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910073830"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533460330"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533460330"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910073830/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910073830/1978734"}},"assignee":{}},{"id":1910049439,"number":1978733,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Renseignements","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T05:55:41Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T05:55:41Z","userUpdatedAt":"2022-06-04T05:55:41Z","customerWaitingSince":{"time":"2022-06-04T05:55:41Z","friendly":"Jun + 4, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"},{"id":6885035,"color":"#A5B2BD","tag":"other"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910049439"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533455039"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533455039"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910049439/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910049439/1978733"}},"assignee":{}},{"id":1909873707,"number":1978732,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Votre dossier nº 8851246 a été accepté (DEMANDE D''AUTORISATION D''INSTRUCTION + DANS LA FAMILLE 2022/2023)","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-04T00:33:59Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T00:33:59Z","userUpdatedAt":"2022-06-04T00:33:59Z","customerWaitingSince":{"time":"2022-06-04T00:33:59Z","friendly":"Jun + 4, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909873707"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533409205"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533409205"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909873707/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909873707/1978732"}},"assignee":{}},{"id":1909608573,"number":1978730,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Oui + c’est bon","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-03T19:34:20Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-03T19:34:21Z","userUpdatedAt":"2022-06-03T19:34:21Z","customerWaitingSince":{"time":"2022-06-03T19:34:21Z","friendly":"Jun + 3, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909608573"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/472328447"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/472328447"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909608573/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909608573/1978730"}},"assignee":{}},{"id":1909571857,"number":1978729,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Montant + du timbre","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-03T19:01:30Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-03T19:01:30Z","userUpdatedAt":"2022-06-03T19:01:30Z","customerWaitingSince":{"time":"2022-06-03T19:01:30Z","friendly":"Jun + 3, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"},{"id":6885035,"color":"#A5B2BD","tag":"other"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909571857"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533345249"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533345249"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909571857/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909571857/1978729"}},"assignee":{}},{"id":1909508850,"number":1978726,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"RE: + Un dossier en construction va bientôt être supprimé","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-03T18:07:27Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-03T18:07:27Z","userUpdatedAt":"2022-06-03T18:07:27Z","customerWaitingSince":{"time":"2022-06-03T18:07:27Z","friendly":"Jun + 3, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909508850"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/420667968"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/420667968"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909508850/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909508850/1978726"}},"assignee":{}},{"id":1909460281,"number":1978724,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-03T17:29:05Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-03T17:29:06Z","userUpdatedAt":"2022-06-03T17:29:05Z","customerWaitingSince":{"time":"2022-06-03T17:29:05Z","friendly":"Jun + 3, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909460281"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533255322"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533255322"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909460281/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909460281/1978724"}},"assignee":{}},{"id":1909359672,"number":1978719,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Prise + de rdv","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-03T16:02:00Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-03T16:02:00Z","userUpdatedAt":"2022-06-03T16:02:00Z","customerWaitingSince":{"time":"2022-06-03T16:02:00Z","friendly":"Jun + 3, ''22"},"source":{"type":"api","via":"customer"},"tags":[{"id":8922426,"color":"#A5B2BD","tag":"contact + form"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909359672"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/435717422"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/435717422"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909359672/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909359672/1978719"}},"assignee":{}},{"id":1909341225,"number":1978718,"threads":1,"type":"email","folderId":3195939,"status":"closed","state":"published","subject":"Re: + Préfecture de la Marne, renouvellement récépissé/APS","preview":"","mailboxId":193013,"createdBy":{},"createdAt":"2022-06-03T15:47:20Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-03T15:47:20Z","userUpdatedAt":"2022-06-03T15:47:20Z","customerWaitingSince":{"time":"2022-06-03T15:47:20Z","friendly":"Jun + 3, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1909341225"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/193013"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/505891768"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/505891768"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1909341225/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1909341225/1978718"}},"assignee":{}},{"id":1907817899,"number":1978559,"threads":4,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Re: + DUREE DE CONSERVATION DES DONNEES","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-02T14:02:18Z","closedBy":577293,"closedByUser":{},"closedAt":"2022-06-03T14:53:13Z","userUpdatedAt":"2022-06-03T14:54:29Z","customerWaitingSince":{"time":"2022-06-03T14:53:13Z","friendly":"Jun + 3, ''22"},"source":{"type":"email","via":"customer"},"tags":[{"id":9822999,"color":"#A5B2BD","tag":"conservation + données"},{"id":3754718,"color":"#A5B2BD","tag":"webinaire"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1907817899"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/190044272"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/190044272"},"closedBy":{"href":"https://api.helpscout.net/v2/users/577293"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1907817899/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1907817899/1978559"}},"assignee":{}},{"id":1904794963,"number":1978181,"threads":3,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Re: + Webinaire tour de France DS - Etape occitanie le 9 juin 2022","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-05-31T14:20:10Z","closedBy":577293,"closedByUser":{},"closedAt":"2022-06-03T14:53:34Z","userUpdatedAt":"2022-06-03T14:53:45Z","customerWaitingSince":{"time":"2022-06-03T14:53:34Z","friendly":"Jun + 3, ''22"},"source":{"type":"web","via":"user"},"tags":[{"id":3754718,"color":"#A5B2BD","tag":"webinaire"}],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1904794963"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/172457074"},"createdByUser":{"href":"https://api.helpscout.net/v2/users/412221"},"closedBy":{"href":"https://api.helpscout.net/v2/users/577293"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1904794963/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1904794963/1978181"}},"assignee":{}}]},"_links":{"next":{"href":"https://api.helpscout.net/v2/conversations?query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed\u0026page=2"},"self":{"href":"https://api.helpscout.net/v2/conversations?page=1\u0026query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed"},"first":{"href":"https://api.helpscout.net/v2/conversations?query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed\u0026page=1"},"last":{"href":"https://api.helpscout.net/v2/conversations?query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed\u0026page=75678"},"page":{"href":"https://api.helpscout.net/v2/conversations?page=1\u0026query=(%0A%20%20%20%20%20%20%20%20modifiedAt:%5B*%20TO%202022-06-05T00:00:00Z%5D%0A%20%20%20%20%20%20)\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed"}},"page":{"size":25,"totalElements":1891943,"totalPages":2,"number":1}}' + recorded_at: Wed, 05 Jun 2024 00:00:00 GMT + +- request: + method: get + uri: https://api.helpscout.net/v2/conversations?page=1&query=(%0A%20%20%20%20%20%20%20%20modifiedAt:%5B*%20TO%202022-06-05T00:00:00Z%5D%0A%20%20%20%20%20%20)&sortField=modifiedAt&sortOrder=desc&status=closed + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Authorization: + - Bearer redacted + Content-Type: + - application/json; charset=UTF-8 + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Date: + - Tue, 11 Jun 2024 14:13:28 GMT + Content-Type: + - application/hal+json + X-Ratelimit-Limit-Minute: + - '200' + X-Ratelimit-Remaining-Minute: + - '198' + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - '0' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - '0' + X-Frame-Options: + - DENY + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Location,Resource-Id + Correlation-Id: + - a9ca7664-2711-4c36-a092-73203365b474#13211836 + X-Kong-Upstream-Latency: + - '640' + X-Kong-Proxy-Latency: + - '3' + Via: + - kong/0.14.1 + body: + encoding: UTF-8 + string: + '{"_embedded":{"conversations":[{"id":1000000,"number":1978770,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Re: + Demande de création de compte","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T23:34:03Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T23:34:04Z","userUpdatedAt":"2022-06-04T23:34:04Z","customerWaitingSince":{"time":"2022-06-04T23:34:04Z","friendly":"Jun + 5, ''22"},"source":{"type":"email","via":"customer"},"tags":[],"cc":[],"bcc":[],"primaryCustomer":{},"customFields":[],"_embedded":{"threads":[]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations/1910642153"},"mailbox":{"href":"https://api.helpscout.net/v2/mailboxes/125926"},"primaryCustomer":{"href":"https://api.helpscout.net/v2/customers/533578452"},"createdByCustomer":{"href":"https://api.helpscout.net/v2/customers/533578452"},"closedBy":{"href":"https://api.helpscout.net/v2/users/1"},"threads":{"href":"https://api.helpscout.net/v2/conversations/1910642153/threads"},"web":{"href":"https://secure.helpscout.net/conversation/1910642153/1978770"}},"assignee":{}},{"id":1910621183,"number":1978769,"threads":2,"type":"email","folderId":1653804,"status":"closed","state":"published","subject":"Re: + Demande de création de compte","preview":"","mailboxId":125926,"createdBy":{},"createdAt":"2022-06-04T22:52:48Z","closedBy":1,"closedByUser":{},"closedAt":"2022-06-04T22:52:48Z","userUpdatedAt":"2022-06-04T22:52:48Z","customerWaitingSince":{"time":"2022-06-04T22:52:48Z","friendly":"Jun + 5,"}}]},"_links":{"self":{"href":"https://api.helpscout.net/v2/conversations?page=1\u0026query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed"},"first":{"href":"https://api.helpscout.net/v2/conversations?query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed\u0026page=1"},"last":{"href":"https://api.helpscout.net/v2/conversations?query=(\n modifiedAt:[* + TO 2022-06-05T00:00:00Z]\n )\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed\u0026page=1"},"page":{"href":"https://api.helpscout.net/v2/conversations?page=2\u0026query=(%0A%20%20%20%20%20%20%20%20modifiedAt:%5B*%20TO%202022-06-05T00:00:00Z%5D%0A%20%20%20%20%20%20)\u0026sortField=modifiedAt\u0026sortOrder=desc\u0026status=closed"}},"page":{"size":25,"totalElements":1,"totalPages":1,"number":1}}' + recorded_at: Wed, 05 Jun 2024 00:00:00 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/tasks/maintenance/helpscout_delete_old_conversations_task_spec.rb b/spec/tasks/maintenance/helpscout_delete_old_conversations_task_spec.rb new file mode 100644 index 000000000..494be20bf --- /dev/null +++ b/spec/tasks/maintenance/helpscout_delete_old_conversations_task_spec.rb @@ -0,0 +1,62 @@ +describe Maintenance::HelpscoutDeleteOldConversationsTask do + before do + mock_helpscout_secrets + travel_to DateTime.new(2024, 6, 5) + end + + subject do + described_class.new.tap { _1.status = "closed" } + end + + describe '#enumerator_builder' do + it "enumerates conversation ids" do + VCR.use_cassette("helpscout_list_old_conversations") do |c| + ids = subject.enumerator_builder(cursor: 0).to_a + # Warning: calling a enumerable method always reinvoke the enumerable ! + # So immediately convert in array and run expectations on it + + # anonymize when recorded cassettes + c.new_recorded_interactions.each do |interaction| + interaction.request.body = anonymize_request(interaction) + + body = anonymize_response(interaction) + interaction.response.body = body.to_json + end + + expect(ids.count).to eq(27) # 25 first page + 2 next page + expect(ids[0][0]).to eq(1910642153) + end + end + end + + def anonymize_response(interaction) + body = JSON.parse(interaction.response.body) + + Array(body.dig("_embedded", "conversations")).each do |conversation| + conversation["createdBy"] = {} + conversation["closedByUser"] = {} + conversation["primaryCustomer"] = {} + conversation["assignee"] = {} + conversation["preview"] = "" # this also removes binary string + conversation["cc"] = [] + end + + body["access_token"] = "redacted" if body.key?("access_token") + + body + end + + def anonymize_request(interaction) + body = interaction.request.body + + return body unless body.include?("client_secret") + + URI.decode_www_form(body).to_h.merge("client_id" => "1234", "client_secret" => "5678").to_query + end + + def mock_helpscout_secrets + Rails.application.secrets.helpscout[:mailbox_id] = '9999' + Rails.application.secrets.helpscout[:client_id] = '1234' + Rails.application.secrets.helpscout[:client_secret] = '5678' + end +end