|
34535
|
1296
|
6
|
2026-05-13T11:22:34.125245+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671354125_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.12849163,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2497872404984632158
|
-4275870702622275252
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34536
|
1295
|
4
|
2026-05-13T11:22:36.063252+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671356063_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181 SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181DEV (docker)₴82APP (-zshdocker_lamp_12026-05-13 11:21:24 Jiminny\Jobs\Crm\SyncHubspotObjectsdocker_1amp_1docker_1amp_12026-05-13 11:22:09 Running ['artisan'meeting-bot: schedule-bot]docker_lamp_11 '/usr/local/bin/php' 'artisan"meeting-bot:schedule-bot >*/proc/1/docker_1amp_12026-05-13 11:22:14 Running ['artisan' dialers:monitor-activities]docker_lamp_11 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/2026-05-13 11:22:17 Running ['artisan' jiminny:monitor-social-account• '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */docker_lamp_1proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:22:20 Running ['artisan' mailbox:skip-lists:refresh].docker_lamp_1 | l '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › '/proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:22:25 Running ['artisan'mailbox: batch:process --max-badocker_lamp_1*/proc/1/fd/1' 2>&11 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=2026-05-13 11:22:27 Running ['artisan'conference:monitor: count]docker_lamp_1• '/usr/local/bin/php' 'artisan' conference:monitor:count > */proc/1/docker_1amp_12026-05-13 11:22:29 Running ['artisan' mailbox:batch: create]docker_lamp_1t '/usr/local/bin/php' 'artisan' mailbox:batch:create › '/proc/1/fd/1docker_lamp_12026-05-13 11:22:31 Running ['artisan'activity:sync'ringcentral' 'avaya' 'telus' 'talkdesk' --from='2026-05-13 11:06:00'--to='2026-05-13 11:22:00']-05-13 11:22:31 Jiminny\Jobs\Mailbox\CreateBatchesdocker_lamp_12026-05-13 11:22:31 Jiminny\Jobs\Mailbox\CreateBatchesdocker_1amp_1docker_1amp_11 '/usr/local/bin/php' 'artisan' activity:sync 'ringcentral' 'avaya''telus' 'talkdesk' --from='2026-05-13 11:06:00' --to='2026-05-13 11:22:00' > */proc/1/fdHomeDMsActivityFilesLater..•MoreView in Docker Desktopo View Configla6lSupport Daily • in 38 m100% <28•Wed 13 May 14:22:35ED-→Describe what you are looking forJiminny ...ab External connections* Starred& jiminny-x-integrati...8platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general#jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...° Direct messagesNikolay Ivanovd. James Graham. Stoyan TanevP. Galya Dimitrova# platform-tickets8146 0• Messagest Add canvasO Filesmhe PrioritThursday, April 16th~+Tuesday, May 5th ~Automation for Jira APP2:12 PMSRD-6835 Salesforce app issues has been raisedwith Platform team and assigned to **. The Priorityis P2 MediumAutomation for Jira APP5:01 PMSRD-6815 [Playback] Ask Jiminny odd behaviourhas been raised with Platform team and assigned toSteliyan Georgiev. The Priority is P2 MediumMonday, May 11th ~Automation for Jira APP 4:38 PMSRD-6845 CRM filling is not being applied has beenraised with Platform team and assigned to **. ThePriority is **Today ~Automation for Jira APP10:42 AMSRD-6848 Sidekick SMS issue has been raised withPlatform team and assigned to **. The Priority is **NewAutomation for Jira APP 1:33 PMSRD-6849 Recorded call does not appear on thedashboard has been raised with Platform team andassigned to **. The Priority is **Message #platform-tickets...
|
NULL
|
8905851205965354130
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181 SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181DEV (docker)₴82APP (-zshdocker_lamp_12026-05-13 11:21:24 Jiminny\Jobs\Crm\SyncHubspotObjectsdocker_1amp_1docker_1amp_12026-05-13 11:22:09 Running ['artisan'meeting-bot: schedule-bot]docker_lamp_11 '/usr/local/bin/php' 'artisan"meeting-bot:schedule-bot >*/proc/1/docker_1amp_12026-05-13 11:22:14 Running ['artisan' dialers:monitor-activities]docker_lamp_11 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/2026-05-13 11:22:17 Running ['artisan' jiminny:monitor-social-account• '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */docker_lamp_1proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:22:20 Running ['artisan' mailbox:skip-lists:refresh].docker_lamp_1 | l '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › '/proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:22:25 Running ['artisan'mailbox: batch:process --max-badocker_lamp_1*/proc/1/fd/1' 2>&11 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=2026-05-13 11:22:27 Running ['artisan'conference:monitor: count]docker_lamp_1• '/usr/local/bin/php' 'artisan' conference:monitor:count > */proc/1/docker_1amp_12026-05-13 11:22:29 Running ['artisan' mailbox:batch: create]docker_lamp_1t '/usr/local/bin/php' 'artisan' mailbox:batch:create › '/proc/1/fd/1docker_lamp_12026-05-13 11:22:31 Running ['artisan'activity:sync'ringcentral' 'avaya' 'telus' 'talkdesk' --from='2026-05-13 11:06:00'--to='2026-05-13 11:22:00']-05-13 11:22:31 Jiminny\Jobs\Mailbox\CreateBatchesdocker_lamp_12026-05-13 11:22:31 Jiminny\Jobs\Mailbox\CreateBatchesdocker_1amp_1docker_1amp_11 '/usr/local/bin/php' 'artisan' activity:sync 'ringcentral' 'avaya''telus' 'talkdesk' --from='2026-05-13 11:06:00' --to='2026-05-13 11:22:00' > */proc/1/fdHomeDMsActivityFilesLater..•MoreView in Docker Desktopo View Configla6lSupport Daily • in 38 m100% <28•Wed 13 May 14:22:35ED-→Describe what you are looking forJiminny ...ab External connections* Starred& jiminny-x-integrati...8platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general#jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...° Direct messagesNikolay Ivanovd. James Graham. Stoyan TanevP. Galya Dimitrova# platform-tickets8146 0• Messagest Add canvasO Filesmhe PrioritThursday, April 16th~+Tuesday, May 5th ~Automation for Jira APP2:12 PMSRD-6835 Salesforce app issues has been raisedwith Platform team and assigned to **. The Priorityis P2 MediumAutomation for Jira APP5:01 PMSRD-6815 [Playback] Ask Jiminny odd behaviourhas been raised with Platform team and assigned toSteliyan Georgiev. The Priority is P2 MediumMonday, May 11th ~Automation for Jira APP 4:38 PMSRD-6845 CRM filling is not being applied has beenraised with Platform team and assigned to **. ThePriority is **Today ~Automation for Jira APP10:42 AMSRD-6848 Sidekick SMS issue has been raised withPlatform team and assigned to **. The Priority is **NewAutomation for Jira APP 1:33 PMSRD-6849 Recorded call does not appear on thedashboard has been raised with Platform team andassigned to **. The Priority is **Message #platform-tickets...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34537
|
1296
|
7
|
2026-05-13T11:22:36.063275+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671356063_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormINavigareCodeLaravelFV faVsco.js?9 master PhostormINavigareCodeLaravelFV faVsco.js?9 master kProiect© UpdateBotAvatar.ph|c) sso.phpCUodateleamPnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation2510 AjReports> @ Audio277v _ Automateakeporis278© RequestGenerateAskJin 279(C) kequestGeneratekeporl 280)© SendReportExpirinaSoo|281c) senckepor.ob.ono© SendReportMailJob.php 283(C) SendRevortNotGeneratt 2840 Calendar285v D crmM Delete286287→ Huosoot288• M Salesforce289© AutologDelayedToCrm.f 290© CheckAndRetryRemotel 291© CreateFollowupActivity. 292C) CreateNotes.oho293© MatchActivitiesToNewC 294© MatchActivityCrmData.f 295(6 Note@hiect nhn© SaveActivity.php1297© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php 301© SyncHubspotObjects.pr 302© SyncLeads.php© SyncObiects.php304© SyncOpportunitiesJob.p zas© SyncOpportunity.php© SyncProfileMetadata.ph 3o7© SyncTeamFields.Job.phr zogc) suncireamMetadata.onr zad© Undate@pportunitvSpec 210l(C) UodateStade oho> MDealRisks312v 7 MailboxC) CreateBatches.ohoC) Createlnbox.oho315g) DeleteEmailMessagesJc 316(c) SmailTeytRelav nho@ ProcescEmailsOneDasc |210)(C) Suneinhoy nhn→ MMestinaRo!© MailboxController.php© TextRelayService.php© EmailTextRelay.php XExterallaUniqueTorostvalldatonkule.org© SmsLength.phg© TextRelay.phpTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmail \MessagePart $payload)Ssender = Sthis->oarseSender(sheaders"From'D:// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'J)):// Check this message is intended for us.if (Srecipient[1] |== config( key: 'jiminny.google_text_host')) {throw new TextRelayException(message: 'Destination Mailbox does not match.',code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom, Sto, SactivityIdl = $this->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => Sfrom]. ['data' => 'phone:INTERNATIONAL']):if (Svalidator->failso) {throw new TextRelayException('Recipient origin number is not valid.'.code: self::REASON CODE RECIPTENT ORIGIN INVALIdSvalidator = Validator: :makel'data' => Stolr "data' => "phone: INTERNATIONAL'D5if Svalidator->failson *throw new TextRelavException('Recipient destination number is not valid.',code: self.•REASON CODE RECIPTENT DESTINATION INVALTOSuser = SuserRepository->findByEmail($sender);"$Cucon === null)throw new TextRelayException(message: 'Sender does not exist.'code: self::REASON_CODE SENDER_UNKNOWNif (Suser->softphone number === null || ! Suser->hasPermission(PermissionEnum::SMS)) {throw new TextRelayException(message: 'Messaging is not enabled for this account.'.anda. colf.. ocAcoM conc ceanco cOpptOnca01 A31 X1Ahel• suppont Dally • In 30 m100% L2• Wed 13 May 14:22:35U AskJiminnyReportActivityServiceTest v= custom.log627v 629630-632631642640_651—652— 6536.5%-650E658-659-661— 662=laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]& console [PROl&# console lcu)« console [STAGING]Tx: Auto vAND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar_domainORDER BY t.name, calendar domain:select * trom users u 1oin calendars c 1<->I.n. on c.user 10 = U.10where u,team id = 882select * from activities where 1d = 14049485: # team 563 crm 537.select * from activities where id = 73272382; # team 563 crm 537select * from activities where 1d = 64400389: # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc;select * from contacts where crm confiquration id = 537 and id = 35057750.select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidlor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN 24623.29443.2961399So jiminny040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;TAAA Nselect * from text_relays where created_at > '2026-05-01# and id IN (32415, 32416);and id = 32412:— 670select * from users where team id = 2 and email like '%scott%' and id = 29510& Shortcuts conflictsClone Carer Below and i more shon cur contliciwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show AdainWN Windsurf TeamoUTE.Rio 4 spaces...
|
NULL
|
1269704042633657493
|
NULL
|
click
|
ocr
|
NULL
|
PhostormINavigareCodeLaravelFV faVsco.js?9 master PhostormINavigareCodeLaravelFV faVsco.js?9 master kProiect© UpdateBotAvatar.ph|c) sso.phpCUodateleamPnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation2510 AjReports> @ Audio277v _ Automateakeporis278© RequestGenerateAskJin 279(C) kequestGeneratekeporl 280)© SendReportExpirinaSoo|281c) senckepor.ob.ono© SendReportMailJob.php 283(C) SendRevortNotGeneratt 2840 Calendar285v D crmM Delete286287→ Huosoot288• M Salesforce289© AutologDelayedToCrm.f 290© CheckAndRetryRemotel 291© CreateFollowupActivity. 292C) CreateNotes.oho293© MatchActivitiesToNewC 294© MatchActivityCrmData.f 295(6 Note@hiect nhn© SaveActivity.php1297© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php 301© SyncHubspotObjects.pr 302© SyncLeads.php© SyncObiects.php304© SyncOpportunitiesJob.p zas© SyncOpportunity.php© SyncProfileMetadata.ph 3o7© SyncTeamFields.Job.phr zogc) suncireamMetadata.onr zad© Undate@pportunitvSpec 210l(C) UodateStade oho> MDealRisks312v 7 MailboxC) CreateBatches.ohoC) Createlnbox.oho315g) DeleteEmailMessagesJc 316(c) SmailTeytRelav nho@ ProcescEmailsOneDasc |210)(C) Suneinhoy nhn→ MMestinaRo!© MailboxController.php© TextRelayService.php© EmailTextRelay.php XExterallaUniqueTorostvalldatonkule.org© SmsLength.phg© TextRelay.phpTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmail \MessagePart $payload)Ssender = Sthis->oarseSender(sheaders"From'D:// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'J)):// Check this message is intended for us.if (Srecipient[1] |== config( key: 'jiminny.google_text_host')) {throw new TextRelayException(message: 'Destination Mailbox does not match.',code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom, Sto, SactivityIdl = $this->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => Sfrom]. ['data' => 'phone:INTERNATIONAL']):if (Svalidator->failso) {throw new TextRelayException('Recipient origin number is not valid.'.code: self::REASON CODE RECIPTENT ORIGIN INVALIdSvalidator = Validator: :makel'data' => Stolr "data' => "phone: INTERNATIONAL'D5if Svalidator->failson *throw new TextRelavException('Recipient destination number is not valid.',code: self.•REASON CODE RECIPTENT DESTINATION INVALTOSuser = SuserRepository->findByEmail($sender);"$Cucon === null)throw new TextRelayException(message: 'Sender does not exist.'code: self::REASON_CODE SENDER_UNKNOWNif (Suser->softphone number === null || ! Suser->hasPermission(PermissionEnum::SMS)) {throw new TextRelayException(message: 'Messaging is not enabled for this account.'.anda. colf.. ocAcoM conc ceanco cOpptOnca01 A31 X1Ahel• suppont Dally • In 30 m100% L2• Wed 13 May 14:22:35U AskJiminnyReportActivityServiceTest v= custom.log627v 629630-632631642640_651—652— 6536.5%-650E658-659-661— 662=laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]& console [PROl&# console lcu)« console [STAGING]Tx: Auto vAND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar_domainORDER BY t.name, calendar domain:select * trom users u 1oin calendars c 1<->I.n. on c.user 10 = U.10where u,team id = 882select * from activities where 1d = 14049485: # team 563 crm 537.select * from activities where id = 73272382; # team 563 crm 537select * from activities where 1d = 64400389: # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc;select * from contacts where crm confiquration id = 537 and id = 35057750.select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidlor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN 24623.29443.2961399So jiminny040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;TAAA Nselect * from text_relays where created_at > '2026-05-01# and id IN (32415, 32416);and id = 32412:— 670select * from users where team id = 2 and email like '%scott%' and id = 29510& Shortcuts conflictsClone Carer Below and i more shon cur contliciwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show AdainWN Windsurf TeamoUTE.Rio 4 spaces...
|
34535
|
NULL
|
NULL
|
NULL
|
|
34538
|
1295
|
5
|
2026-05-13T11:22:40.965516+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671360965_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Create parameter
Create parameter
Initialize with Create parameter
Create parameter
Initialize with a value
Windsurf: Explain & Fix
Add PHPDoc comment
Surround with 'if(isset($userRepository)){...}'
Press to toggle preview...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Create parameter","depth":5,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Create parameter","depth":5,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Initialize with a value","depth":5,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Windsurf: Explain & Fix","depth":5,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Add PHPDoc comment","depth":5,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Surround with 'if(isset($userRepository)){...}'","depth":5,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Press to toggle preview","depth":1,"bounds":{"left":0.0,"top":0.0,"width":0.25694445,"height":0.026666667},"on_screen":false,"role_description":"text"}]...
|
-3759788433234155856
|
2972536568857908512
|
click
|
accessibility
|
NULL
|
Create parameter
Create parameter
Initialize with Create parameter
Create parameter
Initialize with a value
Windsurf: Explain & Fix
Add PHPDoc comment
Surround with 'if(isset($userRepository)){...}'
Press to toggle preview...
|
34536
|
NULL
|
NULL
|
NULL
|
|
34539
|
1296
|
8
|
2026-05-13T11:22:40.968847+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671360968_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Create parameter
Initialize with a value
Windsurf: Create parameter
Initialize with a value
Windsurf: Explain & Fix
Add PHPDoc comment...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Create parameter","depth":5,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Initialize with a value","depth":5,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Windsurf: Explain & Fix","depth":5,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Add PHPDoc comment","depth":5,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"text"}]...
|
-6319487640521191204
|
4129968819919068642
|
click
|
hybrid
|
NULL
|
Create parameter
Initialize with a value
Windsurf: Create parameter
Initialize with a value
Windsurf: Explain & Fix
Add PHPDoc comment
PhostormINavicareCodeLaravelKeractorFV faVsco.js?9 master kProiect v© UpdateBotAvatar.ph|CUodateleamPnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports> @ Audioc) sso.php251277v _ Automateakeporis278© RequestGenerateAskJin 279C) kequestGeneratekeporl 280)© SendReportExpiringSool 281c) senckepor.ob.ono© SendReportMailJob.php 283C) SendRevortNotGeneratt 2840 Calendar285v D crmM Delete286287→ Huosoot288M Salesforce289© AutologDelayedToCrm.f 290© CheckAndRetryRemotel 291© CreateFollowupActivity. 292C) CreateNotes.oho293© MatchActivitiesToNewC 294© MatchActivityCrmData.f 295(6 Note@hiect nhn© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php 301© SyncHubspotObjects.pr 302© SyncLeads.php13031© SyncObiects.php304© SyncOpportunitiesJob.p zos© SyncOpportunity.php© SyncProfileMetadata.ph 3o7© SyncTeamFields.Job.phr zogc) suncireamMetadata.onr zad@ Undate@pportunitvSpec z10l(C) UodateStade oho> MDealRisks312v 7 MailboxC) CreateBatches.oho314C) Createlnbox.ohog DeleteFmailMeccaaes.Ie 21/(c) SmailTeytRelav nho@ ProcescEmailsOneDasc |210)(C) Suneinhoy nhn→ MMeetinaRo!© MailboxController.php© TextRelayService.php© EmailTextRelay.php XexterallaUniqueTorostvalldatonkule.org© SmsLength.phpC) TextRelay.phpTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmail \MessagePart $payload)Ssender = Sthis->oarseSendersheaders"From'D:// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'J)):// Check this message is intended for us.if Srecinient(1l l== confiadkev. tjiminnv.aoogle teyt hostr)) &throw new TextRelayException(message: 'Destination Mailbox does not match.',code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom, Sto, SactivityIdl = $this->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => Sfrom]. ['data' => 'phone:INTERNATIONAL']):if (Svalidator->failso) {throw new TextRelayException('Reciplent oriqln number 1s not val1d.',code: self::REASON CODE RECIPTENT ORIGIN INVALId01 A31 X1ASvalidator = Validator: :makel'data' => Stolr "data' => "phone: INTERNATIONAL'D5if Svalidator->failson *throw new TextRelavException('Recipient destination number is not valid.',code: self.•REASON CODE RECIPTENT DESTINATION INVALTOSuser = SuserRepository->findByEmail($sender);@ Create parameternitalize with a valveWindsurf: Eyplain & FjyAdd PHPDoc commentSurround with 'if(lemptv(SuserRepositorv)XSurround with 'flisset(SuserRenositorv)K..?! Suser->hasPermission(PermissionEnum::SMS)) 4message: 'Messaging is not enabled for this account.'.code: self::REASON CODE SENDER FORBIDDENhel• suppont Dally • In 30 m100% S2• Wed 13 May 14:22:40U AskJiminnyReportActivityServiceTest v= custom.log627630- 632631642640650_651— 6536.5%655-650E658_65°661— 661— 662=laravel.log« SF [jiminny@localhost]A HS_local [jiminny@localhost]& console [PROl&# console lcu)« console [STAGING]Tx: Auto vAND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar_domainORDER BY t.name, calendar domaln:select * trom users u 1oin calendars c 1<->I.n. on c.user 10 = U.10where u,team id = 882select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircall'and account_id = 19003658 order by updated_at desc;select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN 24623.29443.2961399So jiminny040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;666 Vselect * from text_relays where created_at › '2026-05-01'# and id IN (32415, 32416);and id = 32412:— 670select * from users where team id = 2 and email like '%scott%' and id = 29510& Shortcuts conflictsClone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show AdainWN Windsurf TeamoUTE.Rio 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34540
|
1295
|
6
|
2026-05-13T11:22:45.314177+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671365314_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2497872404984632158
|
-4275870702622275252
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34541
|
1296
|
9
|
2026-05-13T11:22:45.295017+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671365295_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2888649345046477086
|
-4275874937736844852
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History...
|
34539
|
NULL
|
NULL
|
NULL
|
|
34542
|
1295
|
7
|
2026-05-13T11:22:48.752121+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671368752_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"31","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1542959194699279863
|
-2909036375338952603
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
34540
|
NULL
|
NULL
|
NULL
|
|
34543
|
1296
|
10
|
2026-05-13T11:22:48.752198+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671368752_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.12849163,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3784117113566394635
|
-3566553623605213756
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34544
|
1295
|
8
|
2026-05-13T11:23:00.422336+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671380422_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"31","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8275813924030287906
|
-2909036375338952603
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34545
|
1296
|
11
|
2026-05-13T11:23:00.405981+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671380405_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-237402440841603673
|
-4278122356683896372
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line...
|
34543
|
NULL
|
NULL
|
NULL
|
|
34546
|
1295
|
9
|
2026-05-13T11:23:13.821724+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671393821_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181 SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181DEV (docker)₴82APP (-zshDOCKER (docker-compose)docker_lamp_12026-05-13 11:22:34 Running ['artisan'twilio:recover-tracks]2sDONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' twilio:recover-tracks > '/proc/1/fd/2>&1docker_lamp_12026-05-13 11:22:37 Running ['artisan'dialers: sync-users]2S DONEdocker_lamp_1t '/usr/local/bin/php' 'artisan'dialers:sync-users › '/proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:22:40 Running ['artisan'datadog: report:failed-processing-states]4S DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' datadog:report:failed-processing-states >'/proc/1/fd/1'2>&1docker_1amp_1docker_1amp_1run_artisan_schedule: Done waiting for schedule:rundocker_lamp_1docker_1amp_12026-05-13 11:23:02 Running ['artisan' meeting-bot: schedule-bot] ...2S DONEdocker_lamp_1 |t '/usr/local/bin/php' 'artisan' meeting-bot:schedule-bot › */proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:23:05 Running ['artisan' dialers:monitor-activities] .1sDONEdocker_lamp_11/fd/1'1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/2>81docker_1amp_12026-05-13 11:23:07 Running ['artisan' jiminny:monitor-social-accountSJ1S DONEdocker_lamp_111 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */proc/1/fd/1'2>&1docker_1amp_12026-05-13 11:23:08 Running ['artisan' mailbox:skip-lists:refresh] .2S DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:23:10 Running ['artisan' mailbox:batch:process --max-batches=15]1S DONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' mailbox:batch:process --max-batches=15 >'/proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:23:12 Running ['artisan'mailbox:batch:retry-failed --max-batches=15] in background1.32ms DONEdocker_lamp_11 • ('/usr/local/bin/php' 'artisan' mailbox:batch:retry-failed--max-batches=15 >'/proc/1/fd/1' 2>&1 ; '/usr/local/bin/php' 'artisan'schedule: finish"framework/schedule-390defd641effba0f73a895e426ded4cf2ba7f11" "$?") › '/dev/null' 2>&1 &View in Docker Desktopo View ConfigEnable WatchHomeDMsActivityFilesLater...More> 0(allEDJiminny ...ab External connections* Starred& jiminny-x-integrati...8platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general#jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...° Direct messagesNikolay Ivanovd. James Graham. Stoyan TanevP. Galya DimitrovaSupport Daily - in 37 m100% <28•Wed 13 May 14:23:13QDescribe what you are looking for# platform-tickets8146 0• Messagest Add canvasO Filesmhe PrioritThursday, April 16th~+Tuesday, May 5th ~Automation for Jira APP2:12 PMSRD-6835 Salesforce app issues has been raisedwith Platform team and assigned to **. The Priorityis P2 MediumAutomation for Jira APP5:01 PMSRD-6815 [Playback] Ask Jiminny odd behaviourhas been raised with Platform team and assigned toSteliyan Georgiev. The Priority is P2 MediumMonday, May 11th ~Automation for Jira APP 4:38 PMSRD-6845 CRM filling is not being applied has beenraised with Platform team and assigned to **. ThePriority is **Today ~Automation for Jira APP10:42 AMSRD-6848 Sidekick SMS issue has been raised withPlatform team and assigned to **. The Priority is **NewAutomation for Jira APP 1:33 PMSRD-6849 Recorded call does not appear on thedashboard has been raised with Platform team andassigned to **. The Priority is **Message #platform-tickets...
|
NULL
|
-3558912599359245977
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181 SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181DEV (docker)₴82APP (-zshDOCKER (docker-compose)docker_lamp_12026-05-13 11:22:34 Running ['artisan'twilio:recover-tracks]2sDONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' twilio:recover-tracks > '/proc/1/fd/2>&1docker_lamp_12026-05-13 11:22:37 Running ['artisan'dialers: sync-users]2S DONEdocker_lamp_1t '/usr/local/bin/php' 'artisan'dialers:sync-users › '/proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:22:40 Running ['artisan'datadog: report:failed-processing-states]4S DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' datadog:report:failed-processing-states >'/proc/1/fd/1'2>&1docker_1amp_1docker_1amp_1run_artisan_schedule: Done waiting for schedule:rundocker_lamp_1docker_1amp_12026-05-13 11:23:02 Running ['artisan' meeting-bot: schedule-bot] ...2S DONEdocker_lamp_1 |t '/usr/local/bin/php' 'artisan' meeting-bot:schedule-bot › */proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:23:05 Running ['artisan' dialers:monitor-activities] .1sDONEdocker_lamp_11/fd/1'1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/2>81docker_1amp_12026-05-13 11:23:07 Running ['artisan' jiminny:monitor-social-accountSJ1S DONEdocker_lamp_111 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */proc/1/fd/1'2>&1docker_1amp_12026-05-13 11:23:08 Running ['artisan' mailbox:skip-lists:refresh] .2S DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:23:10 Running ['artisan' mailbox:batch:process --max-batches=15]1S DONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' mailbox:batch:process --max-batches=15 >'/proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:23:12 Running ['artisan'mailbox:batch:retry-failed --max-batches=15] in background1.32ms DONEdocker_lamp_11 • ('/usr/local/bin/php' 'artisan' mailbox:batch:retry-failed--max-batches=15 >'/proc/1/fd/1' 2>&1 ; '/usr/local/bin/php' 'artisan'schedule: finish"framework/schedule-390defd641effba0f73a895e426ded4cf2ba7f11" "$?") › '/dev/null' 2>&1 &View in Docker Desktopo View ConfigEnable WatchHomeDMsActivityFilesLater...More> 0(allEDJiminny ...ab External connections* Starred& jiminny-x-integrati...8platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general#jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...° Direct messagesNikolay Ivanovd. James Graham. Stoyan TanevP. Galya DimitrovaSupport Daily - in 37 m100% <28•Wed 13 May 14:23:13QDescribe what you are looking for# platform-tickets8146 0• Messagest Add canvasO Filesmhe PrioritThursday, April 16th~+Tuesday, May 5th ~Automation for Jira APP2:12 PMSRD-6835 Salesforce app issues has been raisedwith Platform team and assigned to **. The Priorityis P2 MediumAutomation for Jira APP5:01 PMSRD-6815 [Playback] Ask Jiminny odd behaviourhas been raised with Platform team and assigned toSteliyan Georgiev. The Priority is P2 MediumMonday, May 11th ~Automation for Jira APP 4:38 PMSRD-6845 CRM filling is not being applied has beenraised with Platform team and assigned to **. ThePriority is **Today ~Automation for Jira APP10:42 AMSRD-6848 Sidekick SMS issue has been raised withPlatform team and assigned to **. The Priority is **NewAutomation for Jira APP 1:33 PMSRD-6849 Recorded call does not appear on thedashboard has been raised with Platform team andassigned to **. The Priority is **Message #platform-tickets...
|
34544
|
NULL
|
NULL
|
NULL
|
|
34547
|
1296
|
12
|
2026-05-13T11:23:13.851158+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671393851_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormINavigarecodeFV faVsco.jsProledey© UpdateB PhostormINavigarecodeFV faVsco.jsProledey© UpdateBotAvatar.ph|CUodateleamPnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports> @ Audio|c) sso.php251277v _ Automateakeporis© RequestGenerateAskJin 250© RequestGenerateReport 283© SendReportExpiringSooc) senckepor.ob.onoC) SendReportMailJob.ohp© SendReportNotGenerat‹ 285Calendarv D crmDelete→ HuosootM Salesforce© AutoloaDelavedToCrm.r 291€ CheckAndRetrvRemotel 292© CreateFollowupActivity.C) CreateNotes.oho@ MatchActivitiesToNewd 295@ MatchActivitvCrmData r 296© NoteObject.php© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.pt 303© SyncLeads.php© SyncObjects.php© SyncOpportunitiesJob.p 306© SyncOpportunity.php© SyncProfileMetadata.ph 508© SyncTeamFields.Job.phr 509@ SvncTeamMetadata.ohr 310© UndateOpportunitvSpec 311(C) UodateStade oho> MDealRisksv 7 MailboxC) CreateBatches.ohoC) Createlnbox.oho9 DeleteFmailMeccaaes Ie 317c) SmailTeytRelav nhn@ ProcescEmailsOnePass(C) Suneinhoy nhn> M MoptinaRot© MailboxController.php© TextRelayService.php© EmailTextRelay.php XExterallaUniqueTorostvalldatonkule.org© SmsLength.phgTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmail \MessagePart $payload)Ssender = $this->parseSender($headers['From']):// Extract the Jiminny recipientSrecipient = explode( separator: '@', Sthis->parseRecipient($headers['To'])):// Check this message is intended for us.if (Srecipient(1] !== config( key: 'jiminny.google text host')) {chrow new lexckelayexcepc1onlmessage: 'Destination Mailbox does not match.',code: selt::KEASUN CUUE MALLOUXNISNAICH[Sfrom. Sto. Sactivitvidl = Sthis->parseRecipientIntoEntities(Srecipient[el)SvaLidaton = VaLidator::make(['data' => $froml. ['data' => 'phone:INTERNATTONAL• 1) •if (SvaLidator->fails@) $throw new TextRelavExcention('Recipient origin number is not valid.',code: self::REASON CODE RECTPTENT ORIGIN INVALTDCvallidaton = Validaton• •makodridatal => Stoll Tidatal => Inhone• TNTERNATTONAL 11D•if (Svalidaton-sfaile0)$throw new TextRelayException(message: 'Recipient destination number is not valid.'.code: self::REASON_CODE_RECIPIENT_DESTINATION_INVALIDSuser = SuserRepository->findByEmail(Ssender) :if (Suser ===nULL) -throw new TextRelayExceptiondmessage: "Sender does not exist.'code: self::REASON_CODE SENDER_UNKNOWNif (Suser->softphone number === null ll ! Suser->hasPermission(PermissionEnum:•SMS)) ≤throw new TextRelavExcentionmessage: 'Messaging is not enabled for this account.',code: self::REASON CODE SENDER FORBIDDEMM01A3121.hhl" suppont Dally • In 3/m100% S2• Wed 13 May 14:23:13AskJiminnyReportActivityServiceTest v= custom.log=laravel.log« SF [jiminny@localhost]A HS_local [jiminny@localhost]DA00@AND td.deleted_at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar_domainORDER BY t.name, calendar domain:& console [PROl&# console lcu)« console [STAGING]So jiminny630- 632631642-651—652— 6536.5%655650E658-[PHONE]63select * from users u join calendars c ->l.n: on c.user_1d = u.1dwhere u.team_id = 882;select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc;select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uvid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN 24623.29443.2961399040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;666 Vselect * from text_relays where created_at > '2026-05-01# and id IN (32415, 32416);and id = 32412:+ 66%— 470select * from users where team id = 2 and email like '%scott%' and id = 29510& Shortcuts conflictsClone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show Adain251-27io 4 spaces...
|
NULL
|
-2887476019246161338
|
NULL
|
click
|
ocr
|
NULL
|
PhostormINavigarecodeFV faVsco.jsProledey© UpdateB PhostormINavigarecodeFV faVsco.jsProledey© UpdateBotAvatar.ph|CUodateleamPnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports> @ Audio|c) sso.php251277v _ Automateakeporis© RequestGenerateAskJin 250© RequestGenerateReport 283© SendReportExpiringSooc) senckepor.ob.onoC) SendReportMailJob.ohp© SendReportNotGenerat‹ 285Calendarv D crmDelete→ HuosootM Salesforce© AutoloaDelavedToCrm.r 291€ CheckAndRetrvRemotel 292© CreateFollowupActivity.C) CreateNotes.oho@ MatchActivitiesToNewd 295@ MatchActivitvCrmData r 296© NoteObject.php© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.pt 303© SyncLeads.php© SyncObjects.php© SyncOpportunitiesJob.p 306© SyncOpportunity.php© SyncProfileMetadata.ph 508© SyncTeamFields.Job.phr 509@ SvncTeamMetadata.ohr 310© UndateOpportunitvSpec 311(C) UodateStade oho> MDealRisksv 7 MailboxC) CreateBatches.ohoC) Createlnbox.oho9 DeleteFmailMeccaaes Ie 317c) SmailTeytRelav nhn@ ProcescEmailsOnePass(C) Suneinhoy nhn> M MoptinaRot© MailboxController.php© TextRelayService.php© EmailTextRelay.php XExterallaUniqueTorostvalldatonkule.org© SmsLength.phgTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmail \MessagePart $payload)Ssender = $this->parseSender($headers['From']):// Extract the Jiminny recipientSrecipient = explode( separator: '@', Sthis->parseRecipient($headers['To'])):// Check this message is intended for us.if (Srecipient(1] !== config( key: 'jiminny.google text host')) {chrow new lexckelayexcepc1onlmessage: 'Destination Mailbox does not match.',code: selt::KEASUN CUUE MALLOUXNISNAICH[Sfrom. Sto. Sactivitvidl = Sthis->parseRecipientIntoEntities(Srecipient[el)SvaLidaton = VaLidator::make(['data' => $froml. ['data' => 'phone:INTERNATTONAL• 1) •if (SvaLidator->fails@) $throw new TextRelavExcention('Recipient origin number is not valid.',code: self::REASON CODE RECTPTENT ORIGIN INVALTDCvallidaton = Validaton• •makodridatal => Stoll Tidatal => Inhone• TNTERNATTONAL 11D•if (Svalidaton-sfaile0)$throw new TextRelayException(message: 'Recipient destination number is not valid.'.code: self::REASON_CODE_RECIPIENT_DESTINATION_INVALIDSuser = SuserRepository->findByEmail(Ssender) :if (Suser ===nULL) -throw new TextRelayExceptiondmessage: "Sender does not exist.'code: self::REASON_CODE SENDER_UNKNOWNif (Suser->softphone number === null ll ! Suser->hasPermission(PermissionEnum:•SMS)) ≤throw new TextRelavExcentionmessage: 'Messaging is not enabled for this account.',code: self::REASON CODE SENDER FORBIDDEMM01A3121.hhl" suppont Dally • In 3/m100% S2• Wed 13 May 14:23:13AskJiminnyReportActivityServiceTest v= custom.log=laravel.log« SF [jiminny@localhost]A HS_local [jiminny@localhost]DA00@AND td.deleted_at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar_domainORDER BY t.name, calendar domain:& console [PROl&# console lcu)« console [STAGING]So jiminny630- 632631642-651—652— 6536.5%655650E658-[PHONE]63select * from users u join calendars c ->l.n: on c.user_1d = u.1dwhere u.team_id = 882;select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc;select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uvid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN 24623.29443.2961399040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;666 Vselect * from text_relays where created_at > '2026-05-01# and id IN (32415, 32416);and id = 32412:+ 66%— 470select * from users where team id = 2 and email like '%scott%' and id = 29510& Shortcuts conflictsClone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show Adain251-27io 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34548
|
1295
|
10
|
2026-05-13T11:23:20.952295+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671400952_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"31","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1324193351794283232
|
-2909036375341049755
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34549
|
1296
|
13
|
2026-05-13T11:23:20.958432+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671400958_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.12849163,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.5152925,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7428175871130574480
|
-4287138360613206580
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close...
|
34547
|
NULL
|
NULL
|
NULL
|
|
34550
|
1295
|
11
|
2026-05-13T11:23:27.166472+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671407166_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4752793375569107729
|
-4564105331001062964
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere...
|
34548
|
NULL
|
NULL
|
NULL
|
|
34551
|
1296
|
14
|
2026-05-13T11:23:27.131305+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671407131_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormINavigarecodeFV faVsco.jsProiect(C) Mailbo PhostormINavigarecodeFV faVsco.jsProiect(C) MailboxController.ohr© TextRelayService.php© EmailTextRelay.php X© UpdateBotAvatar.ph|CUodateleamrnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports> @ Audioc) sso.php© ExternalldUniqueToHostValidationRule.php© SmsLength.phgTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueuepublic function handle(v _ Automateakeporis© RequestGenerateAskJinC) KequestGeneratekepon© SendReportExpirinaSooc) senckepor.ob.ong© SendReportMailJob.phpC) SendReport NotGenerat0 Calendarv D crmDelete→ HuosootM SalesforceC) AutoloaDelavedToCrm.r(C) CheckAndRetrvRemote!C) CreateNotes.oho© MatchActivities ToNewO 105© MatchActivityCrmData.f 106(6 Note@hiect nhn107© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.ph© SyncLeads.php© SyncObiects.php© SyncOpportunitiesJob.p© SyncOpportunity.php© SyncProfileMetadata.ph© SyncTeamFieldsJob.phf 11gc) SuncireamMetadata.onr@ Undate@pportunitvSped(C) UodateStade oho> MDealRisks121122v 7 MailboxC) CreateBatches.ohoC) Createlnbox.ohog DeleteFmailMeccanes.ld(c) SmailTeytRelav nho@ ProceccEmailsOneDass127(C) Suneinhoy nhn> M MoptinaRotSmailService = $relayService->getService(config( key: 'jiminny google_text_user'));try 1// Retrieve the message from the email server.Smessage = $this->getMessage($mailService, Sthis->messageId):Snavload = Smessade->ae+Pavloado•Sheaders = $this->getHeaders(Spayload->getHeadersO);Sdate = Carbon::createFromFormat( format: Carbon::RFC2822, Sheaders[ 'Date']):Sthis->textRelay->update([emall sent at = saate'sender' => Str::Zimit(Sheaders['From']Imic 191,"reciplent = Str::Lim1tSheaders"10'limic 171)D):Sthis->checkIntegritv(Spavload):Suser = sthis->activitvorigin->[URL_WITH_CREDENTIALS] HS_local [(jiminny@localhost]& console [PRolx# console lcu)« console [STAGING]AND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar domainORDER BY t.name, calendar domain:select * trom users u 1oin calendars c 1<->I.n. on c.user 10 = U.10where u,team id = 882select * from activities where 1d = 14049485: # team 563 crm 537.select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc;select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uvid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872)select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN (24623.29443.2961399So jiminny040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;666 vselect * from text_relays where created_at › '2026-05-01'# and id IN (32415, 32416);and id = 32412:'— 668-669- 070select * from users where team id = 2 and email like '%scott%' and id = 29510-& Shortcuts conflictsClone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show AdainUTE.Rio 4 spaces...
|
NULL
|
836457029012138385
|
NULL
|
click
|
ocr
|
NULL
|
PhostormINavigarecodeFV faVsco.jsProiect(C) Mailbo PhostormINavigarecodeFV faVsco.jsProiect(C) MailboxController.ohr© TextRelayService.php© EmailTextRelay.php X© UpdateBotAvatar.ph|CUodateleamrnoto.oSupport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports> @ Audioc) sso.php© ExternalldUniqueToHostValidationRule.php© SmsLength.phgTextRelayExceptionclass EmailTextRelay extends Job implements ShouldQueuepublic function handle(v _ Automateakeporis© RequestGenerateAskJinC) KequestGeneratekepon© SendReportExpirinaSooc) senckepor.ob.ong© SendReportMailJob.phpC) SendReport NotGenerat0 Calendarv D crmDelete→ HuosootM SalesforceC) AutoloaDelavedToCrm.r(C) CheckAndRetrvRemote!C) CreateNotes.oho© MatchActivities ToNewO 105© MatchActivityCrmData.f 106(6 Note@hiect nhn107© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.ph© SyncLeads.php© SyncObiects.php© SyncOpportunitiesJob.p© SyncOpportunity.php© SyncProfileMetadata.ph© SyncTeamFieldsJob.phf 11gc) SuncireamMetadata.onr@ Undate@pportunitvSped(C) UodateStade oho> MDealRisks121122v 7 MailboxC) CreateBatches.ohoC) Createlnbox.ohog DeleteFmailMeccanes.ld(c) SmailTeytRelav nho@ ProceccEmailsOneDass127(C) Suneinhoy nhn> M MoptinaRotSmailService = $relayService->getService(config( key: 'jiminny google_text_user'));try 1// Retrieve the message from the email server.Smessage = $this->getMessage($mailService, Sthis->messageId):Snavload = Smessade->ae+Pavloado•Sheaders = $this->getHeaders(Spayload->getHeadersO);Sdate = Carbon::createFromFormat( format: Carbon::RFC2822, Sheaders[ 'Date']):Sthis->textRelay->update([emall sent at = saate'sender' => Str::Zimit(Sheaders['From']Imic 191,"reciplent = Str::Lim1tSheaders"10'limic 171)D):Sthis->checkIntegritv(Spavload):Suser = sthis->activitvorigin->[URL_WITH_CREDENTIALS] HS_local [(jiminny@localhost]& console [PRolx# console lcu)« console [STAGING]AND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_1d, '(, =1))GROUP BY t.id, t.name, calendar domainORDER BY t.name, calendar domain:select * trom users u 1oin calendars c 1<->I.n. on c.user 10 = U.10where u,team id = 882select * from activities where 1d = 14049485: # team 563 crm 537.select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc;select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * from activity searches where id = 87714:select * from activity search_filters where activity search_id = 87714:SELECT * FROM activities WHERE uvid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELECT * FROM crm_configurations WHERE provider = 'hubspot';ated_report_results where media type = 'pdf' and status = 2and id IN (18, 1872)select * from automated_reports where id = 54;SELECT * EROM usens WHERE id TN (24623.29443.2961399So jiminny040 A1 A40 Y 65 ^SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;666 vselect * from text_relays where created_at › '2026-05-01'# and id IN (32415, 32416);and id = 32412:'— 668-669- 070select * from users where team id = 2 and email like '%scott%' and id = 29510-& Shortcuts conflictsClone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....Modifv ShortcutsDon't Show AdainUTE.Rio 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34552
|
1295
|
12
|
2026-05-13T11:23:33.735159+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671413735_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"31","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7697358862744210322
|
-4206073567320668088
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34553
|
1296
|
15
|
2026-05-13T11:23:33.747669+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671413747_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.12849163,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"}]...
|
3122775930622718190
|
-4278122356876834356
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12...
|
34551
|
NULL
|
NULL
|
NULL
|
|
34554
|
1296
|
16
|
2026-05-13T11:23:36.582729+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671416582_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.12849163,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.5152925,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.48404256,"top":0.15881884,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"31","depth":4,"bounds":{"left":0.49335107,"top":0.15881884,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.5049867,"top":0.15881884,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.51396275,"top":0.15722266,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.5212766,"top":0.15722266,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.5299202,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.53856385,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.54953456,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.5581782,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.5668218,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.5777925,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.5887633,"top":0.074221864,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.61535907,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.6263298,"top":0.074221864,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9587766,"top":0.074221864,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.9281915,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.94049203,"top":0.09896249,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.94980055,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"bounds":{"left":0.96210104,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9740692,"top":0.09736632,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.98138297,"top":0.09736632,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"}]...
|
1675972978730997373
|
2218635325254022725
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34555
|
1295
|
13
|
2026-05-13T11:23:36.596030+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671416596_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"31","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3205990197548604186
|
2218635325254022725
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
1
31
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
34552
|
NULL
|
NULL
|
NULL
|
|
34556
|
1295
|
14
|
2026-05-13T11:23:41.028706+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671421028_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2596895591867851825
|
-3710668803626826292
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34557
|
1296
|
17
|
2026-05-13T11:23:41.050313+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671421050_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.1300878,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.1292897,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.1292897,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.12849163,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.12769353,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2596895591867851825
|
-3710668803626826292
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight...
|
34554
|
NULL
|
NULL
|
NULL
|
|
34558
|
1295
|
15
|
2026-05-13T11:23:44.018570+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671424018_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_selected":false,"is_expanded":false}]...
|
-4338288383390440797
|
-3411194954655512372
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest...
|
34556
|
NULL
|
NULL
|
NULL
|
|
34559
|
1296
|
18
|
2026-05-13T11:23:43.985182+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671423985_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"","depth":2,"bounds":{"left":0.8976064,"top":0.82681566,"width":0.06948138,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":2,"bounds":{"left":0.8976064,"top":0.858739,"width":0.06948138,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1088625150928280118
|
-4131759766773487156
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34560
|
1296
|
19
|
2026-05-13T11:23:45.033213+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671425033_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormINavigareCodeLaravelKeractor© MailboxContr PhostormINavigareCodeLaravelKeractor© MailboxController.php© UpdateBotAvatar.phC Uodate leamrnoto.pm SuoportTextkelayservice.ong© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports0 Audio251258v _ Automateakeporis© RequestGenerateAskJin259class EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)A30 X1 ^ v 629(C) KequestGeneratekeponi© SendReportExpiringSooc) senckepor.ob.ong© SendReportMailJob.php264C) SendReport NotGenerat0 Calendarv D crmM Delete266→ Huosoot268M SalesforceC) AutoloaDelavedToCrm.r(C) CheckAndRetrvRemote!271273© CreateNotes.php(c) MatchActivitiecToNewol© MatchActivityCrmData.p(6 Note@hiect nhn© SaveActivity.php© SaveTranscription.php©SetupLayout.pho© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.ph© SyncLeads.php© SyncObiects.php© SyncOpportunitiesJob.p© SyncOpportunity.php© SyncProfileMetadata.ph© SyncTeamFieldsJob.phgc) SuncireamMetadata.onr@ Undate@pportunitvSped(C) UodateStade oho> MDealRisks292v 7 MailboxC) CreateBatches.ohoC) Createlnbox.ohog DeleteFmailMeccanes.ld295(c) SmailTeytRelav nho(C) Suneinhoy nhn> M MoptinaRotStext = sema1l->gecv1s1dlelexcif (Stext === ") {throw new TextRelayException(: 'Message body is un-readable or empty.'.code: self::REASON_CODE MESSAGE BODY_EMPTYSvalidator = Validator::make('data' => Stextl, 'data' => new SmsMessageOlDs1f Svalidator->farlsonthrow new TextrelayException'Message body is too large to send as an SMS.',code: self::REASON_CODE_MESSAGE_BODY_TOO_LARGESthis->text = Stext.Scenden = Sthis->nanceSenden/Sheadenc/"From')-// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient(1] !== config( key: "jiminny.google_ text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom. Sto. Sactivitvidl = Sthis->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidator->fails@) {throw new TextRelavExcention('Recinient origin number is not valid.'.code: self.•REASON CODE RECIPTENT ORIGIN INVALTD1631I032Dnnnnn644648- 651=653654— 65— 65-66662'- 667- 668- 669— 676icts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (2 minutes ago|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]A console [STAGING]AND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider id.'(d, -1)0|GROUP 8Y 1.1d. t.name. calendar domaniORDER BY t.name, calendar domain:select * from users u join calendars c 1<->l.n: on c.user_id = u.idwhere U.team 1d = 8821select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircall'and account_id = 19003658 order by updated_at desc:select * from contacts where crm confiquration id = 537 and id = 35957759:select * from accounts where crm confiquration id = 537 and id = 19003658:SUlts where 10 = 19767select * tromautomated reports where 10 = 5857select * from activity searches where id = 87714:select * tromactivity search tzlterswhere actzvitv search 1d = 87141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * From nate Uimits:select * fromand id IN (18, 1872);select * from automated_reports where id = 54)SELECT * FROM users WHERE id IN (24623,29443,29613);ted_report_results where media type = 'pdf' and status = 2SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text relays where created at > '2026-05-01# and id IN (32415, 32416):and id = 32412:select * from users where team id = 2 and email like '%scott%' and id = 29510:• suppont Dally • In 37 m100% L2• Wed 13 May 14:23:44AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleSMS Failure Email Inve+0 •So jiminnycontinue040 A1 A40 V 65 ^Read UserRepository.php #L325-354ExternalldUniquetoHostValidationRule.pho•ExternalldUniqueToHostValidationRule.php+4 -2• ExternalldUniqueToHostValidationRule.php+1 -2I've completed updating all the places where users are searched by email to include secondary_email as well. Here's asummary of the changes:Files Updated1. EmailTextRelay.php (line 304)• Replaced User::where('email', Ssender)->first() with SuserRepository->findByEmail(Ssender)•This tixes Scott's case - ithe hasrewardoatewav.com as his secondarv emall. the SMS relay willl now work2. Guards/Sso.oho (lines 17. 29)• Renlaced both User:«where('email'. ...)-first/) calls with Sthis-suserRenositorv->findBvEmai1(...)•SSO login will now check both email fields3. Http/Controllers/APl/SsoController.php (line 32)• Replaced User::where('email", Srequest→>email)→first with Sthis->userRepository->findBvEmail(Srealuest_semail)•SSO loain endpoint will now check both email fields4Listeners/UsersNalidateSendinaMessage.nho line 31)• Replaced User::where('email'. Saddress)→firsto withsthis->userReposiltorv->findByEmaiiSaddress)Smoil rosiniont volidation will naw shosk both omail fiolde5. Services/SocialAccountService.ono (line 355•Replaced User::where('email'. SuserData('email'])->first() with Sthis->userRepository->findByEmail(sucerDatal "emaili1)• •Auth social account lookup will now check both emall tields6. Htto/Controllers/Auth/ExtensionController.oho (line 215)• Replaced User::where ('emas1", ...)-suhere("status'. ...)-firct() with sthis-suserRenositorv->findBvElView allapp/Services/#SocialAccountService.pho +3 -1app/Http/Controllers/Auth/ ExtensionController.php +1 -3ollers APl u Ssocontroller.php +4 -2anniGunrdel M Sco nhn 48 .2app/Listeners/Users/ ValidateSendingMessage.php +6 -3les/M SxternalidUniqueToHostValidationRule.ohv +6 -4A Shortcuts conflictsI need onlv EmailTextRelav?Clone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....« Code SWF-1.6Modifv ShortcutsDon't Show AdainWN Windsurf Teams282-50UTC.8io 4 spaces...
|
NULL
|
1847970321021460315
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhostormINavigareCodeLaravelKeractor© MailboxContr PhostormINavigareCodeLaravelKeractor© MailboxController.php© UpdateBotAvatar.phC Uodate leamrnoto.pm SuoportTextkelayservice.ong© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports0 Audio251258v _ Automateakeporis© RequestGenerateAskJin259class EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegrity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)A30 X1 ^ v 629(C) KequestGeneratekeponi© SendReportExpiringSooc) senckepor.ob.ong© SendReportMailJob.php264C) SendReport NotGenerat0 Calendarv D crmM Delete266→ Huosoot268M SalesforceC) AutoloaDelavedToCrm.r(C) CheckAndRetrvRemote!271273© CreateNotes.php(c) MatchActivitiecToNewol© MatchActivityCrmData.p(6 Note@hiect nhn© SaveActivity.php© SaveTranscription.php©SetupLayout.pho© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.ph© SyncLeads.php© SyncObiects.php© SyncOpportunitiesJob.p© SyncOpportunity.php© SyncProfileMetadata.ph© SyncTeamFieldsJob.phgc) SuncireamMetadata.onr@ Undate@pportunitvSped(C) UodateStade oho> MDealRisks292v 7 MailboxC) CreateBatches.ohoC) Createlnbox.ohog DeleteFmailMeccanes.ld295(c) SmailTeytRelav nho(C) Suneinhoy nhn> M MoptinaRotStext = sema1l->gecv1s1dlelexcif (Stext === ") {throw new TextRelayException(: 'Message body is un-readable or empty.'.code: self::REASON_CODE MESSAGE BODY_EMPTYSvalidator = Validator::make('data' => Stextl, 'data' => new SmsMessageOlDs1f Svalidator->farlsonthrow new TextrelayException'Message body is too large to send as an SMS.',code: self::REASON_CODE_MESSAGE_BODY_TOO_LARGESthis->text = Stext.Scenden = Sthis->nanceSenden/Sheadenc/"From')-// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient(1] !== config( key: "jiminny.google_ text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom. Sto. Sactivitvidl = Sthis->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidator->fails@) {throw new TextRelavExcention('Recinient origin number is not valid.'.code: self.•REASON CODE RECIPTENT ORIGIN INVALTD1631I032Dnnnnn644648- 651=653654— 65— 65-66662'- 667- 668- 669— 676icts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (2 minutes ago|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]A console [STAGING]AND td.deleted at IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider id.'(d, -1)0|GROUP 8Y 1.1d. t.name. calendar domaniORDER BY t.name, calendar domain:select * from users u join calendars c 1<->l.n: on c.user_id = u.idwhere U.team 1d = 8821select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircall'and account_id = 19003658 order by updated_at desc:select * from contacts where crm confiquration id = 537 and id = 35957759:select * from accounts where crm confiquration id = 537 and id = 19003658:SUlts where 10 = 19767select * tromautomated reports where 10 = 5857select * from activity searches where id = 87714:select * tromactivity search tzlterswhere actzvitv search 1d = 87141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * From nate Uimits:select * fromand id IN (18, 1872);select * from automated_reports where id = 54)SELECT * FROM users WHERE id IN (24623,29443,29613);ted_report_results where media type = 'pdf' and status = 2SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text relays where created at > '2026-05-01# and id IN (32415, 32416):and id = 32412:select * from users where team id = 2 and email like '%scott%' and id = 29510:• suppont Dally • In 37 m100% L2• Wed 13 May 14:23:44AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleSMS Failure Email Inve+0 •So jiminnycontinue040 A1 A40 V 65 ^Read UserRepository.php #L325-354ExternalldUniquetoHostValidationRule.pho•ExternalldUniqueToHostValidationRule.php+4 -2• ExternalldUniqueToHostValidationRule.php+1 -2I've completed updating all the places where users are searched by email to include secondary_email as well. Here's asummary of the changes:Files Updated1. EmailTextRelay.php (line 304)• Replaced User::where('email', Ssender)->first() with SuserRepository->findByEmail(Ssender)•This tixes Scott's case - ithe hasrewardoatewav.com as his secondarv emall. the SMS relay willl now work2. Guards/Sso.oho (lines 17. 29)• Renlaced both User:«where('email'. ...)-first/) calls with Sthis-suserRenositorv->findBvEmai1(...)•SSO login will now check both email fields3. Http/Controllers/APl/SsoController.php (line 32)• Replaced User::where('email", Srequest→>email)→first with Sthis->userRepository->findBvEmail(Srealuest_semail)•SSO loain endpoint will now check both email fields4Listeners/UsersNalidateSendinaMessage.nho line 31)• Replaced User::where('email'. Saddress)→firsto withsthis->userReposiltorv->findByEmaiiSaddress)Smoil rosiniont volidation will naw shosk both omail fiolde5. Services/SocialAccountService.ono (line 355•Replaced User::where('email'. SuserData('email'])->first() with Sthis->userRepository->findByEmail(sucerDatal "emaili1)• •Auth social account lookup will now check both emall tields6. Htto/Controllers/Auth/ExtensionController.oho (line 215)• Replaced User::where ('emas1", ...)-suhere("status'. ...)-firct() with sthis-suserRenositorv->findBvElView allapp/Services/#SocialAccountService.pho +3 -1app/Http/Controllers/Auth/ ExtensionController.php +1 -3ollers APl u Ssocontroller.php +4 -2anniGunrdel M Sco nhn 48 .2app/Listeners/Users/ ValidateSendingMessage.php +6 -3les/M SxternalidUniqueToHostValidationRule.ohv +6 -4A Shortcuts conflictsI need onlv EmailTextRelav?Clone Carer Below and i more shon cur contlictiwith macos shortcuts. Modity these shortcuts or....« Code SWF-1.6Modifv ShortcutsDon't Show AdainWN Windsurf Teams282-50UTC.8io 4 spaces...
|
34559
|
NULL
|
NULL
|
NULL
|
|
34561
|
1295
|
16
|
2026-05-13T11:23:47.797825+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671427797_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.0,"top":0.0,"width":0.034027778,"height":0.018888889},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4752793375569107729
|
-4564105331001062964
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34562
|
1296
|
20
|
2026-05-13T11:23:47.797820+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671427797_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Shortcuts conflicts","depth":2,"bounds":{"left":0.8753325,"top":0.89944136,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","depth":3,"bounds":{"left":0.8753325,"top":0.915403,"width":0.11037234,"height":0.027134877},"on_screen":true,"value":"Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.915403,"width":0.10139628,"height":0.040702313},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Modify Shortcuts","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.03523936,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Don't Show Again","depth":2,"bounds":{"left":0.91589093,"top":0.9481245,"width":0.036236703,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"More","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.016289894,"height":0.0},"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
4851342688736814118
|
-4564107525797491508
|
click
|
accessibility
|
NULL
|
Shortcuts conflicts
Clone Caret Below and 1 more s Shortcuts conflicts
Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings.
text/html
text/html
text/html
Modify Shortcuts
Don't Show Again
More
Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34563
|
1295
|
17
|
2026-05-13T11:24:05.133078+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671445133_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"30","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1649737482680982656
|
2218635325254022725
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
34561
|
NULL
|
NULL
|
NULL
|
|
34564
|
1296
|
21
|
2026-05-13T11:24:06.641899+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671446641_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.15482841,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.15403032,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.15323225,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.3949468,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"30","depth":4,"bounds":{"left":0.3723404,"top":0.18355946,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.38464096,"top":0.18355946,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39361703,"top":0.1819633,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40093085,"top":0.1819633,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.40957448,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.41821808,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.42918882,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.43783244,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.44647607,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4574468,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.46841756,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.4950133,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.50598407,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.7084442,"top":0.09896249,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.67785907,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.69015956,"top":0.123703115,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.6994681,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"bounds":{"left":0.7117686,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7237367,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.73105055,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1649737482680982656
|
2218635325254022725
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
34562
|
NULL
|
NULL
|
NULL
|
|
34565
|
1295
|
18
|
2026-05-13T11:24:35.607379+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671475607_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"30","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1649737482680982656
|
2218635325254022725
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34566
|
1296
|
22
|
2026-05-13T11:24:37.058734+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671477058_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.15482841,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.15403032,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.15323225,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.3949468,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"30","depth":4,"bounds":{"left":0.3723404,"top":0.18355946,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.38464096,"top":0.18355946,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39361703,"top":0.1819633,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40093085,"top":0.1819633,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.40957448,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.41821808,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.42918882,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.43783244,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.44647607,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4574468,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.46841756,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.4950133,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.50598407,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.7084442,"top":0.09896249,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.67785907,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.69015956,"top":0.123703115,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.6994681,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"bounds":{"left":0.7117686,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7237367,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.73105055,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1649737482680982656
|
2218635325254022725
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34567
|
1295
|
19
|
2026-05-13T11:25:05.433882+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671505433_m1.jpg...
|
PhpStorm
|
faVsco.js – console [PROD]
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7673782238848625796
|
-8646559087753982588
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
SlackFileEdi Project: faVsco.js, menu
master, menu
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKER181DEV (docker)₴82APP (-zshDOCKER (docker-compose)docker_lamp_12026-05-13 11:23:17 Jiminny\Services\Crm\IntegrationApp\Jobs\ValidateTeamActiveConnectionJobdocker_1amp_1TeamActiveConnectionJob2026-05-13 11:23:17 Jiminny\Services\Crm\IntegrationApp\Jobs\Validate471.18ms DONEdocker_lamp_1docker_1amp_112026-05-13 11:24:02 Running ['artisan'meeting-bot: schedule-bot]3sDONEdocker_1amp_11 '/usr/local/bin/php' 'artisan"meeting-bot: schedule-bot > */proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:24:06 Running ['artisan' dialers:monitor-activities] .4s DONEdocker_lamp_11/fd/1'1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/docker_lamp_12026-05-13 11:24:10 Running ['artisan' jiminny:monitor-social-account3S DONEdocker_lamp_111 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */proc/1/fd/1'2>&1docker_lamp_1|2026-05-13 11:24:14 Running ['artisan' mailbox:skip-lists:refresh]3S DONEdocker_lamp_1I l '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/1/fd/1'2>&1docker_lamp_112026-05-13 11:24:17 Running ['artisan' mailbox:batch:process--max-batches=15]docker_1amp_1• '/usr/local/bin/php' 'artisan' mailbox:batch:process --max-batches=15 > '/proc/1/fd/1'docker_lamp_12026-05-13 11:24:19 Running ['artisan' conference:monitor: count]1sDONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' conference:monitor: count › */proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:24:21 Running ['artisan' activity:aircall:check-and-rendocker_lamp_1/proc/1/fd/1'docker_1amp_11sDONEdocker_lamp_1c/1/fd/1'2>&1docker_1amp_1docker_lamp_1docker_lamp_11 '/usr/local/bin/php' 'artisan' activity:aircall:check-and-renew > '2>812026-05-13 11:24:24 Running ['artisan'track:retry-failed-downloads]1 '/usr/local/bin/php' 'artisan' track:retry-failed-downloads › '/prorun_artisan_schedule: Done waiting for schedule:runView in Docker Desktopo View Configw Enable WatchHomeDMsActivityFilesLaterMorela6l→Jiminny ...ab External connections* Starred& jiminny-x-integrati...8platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general#jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...° Direct messagesNikolay Ivanovd. James GrahamTAWATERANUnread mentionsSupport Daily • in 35 m100% <28•Wed 13 May 14:25:05Describe what you are looking for# platform-tickets8146 0• Messagest Add canvasO Filesmhe PrioritThursday, April 16th~+Tuesday, May 5th ~Automation for Jira APP2:12 PMSRD-6835 Salesforce app issues has been raisedwith Platform team and assigned to **. The Priorityis P2 MediumAutomation for Jira APP5:01 PMSRD-6815 [Playback] Ask Jiminny odd behaviourhas been raised with Platform team and assigned toSteliyan Georgiev. The Priority is P2 MediumMonday, May 11th ~Automation for Jira APP 4:38 PMSRD-6845 CRM filling is not being applied has beenraised with Platform team and assigned to **. ThePriority is **Today ~Automation for Jira APP10:42 AMSRD-6848 Sidekick SMS issue has been raised withPlatform team and assigned to **. The Priority is **NewAutomation for Jira APP 1:33 PMSRD-6849 Recorded call does not appear on thedashboard has been raised with Platform team andassigned to **. The Priority is **Message #platform-tickets...
|
34565
|
NULL
|
NULL
|
NULL
|
|
34568
|
1296
|
23
|
2026-05-13T11:25:05.442796+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671505442_m2.jpg...
|
PhpStorm
|
faVsco.js – console [PROD]
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormINavigareCodeLaravelKeractor?9 master© Mai PhostormINavigareCodeLaravelKeractor?9 master© MailboxController.php|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]© UpdateBotAvatar.phTextkelayservice.ongA console [STAGING]C Uodate leamrnoto.pm Suoport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports251class EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegnity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)A30 X1 A v 6290 Audio258Stext = sema1l->gecv1s1dlelexcv _ Automateakeporis© RequestGenerateAskJin259(C) KequestGeneratekeponi© SendReportExpiringSooc) senckepor.ob.ong© SendReportMailJob.php264C) SendReport NotGenerat0 Calendarv D crm266M Delete→ Huosoot268M SalesforceC) AutoloaDelavedToCrm.r271(C) CheckAndRetrvRemote!© CreateNotes.php273(c) MatchActivitiecToNewol© MatchActivityCrmData.p(6 Note@hiect nhn© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.ph© SyncLeads.php© SyncObiects.php© SyncOpportunitiesJob.p© SyncOpportunity.php© SyncProfileMetadata.ph© SyncTeamFieldsJob.phgc) SuncireamMetadata.onr@ Undate@pportunitvSped(C) UodateStade oho> MDealRisksv 7 MailboxC) CreateBatches.ohoC) Createlnbox.ohog DeleteFmailMeccanes.ld295(c) SmailTeytRelav nho(C) Suneinhoy nhn> M MoptinaRotif (Stext === ") {throw new TextRelayException(: 'Message body is un-readable or empty.'.code: self::REASON_CODE MESSAGE BODY_EMPTYSvalidator = Validator: :make('data' => Stextlr 'data' => new SmsMessage 0lDs1f Svalidator->farlsonthrow new TextrelayException'Message body is too large to send as an SMS.',code: self::REASON_CODE_MESSAGE_BODY_TOO_LARGESthis->text = Stext.Scenden = Sthis->nanceSenden/Sheadenc/"From')-// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient(1] !== config( key: "jiminny.google_ text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom. Sto. Sactivitvidl = Sthis->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidator->fails@) {throw new TextRelavExcention('Recinient origin number is not valid.'..code: self.•REASON CODE RECIPTENT ORIGIN INVALIDSvalidator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']):1631I03211111644648650- 651=653654— 65— 65659-66662664T665666 /'- 667- 668- 669-/70icts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (3 minutes agoSo jiminny040 A1 A40 V 65 ^AND td.deletedat IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider id.'(d', -1)0|GROUP 8Y 1.1d. t.name. calendar domaniORDER BY t.name, calendar domain:select * from users u join calendars c 1<->l.n: on c.user_id = u.idwhere U.team 1d = 8821select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircall'and account_id = 19003658 order by updated_at desc:select * from contacts where crm confiquration id = 537 and id = 35957759:select * from accounts where crm confiquration id = 537 and id = 19003658:SUlts where 10 = 19767select * tromautomated reports where 10 = 5857select * from activity searches where id = 87714:select * tromactivity search tzlterswhere actzvitv search 1d = 87141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * From nate Uimits:select * fromted_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54)SELECT * FROM users WHERE id IN (24623,29443,29613);SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text relays where created at > '2026-05-01'# and id IN (32415, 32416):and id = 32412:select * from users where team id = 2 and email like '%scott%' and id = 29510:suppont Dally • In 3ol100% L2• Wed 13 May 14:25:05AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User Em+0 ..Ineed only EmailTextRelay? | changed it a bit. REveiw itRead EmailTextRelay.phpTnoughttor 2s>Your changes to EmailTextRelay.php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows codina standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251 - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User::where('emas]" Ssender)-sfirst() to SuserRenositorv->filReview:wllserReSitorv: :findBvEmailo checks both emaii and cecondarv emaii fieldsThe dependency injection is cleaner - UserRepository is only used where needed• V Folllows the codina standards (multi- ine method sianatures• • No breaking changes to the existing logicThis approach is actually better than mine - vou kept the UserRepository usage localized to checkintegrity where theucor lookun sctually hannens rather than ucina it in bandle and naccina the ticer aroundlThe fix will resolve Scott's issue if he adds rewardgateway.com as his secondary_emait in Jiminny. The SMS relay will nowtind his account when he sends from that email adaress.lo Il «.View alllapp/Services/#SocialAccountService.pho +3 -1app/Http/Controllers/Auth/ ExtensionController.php +1-3llers/API SsoController.php +4 -2annlGuardel MSco nhn 48app/Listeners/Users/ ValidateSendingMessage.php +6 -3es/# SxternalldUniqueToHostValidationRule.ohvAsk anvthina (84L)« Code SWF-1.6Reiect allAccent alliWN Windsurf Toams 282-50 UTF.9io 4 spaces...
|
NULL
|
-361374171825996954
|
NULL
|
click
|
ocr
|
NULL
|
PhostormINavigareCodeLaravelKeractor?9 master© Mai PhostormINavigareCodeLaravelKeractor?9 master© MailboxController.php|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]© UpdateBotAvatar.phTextkelayservice.ongA console [STAGING]C Uodate leamrnoto.pm Suoport© CheckTeamPlanEligibility.pvD Jobs> @ Activity0 AiAutomation0 AjReports251class EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegnity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)A30 X1 A v 6290 Audio258Stext = sema1l->gecv1s1dlelexcv _ Automateakeporis© RequestGenerateAskJin259(C) KequestGeneratekeponi© SendReportExpiringSooc) senckepor.ob.ong© SendReportMailJob.php264C) SendReport NotGenerat0 Calendarv D crm266M Delete→ Huosoot268M SalesforceC) AutoloaDelavedToCrm.r271(C) CheckAndRetrvRemote!© CreateNotes.php273(c) MatchActivitiecToNewol© MatchActivityCrmData.p(6 Note@hiect nhn© SaveActivity.php© SaveTranscription.php© SetupLayout.php© SyncActivity.php© SyncFieldMetadata.php© SyncHubspotObjects.ph© SyncLeads.php© SyncObiects.php© SyncOpportunitiesJob.p© SyncOpportunity.php© SyncProfileMetadata.ph© SyncTeamFieldsJob.phgc) SuncireamMetadata.onr@ Undate@pportunitvSped(C) UodateStade oho> MDealRisksv 7 MailboxC) CreateBatches.ohoC) Createlnbox.ohog DeleteFmailMeccanes.ld295(c) SmailTeytRelav nho(C) Suneinhoy nhn> M MoptinaRotif (Stext === ") {throw new TextRelayException(: 'Message body is un-readable or empty.'.code: self::REASON_CODE MESSAGE BODY_EMPTYSvalidator = Validator: :make('data' => Stextlr 'data' => new SmsMessage 0lDs1f Svalidator->farlsonthrow new TextrelayException'Message body is too large to send as an SMS.',code: self::REASON_CODE_MESSAGE_BODY_TOO_LARGESthis->text = Stext.Scenden = Sthis->nanceSenden/Sheadenc/"From')-// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient(1] !== config( key: "jiminny.google_ text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[Sfrom. Sto. Sactivitvidl = Sthis->parseRecipientIntoEntities(Srecipient[0l):Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidator->fails@) {throw new TextRelavExcention('Recinient origin number is not valid.'..code: self.•REASON CODE RECIPTENT ORIGIN INVALIDSvalidator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']):1631I03211111644648650- 651=653654— 65— 65659-66662664T665666 /'- 667- 668- 669-/70icts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (3 minutes agoSo jiminny040 A1 A40 V 65 ^AND td.deletedat IS NULLAND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider id.'(d', -1)0|GROUP 8Y 1.1d. t.name. calendar domaniORDER BY t.name, calendar domain:select * from users u join calendars c 1<->l.n: on c.user_id = u.idwhere U.team 1d = 8821select * from activities where id = 74049485; # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities where id = 54520297; # team 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircall'and account_id = 19003658 order by updated_at desc:select * from contacts where crm confiquration id = 537 and id = 35957759:select * from accounts where crm confiquration id = 537 and id = 19003658:SUlts where 10 = 19767select * tromautomated reports where 10 = 5857select * from activity searches where id = 87714:select * tromactivity search tzlterswhere actzvitv search 1d = 87141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuid to bin(•47842446-af51-4bcb-854f-cc6560290101') = uuid:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * From nate Uimits:select * fromted_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * from automated_reports where id = 54)SELECT * FROM users WHERE id IN (24623,29443,29613);SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text relays where created at > '2026-05-01'# and id IN (32415, 32416):and id = 32412:select * from users where team id = 2 and email like '%scott%' and id = 29510:suppont Dally • In 3ol100% L2• Wed 13 May 14:25:05AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User Em+0 ..Ineed only EmailTextRelay? | changed it a bit. REveiw itRead EmailTextRelay.phpTnoughttor 2s>Your changes to EmailTextRelay.php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows codina standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251 - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User::where('emas]" Ssender)-sfirst() to SuserRenositorv->filReview:wllserReSitorv: :findBvEmailo checks both emaii and cecondarv emaii fieldsThe dependency injection is cleaner - UserRepository is only used where needed• V Folllows the codina standards (multi- ine method sianatures• • No breaking changes to the existing logicThis approach is actually better than mine - vou kept the UserRepository usage localized to checkintegrity where theucor lookun sctually hannens rather than ucina it in bandle and naccina the ticer aroundlThe fix will resolve Scott's issue if he adds rewardgateway.com as his secondary_emait in Jiminny. The SMS relay will nowtind his account when he sends from that email adaress.lo Il «.View alllapp/Services/#SocialAccountService.pho +3 -1app/Http/Controllers/Auth/ ExtensionController.php +1-3llers/API SsoController.php +4 -2annlGuardel MSco nhn 48app/Listeners/Users/ ValidateSendingMessage.php +6 -3es/# SxternalldUniqueToHostValidationRule.ohvAsk anvthina (84L)« Code SWF-1.6Reiect allAccent alliWN Windsurf Toams 282-50 UTF.9io 4 spaces...
|
34566
|
NULL
|
NULL
|
NULL
|
|
34569
|
1295
|
20
|
2026-05-13T11:25:07.304096+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671507304_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4235983745889776938
|
-8204421443435123770
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKERDOCKER (docker-compose)docker_lamp_1docker_lamp_1181DEV (docker)₴82APP (-zsh2026-05-13 11:24:02 Running ['artisan'meeting-bot:schedule-bot]docker_1amp_11 '/usr/local/bin/php' 'artisan"meeting-bot: schedule-bot >*/proc/1/2026-05-13 11:24:06 Running L'artisan'dialers:monitor-activities]4sDONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › */proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:24:10 Running ['artisan' jiminny:monitor-social-account3s DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > '/proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:24:14 Running ['artisan' mailbox:skip-lists:refresh]3sDONEdocker_lamp_11 '/usr/local/bin/php' 'artisan'mailbox:skip-lists:refresh › */proc/1/fd/1'2>&1docker_1amp_12026-05-13 11:24:17 Running ['artisan' mailbox:batch:process --max-batches=15]1s DONEdocker_Lamp_1L '/usr/local/bin/php' 'artisan' mailbox:batch:process --max-batches=15 >*/proc/1/fd/1' 2>&1docker_lamp_12026-05-13 11:24:19 Running ['artisan'conference:monitor:count]1S DONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' conference:monitor: count > */proc/1/fd/1'2>&1docker_lamp_12026-05-13 11:24:21 Running ['artisan' activity:aircall: check-and-ren2S DONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' activity:aircall: check-and-renew > */proc/1/fd/1'docker_lamp_12026-05-13 11:24:24 Running ['artisan' track:retry-failed-downloads]1s DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' track:retry-failed-downloads › '/proc/1/fd/1'2>&1docker_lamp_1docker_lamp_1run_artisan_schedule: Done waiting for schedule:rundocker_lamp_1docker_lamp_12026-05-13 11:25:03 Running ['artisan'meeting-bot:schedule-bot] ….3s DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' meeting-bot:schedule-bot › '/proc/1/fd/1' 2>&1.View in Docker Desktopo View Configw Enable WatchHomeDMsActivityFilesLater..•Morela6l→Jiminny ...ab External connections* Starred& jiminny-x-integrati...8platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general#jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...° Direct messagesNikolay Ivanovd. James GrahamTAWATERANUnread mentionsSupport Daily • in 35 m100% <28•Wed 13 May 14:25:07Describe what you are looking for# platform-tickets8146 0• Messagest Add canvasO Filesmhe PrioritThursday, April 16th~+Tuesday, May 5th ~Automation for Jira APP2:12 PMSRD-6835 Salesforce app issues has been raisedwith Platform team and assigned to **. The Priorityis P2 MediumAutomation for Jira APP5:01 PMSRD-6815 [Playback] Ask Jiminny odd behaviourhas been raised with Platform team and assigned toSteliyan Georgiev. The Priority is P2 MediumMonday, May 11th ~Automation for Jira APP 4:38 PMSRD-6845 CRM filling is not being applied has beenraised with Platform team and assigned to **. ThePriority is **Today ~Automation for Jira APP10:42 AMSRD-6848 Sidekick SMS issue has been raised withPlatform team and assigned to **. The Priority is **NewAutomation for Jira APP 1:33 PMSRD-6849 Recorded call does not appear on thedashboard has been raised with Platform team andassigned to **. The Priority is **Message #platform-tickets...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34571
|
1296
|
24
|
2026-05-13T11:25:11.336363+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671511336_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5222591262487654398
|
-8636637129462003327
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
PhpStormProiectVIewINavigareCodeLaravelRefactorJOOISWindowFV faVsco.js?9 master© MailboxController.php= custom.log=laravel.logA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]g createlnoox.onpC) TextRelavService.ongC DeleteEmallmessagesscA console [STAGING]c Processtmalsonerass© SmsRelayFailed.phgSo jiminny40 41 840 X.05select * from automated_report_results where id = 19760 MeetinaBo1Middlewarew StreaminaC TeamTelephonyC User259c) ChangeEmailJob.phpDeactivateUserJob.phpc) DeleteScheduleduserAc(C) SetuoDefaultSavedSean264© SyncTolntercom.php© SyncToPlanhat.php© SyncToUserPilot.php266© BaseProcessingJob.phpc) Dummv.loh.nhn© ImportRecallAlRecordingsJ© ImportRemoteTrackJob.phG Job.phpC.lohDicnatcher nhn© JobDispatcherInterface.ph© PurgeSoftDeletedOpportur275T SqsVisibilityControl.phpv C Listenersv @ Activitiesv @ ActivityProvider> @ JustCallTextrelayExceptionselect * TrOmaucomared reports where 10 = sosselect * from activity_searches where id = 87714;class EmailTextRelay extends Job implements ShouldQueueA30 K1 A V651seLecc * Tromacclvicy search tilcerswnere accivlcy search 10 = 8/7141private function checkIntegrity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)Stext = sema1l->gecv1s1dlelexc=- 652SELECT * FROM actIvities WHERE UU1d_to_ D1n 88271672-202d-4162-9d04-73ff5f0566a9' = UU1dor uuid to_ bin(•47842446-af51-4bcb-854f-cc65602901019) = uuid:if (Stext === 1') {throw new TextRelayException(Message body 1s un-readable or empcy.'.code: self::REASON_CODE MESSAGE BODY_EMPTYSELECT * FROM crm_configurations WHERE provider = 'nubspot";select * from rate limits:658— 666$validator = Validator::make(['data' => $text], ['data' => new SmsMessage)]):if (Svalidator->fails0) {throw new TextrelayExceptionMessade body is too larde to send as an SMS.')code: self.•REASON CODE MESSAGE BODY TOO LARG:=663E664— 665=666 v— 647668669select * from automated_report_results where media type = 'pdf" and status = 2and id IN (18, 1872):select * from automated_reports where id = 54)SELECT * FROM users WHERE id IN (24623,29443,29613);SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text_relays where created_at > '2026-05-01'# and id IN (32415, 32416);and id = 32412;Sthis->text = Stext.select * from users where team_id = 2 and email like '%scott%' and id = 29510;$sender = $this->parseSender($headers['From']):// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'D)):Local ChangesConsoleDo not ignoreHighlight wordsa Base version ano/Console/Commands/.liminnvDebuaCommand.ova Shelved version• D & Sendrevor,oo Z tlle,• reorder calls 1 tlle, 11.05.26, 10:09> Move non paginator search calls to client-› search 1 file. 11.05.26. 10:07declare(strict tvnes=):declare (strict tvnes=1):› Almost ready one call to be tested 8 files, 8.05.26. 14:54> hubspot rate limit temp checkout 17 files. 8.05.26. 11:48•- namesnace Jiminnv Console Commands:namesnace liminnv Console Commands.> saved search delete 1 file. 27.04.26. 14:58expiration message 6 files. 27.04.26. 9:23• Up dev loas 1 fle 14.04.26 12:02› tem test 1 file, 24.04.26, 10:36user transformer 2 files 23.04.26 15:43email ready Q files 23.04.26 15.31Email on not sent 5 files 21.04.26 19-39use Illuminate\Console\Command=- /sest* Class JiminnyDebugCommanduse Carbon\Carbon;use Carbon\CarbonImmutableuse Illuminate\Console\Commanduse Illuminate\Support\Facades Redisuce TovalidAnaumen+Fycontion•* dpackage Jiminnu Console Commandeuse Jiminny Jobs AutomatedReports RequestGenerateAskJiminnyReportJob:uco liminnul lobelAntomotodDonontel CondDonon+Mod1 lohe• Planhat track interoct event 2 files 21 04 26 12.56> Up trackina controller 1 file 20 04 26 9•221) Mont cond if no c2 nath (fiv undato to failod) 1 filo 17 04 26 12.56.class JiminnyDebugCommand extends Commanc• ESATIIDE CHANGEC 2 4lOC 6 04 26 12-10protected Ssignature = 'jiminnv:debug':> web.php fix router 1 file, 1.04.26, 9:23ortcuts conflicts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Ag17use Jiminny Jobs\Crm\Delete\VerifyActivityCrmTaskJob:use Jiminny Jobs\Crm\MatchActivitvCrmData:use Jiminny Jobs\JobDispatcherInterfaceuse Jiminny Models Activity:suppont Dally • In 3om100% S2• Wed 13 May 14:25:11AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User EmaIneed only EmailTextRelay? | changed it a bit. REveiw itTnoughttor zsYour changes to EmailTextRelay-php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows coding standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251) - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User::where('emas]" Ssender)-sfirst() to SuserRenositorv->filllserRersitorv: :findBvEmailo checks both emaii and cecondarv email fieldsIne dependency injection is cleaner - userkepository is only used where neededFolllows the codina standards (multi-ine method sianatures)• • No breaking changes to the existing logicers/Auth/extensionController.oho +1-3app/Http/Controllers/API SsoController.php +4 -2ann/Guarde/MSco.nhn +8 -21aop/Listeners/Users/1 ValidateSendinaMessage.oho +6 -3es/# ExternalldUniqueToHostValidationRule.pho +6Ask anything (8 +L)<> Code SWE-1.6Accept all5 differencesW Windsurf Teams#henasod...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34576
|
1295
|
24
|
2026-05-13T11:25:20.807919+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671520807_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4235983745889776938
|
-8204421443435123770
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKERDOCKER (docker-compose)fd/1'2>&1docker_lamp_14S DONEdocker_1amp_11/fd/1'2>&1docker_lamp_1S]3S DONEdocker_1amp_1proc/1/fd/1'12>&1docker_lamp_13s DONEdocker_lamp_11/fd/1'2>&1docker_lamp_1tches=15]1s DONEdocker_lamp_1'/proc/1/fd/1'docker_lamp_1181DEV (docker)₴82APP (-zsh2026-05-13 11:24:06 Running ['artisan'dialers:monitor-activities]1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities"/proc/2026-05-13 11:24:10 Running L'artisan'jiminny:monitor-social-account1 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */2026-05-13 11:24:14 Running ['artisan' mailbox:skip-lists:refresh].1 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/2026-05-13 11:24:17 Running ['artisan' mailbox:batch:process --max-ba1 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=2026-05-13 11:24:19 Running ['artisan' conference:monitor:count] ...docker_lamp_11 '/usr/local/bin/php' 'artisan' conference:monitor:count › */proc/1/docker_lamp_12026-05-13 11:24:21 Running ['artisan' activity:aircall:check-and-ren• '/usr/local/bin/php' 'artisan' activity:aircall: check-and-renew > 'docker_lamp_11S DONEdocker_1amp_1c/1/fd/1'2>&1docker_lamp_1docker_lamp_1docker_lamp_1docker_1amp_13sDONEdocker_lamp_1fd/1'2>&1docker_lamp_11S DONEdocker_lamp_11/fd/1' 2>&12026-05-13 11:24:24 Running ['artisan' track:retry-failed-downloads]1 '/usr/local/bin/php' 'artisan' track:retry-failed-downloads › '/prorun_artisan_schedule: Done waiting for schedule:run2026-05-13 11:25:03 Running ['artisan'meeting-bot:schedule-bot] ...1 '/usr/local/bin/php' 'artisan'meeting-bot: schedule-bot › '/proc/1/2026-05-13 11:25:06 Running ['artisan' dialers:monitor-activities]1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/View in Docker Desktopo View Configw Enable WatchHomeDMsActivityFilesLater...Morela6lSupport Daily • in 35 m100% <78•Wed 13 May 14:25:20-→Describe what you are looking forJiminny ...# contusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches#random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messageso Nikolay IvanovJames GrahamStoyan Tanev®. Galya Dimitrova ERe Steliyan GeorgievPetko Kashinskie. Aneliya Angelova&. Stefka StoyanovaB. Vasil VasilevLukas Kovalik y... O::: AppsToastJira Cloud# releases8 226 0• Messages+C Files• BookmarksProject: appToday ~05/13/202610:15:05Tag:View JobGitHub APP 1:35 PM11 new commits pushed to master by ilian-jiminnye05484a4| - JY-20432 Added more logging forFFMPEG errors and check if s3 file is emptyd847ac11 - JY-20432 more loggingd16bf02b - JY-20432 lint fixes393f38b5 - JY-20432 fixed test70db57af - Merge branch 'master' into JY-20432-add-more-ffmpeg-loggingShow morejiminny/app | Added by GitHubNewCircleCl APP 1:58 PMDeployment Successful!Project: appWhen:05/13/202610:58:40Tag:View JobMessage #releases+Aa..•...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34577
|
1296
|
27
|
2026-05-13T11:25:21.932018+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671521932_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7429716278976468786
|
-8636355650190325311
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
PhpStormProiect vVIewINavigareCodeLaravelRefactorJOOISWindowFV faVsco.js?9 master© MailboxController.php= custom.log=laravel.logA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]g createlnoox.onpC) TextRelavService.ongC DeleteEmallmessagesscA console [STAGING]c Processtmalsonerass© SmsRelayFailed.phgSo jiminny040 A1 A40 V 65 ^select * from automated_report_results where id = 197607 MeetingBotC Middlewarew StreaminaC TeamTelephony0 Userc) ChangeEmailJob.phoDeactivateUserJob.phpc) DeleteScheduledUserAcTextrelayExceptionselect * TrOmaucomared reports where 10 = sosselect * from activity_searches where id = 87714;class EmailTextRelay extends Job implements ShouldQueueA30MTAV651seLecc * Tromacclvicy search tilcerswnere accivlcy search 10 = 8/7141private function checkIntegrity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)Stext = sema1l->gecv1s1dlelexc=- 652259SELECT * FROM actIvities WHERE UU1d_to_ D1n 88271672-202d-4162-9d04-73ff5f0566a9' = UU1dor uuid to_ bin(•47842446-af51-4bcb-854f-cc65602901019) = uuid:if (Stext === 1'){throw new TextRelayException(Message body 1s un-readable or empcy.'.code: self::REASON_CODE MESSAGE BODY_EMPTYSELECT * FROM crm_configurations WHERE provider = 'nubspot";select * from rate limits:658264© SyncTolntercom.php— 666© SyncToPlanhat.php© SyncToUserPilot.php266© BaseProcessingJob.phpc) Dummv.loh.nhn© ImportRecallAlRecordingsJ© ImportRemoteTrackJob.ph$validator = Validator::make(['data' => $text], ['data' => new SmsMessage)]):if (Svalidator->fails0) {throw new TextrelayExceptionMessade body is too larde to send as an SMS.')code: self.•REASON CODE MESSAGE BODY TOO LARG:G Job.phpC.lohDicnatcher nhn© JobDispatcherInterface.ph=663E664— 665=666 v— 647668669© PurgeSoftDeletedOpportur275Sthis->text = Stext.T SqsVisibilityControl.phpv C Listeners$sender = $this->parseSender($headers['From']):v @ Activitiesv @ ActivityProvider>C JustCall// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):select * from automated_report_results where media type = 'pdf" and status = 2and id IN (18, 1872):select * from automated_reports where id = 54)SELECT * FROM users WHERE id IN (24623,29443,29613);SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text_relays where created_at > '2026-05-01'# and id IN (32415, 32416);and id = 32412;select * from users where team_id = 2 and email like '%scott%' and id = 29510;Local ChangesConsole→ = Side-by-side viewer -Do not ignoreHighlight wordsa Base version ano/Console/Commands/.liminnvDebuaCommand.ova Shelved version• D & Sendrevor.oo Z tile• reorder calls 1 tlle, 11.05.26, 10:09> Move non paginator search calls to client-› search 1 file. 11.05.26. 10:07declare(strict tvnes=):declare (strict tvnes=1):› Almost ready one calli to be tested 8 files. 8.05.26. 14:54> hubspot rate limit temp checkout 17 files. 8.05.26. 11:48•- namesnace Jiminnv Console Commands:namesnace liminnv Console Commands.> saved search delete 1 file. 27.04.26. 14:58expiration message 6 files. 27.04.26. 9:23• Up dev loas 1 fle 14.04.26 12:02› tem test 1 file, 24.04.26, 10:36user transformer 2 files 23.04.26 15:13email ready Q files 23.04.26 15.31Email on not sent 5 files 21.04.26 19•39use Illuminate\Console\Command=- /sest* Class JiminnyDebugCommanduse Carbon\Carbon;use Carbon\CarbonImmutableuse Illuminate\Console\Commanduse Illuminate\Support\Facades Redisuce TovalidAnaumen+Fycontion•* dpackage Jiminnu Console Commandeuse Jiminny Jobs AutomatedReports RequestGenerateAskJiminnyReportJob:uco liminnul lobelAntomotodDonontel CondDonon+Mod1 lnh+• Planhat track interoct event 2 files 21.04 26 12•56> Up trackina controller 1 file 20 04 26 9•221) Mont cond if no c2 nath (fiv undato to failod) 1 filo 17 04 26 12.56.• ESATIIDE CHANGEC 2 4lOC 6 04 26 12-10> web.php fix router 1 file, 1.04.26, 9:23class JiminnyDebugCommand extends Commancprotected Ssignature = 'jiminnv:debug':17use Jiminny Jobs\Crm\Delete\VerifyActivityCrmTaskJob:use Jiminny Jobs\Crm\MatchActivitvCrmData:use Jiminny Jobs\JobDispatcherInterfaceuse Jiminny Models Activity:suppont Dally • In 3om100% S2• Wed 13 May 14:25:21AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User EmaIneed only EmailTextRelay? | changed it a bit. REveiw itTnoughttor zsYour changes to EmailTextRelay-php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows codina standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251) - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User::where('emas]" Ssender)-sfirst() to SuserRenositorv->filllserRersitorv: :findBvEmailo checks both emaii and cecondarv email fieldsIne dependency injection is cleaner - userkepository is only used where neededFolllows the codina standards (multi-ine method sianatures)• • No breaking changes to the existing logicers/Auth/extensionController.oho +1-3app/Http/Controllers/API SsoController.php +4 -2ann/Guarde/MSco.nhn +8 -21aop/Listeners/Users/1 ValidateSendinaMessage.oho +6 -3es/ ExternalldUniqueToHostValidationRule.phv +6Ask anything (8 +L)<> Code SWE-1.6Accept all5 differencesW Windsurf Teams#henasod...
|
34575
|
NULL
|
NULL
|
NULL
|
|
34578
|
1296
|
28
|
2026-05-13T11:25:24.960140+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671524960_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.15482841,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.15403032,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2325747045127793127
|
-8240172924586971708
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
PhostormINavigareCodeLaravelKeractorFV faVsco.js°9 masterProiect© MailboxController.phpg createlnoox.onpC DeleteEmallmessagessc© TextRelayService.phgc Processtmalsonerass© SmsRelayFailed.php0 MeetinaBo1C Middleware> → StreaminaC TeamTelephony0 Userclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegnity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)259260c) ChangeEmailJob.pho261DeactivateUserJob.phpc) DeleteScheduledUserAc263)(C) SetuoDefaultSavedSeanCSvncTolntercom.ohv© SyncToPlanhat.php© SyncToUserPilot.php© BaseProcessingJob.phpc) Dummv.loh.nhn264265266267269© ImportRecallAlRecordingsJ276© ImportRemoteTrackJob.ph271G Job.phpC.lohDicnatcher nhn© JobDispatcherInterface.ph© PurgeSoftDeletedOpporturT SqsVisibilityControl.phpv C Listenersv @ Activitiesv @ ActivityProvider>C JustCallv D UserPilot© TrackProviderinst> C Audic275277?D 8otsv 2 Coachina>_lintercomv PlanhatC) CreateActivitvLod© CreateCoachingFC) Createcoachings© CreateCoachingF2852862872882892902911© CreateCommenteC) CreateManaderC.2931© CreatePlayedEverC) CreateSelfCoache(e CrontoCharodEvo•MlilcorDilot(e) Cronto AvnilabilitvNot(e) CronteCanchingSoorStext = sema1l->gecv1s1dlelexcif (Stext === ') {throw new TextRelayException(: 'Message body is un-readable or empty.',code: self::REASON_CODE MESSAGE BODY_EMPTYsvauidator = Validator::make(data' => Stextlr 'data' => new SmsMessageOlD1f Svalidator->farlsonthrow new TextrelayExceptionMessade body is too larde to send as an SMS.'.code: self.•REASON CODE MESSAGE BODY TOO LARG:Sthis->text = $text;$sender = $this->parseSender($headers['From']):// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient[1] |== config( key: 'jiminny.google_text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidaton->fails0){throw new TextRelavExcention('Recipient origin number is not valid.',code: self.•REASON CODE RECIPTENT ORIGIN INVALIDSvalidator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']):ortcuts conflicts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (3 minutes ago|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]A console [STAGING]630A30MTAV-639—6331634636— 6471 64864$65€651—652— 653=654— 655~65465)=6601 66669663664T6651 668—669_ 676Tx: Auto vSo jiminnyAND td.domain = LOWERSUBSTRINGLNDEX(c.calendar provider 1d, 'd', -1)0GROUP BY t.id, t.name, calendar domain40 41 840 X.05OrDER BY t.name.select * trom users u 1o1n calendans c 1<»>I.n. on c.user 1d = U.1dwhere u.team id = 882select * from activities where id = 14049485: # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities whene id = 54520207• # +eam 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc:select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where 1d = 585;select * trom activity searches where10 = 8/1147select * trom activity search_ tilters where activity search 1d = 8/7141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuld to b1n 4/842446-2151-4000-854t-cc6568290101' = UU1d:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * from rate limitssellect * From auted_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * fromomated_reports where id = 54;SELECT * FROM users WHERE id IN (24623,29443,29613):SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text_relays where created_at > '2026-05-01'# and id IN (32415, 32416);and id = 20112.select * from users where team id = 2 and email like '%scott%' and id = 29510suppont Dally • In 3ol100% S2• Wed 13 May 14:25:24AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User EmIneed only EmailTextRelay? | changed it a bit. REveiw itRead EmailTextRelay.phpTnoughttor 2s>Your changes to EmailTextRelay.php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows codina standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251 - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User:where("emaj]" Ssender)-sfirct() to SuserRenositorv->fiReview:wulserReSitorv: :findBvEmailo checks both emaii and cecondarv email fieldsThe dependency injection is cleaner - UserRepository is only used where needed•V Folllows the codina standards (multi- ine method sianatures• • No breaking changes to the existing logicThis approach is actually better than mine - vou kept the UserRepository usage localized to checkintearity where theucor lookun sctually hannens rather than ucina it in bandle and naccina the licer aroundiThe fix will resolve Scott's issue if he adds rewardgateway.com as his secondary_emait in Jiminny. The SMS relay will nowtind his account when he sends from that email adaress.lo Il «.app/Services/#SocialAccountService.pho +3 -1app/Http/Controllers/Auth/ ExtensionController.php +1-3llers/API SsoController.php +4 -2annlGunrdel M Gco nhn 48app/Listeners/Users/ ValidateSendingMessage.php +6 -3es/# SxternalldUniqueToHostValidationRule.ohvAsk anvthina (84L)« Code SWF-1.6Reiect alllWN Windsurf Toams 277•56 UTF.9View alllAccent alliio 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34579
|
1295
|
25
|
2026-05-13T11:25:27.118466+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778671527118_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKERDOC SlackFileEditViewGoHistoryWindowHelpPRODIDOCKERDOCKER (docker-compose)fd/1'2>&1docker_lamp_14S DONEdocker_1amp_11/fd/1'2>&1docker_lamp_1S]3S DONEdocker_1amp_1proc/1/fd/1'2>&1docker_lamp_13s DONEdocker_lamp_11/fd/1'2>&1docker_lamp_1tches=15]1s DONEdocker_lamp_1'/proc/1/fd/1'docker_lamp_1181XDEV (docker)₴82APP (-zsh2026-05-13 11:24:06 Running ['artisan'dialers:monitor-activities]1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities"/proc/2026-05-13 11:24:10 Running L'artisan'jiminny:monitor-social-account1 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */2026-05-13 11:24:14 Running ['artisan' mailbox:skip-lists:refresh].1 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/2026-05-13 11:24:17 Running ['artisan' mailbox:batch:process --max-ba1 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=2026-05-13 11:24:19 Running ['artisan' conference:monitor:count] ...docker_lamp_11 '/usr/local/bin/php' 'artisan' conference:monitor:count › */proc/1/docker_lamp_12026-05-13 11:24:21 Running ['artisan' activity:aircall:check-and-ren• '/usr/local/bin/php' 'artisan' activity:aircall: check-and-renew > 'docker_lamp_11S DONEdocker_1amp_1c/1/fd/1'2>&1docker_lamp_1docker_lamp_1docker_lamp_1docker_1amp_13S DONEdocker_lamp_1fd/1'2>&1docker_lamp_11S DONEdocker_lamp_11/fd/1' 2>&12026-05-13 11:24:24 Running ['artisan' track:retry-failed-downloads]1 '/usr/local/bin/php' 'artisan' track:retry-failed-downloads › '/prorun_artisan_schedule: Done waiting for schedule:run2026-05-13 11:25:03 Running ['artisan'meeting-bot:schedule-bot] ...1 '/usr/local/bin/php' 'artisan'meeting-bot: schedule-bot › '/proc/1/2026-05-13 11:25:06 Running ['artisan' dialers:monitor-activities]1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/View in Docker Desktopo View Configw Enable WatchHomeDMsActivityFilesLater...Morela6lSupport Daily • in 35 m100% <78•-→Jiminny ...# contusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches#random# releases# sofia-office# support# thank-yous# the_people_of jimi...Wed 13 May 14:25:26Describe what you are looking for• Direct messageso Nikolay IvanovJames GrahamStoyan Tanev®. Galya DimitrovaRe Steliyan GeorgievPetko Kashinskie. Aneliya Angelova&. Stefka StoyanovaB. Vasil VasilevLukas Kovalik y... O::: AppsToastJira Cloud# releases8 226 0• Messages+C Files• BookmarksProject: appToday ~05/13/202610:15:05Tag:View JobGitHub APP 1:35 PM11 new commits pushed to master by ilian-jiminnye05484a4| - JY-20432 Added more logging forFFMPEG errors and check if s3 file is emptyd847ac11 - JY-20432 more loggingd16bf02b - JY-20432 lint fixes393f38b5 - JY-20432 fixed test70db57af - Merge branch 'master' into JY-20432-add-more-ffmpeg-loggingShow morejiminny/app | Added by GitHubNewCircleCl APP 1:58 PMDeployment Successful!Project: appWhen:05/13/202610:58:40Tag:View JobMessage #releases+..•...
|
NULL
|
-7224280218452056239
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpPRODIDOCKERDOC SlackFileEditViewGoHistoryWindowHelpPRODIDOCKERDOCKER (docker-compose)fd/1'2>&1docker_lamp_14S DONEdocker_1amp_11/fd/1'2>&1docker_lamp_1S]3S DONEdocker_1amp_1proc/1/fd/1'2>&1docker_lamp_13s DONEdocker_lamp_11/fd/1'2>&1docker_lamp_1tches=15]1s DONEdocker_lamp_1'/proc/1/fd/1'docker_lamp_1181XDEV (docker)₴82APP (-zsh2026-05-13 11:24:06 Running ['artisan'dialers:monitor-activities]1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities"/proc/2026-05-13 11:24:10 Running L'artisan'jiminny:monitor-social-account1 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts > */2026-05-13 11:24:14 Running ['artisan' mailbox:skip-lists:refresh].1 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/2026-05-13 11:24:17 Running ['artisan' mailbox:batch:process --max-ba1 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=2026-05-13 11:24:19 Running ['artisan' conference:monitor:count] ...docker_lamp_11 '/usr/local/bin/php' 'artisan' conference:monitor:count › */proc/1/docker_lamp_12026-05-13 11:24:21 Running ['artisan' activity:aircall:check-and-ren• '/usr/local/bin/php' 'artisan' activity:aircall: check-and-renew > 'docker_lamp_11S DONEdocker_1amp_1c/1/fd/1'2>&1docker_lamp_1docker_lamp_1docker_lamp_1docker_1amp_13S DONEdocker_lamp_1fd/1'2>&1docker_lamp_11S DONEdocker_lamp_11/fd/1' 2>&12026-05-13 11:24:24 Running ['artisan' track:retry-failed-downloads]1 '/usr/local/bin/php' 'artisan' track:retry-failed-downloads › '/prorun_artisan_schedule: Done waiting for schedule:run2026-05-13 11:25:03 Running ['artisan'meeting-bot:schedule-bot] ...1 '/usr/local/bin/php' 'artisan'meeting-bot: schedule-bot › '/proc/1/2026-05-13 11:25:06 Running ['artisan' dialers:monitor-activities]1 '/usr/local/bin/php' 'artisan' dialers:monitor-activities › '/proc/View in Docker Desktopo View Configw Enable WatchHomeDMsActivityFilesLater...Morela6lSupport Daily • in 35 m100% <78•-→Jiminny ...# contusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches#random# releases# sofia-office# support# thank-yous# the_people_of jimi...Wed 13 May 14:25:26Describe what you are looking for• Direct messageso Nikolay IvanovJames GrahamStoyan Tanev®. Galya DimitrovaRe Steliyan GeorgievPetko Kashinskie. Aneliya Angelova&. Stefka StoyanovaB. Vasil VasilevLukas Kovalik y... O::: AppsToastJira Cloud# releases8 226 0• Messages+C Files• BookmarksProject: appToday ~05/13/202610:15:05Tag:View JobGitHub APP 1:35 PM11 new commits pushed to master by ilian-jiminnye05484a4| - JY-20432 Added more logging forFFMPEG errors and check if s3 file is emptyd847ac11 - JY-20432 more loggingd16bf02b - JY-20432 lint fixes393f38b5 - JY-20432 fixed test70db57af - Merge branch 'master' into JY-20432-add-more-ffmpeg-loggingShow morejiminny/app | Added by GitHubNewCircleCl APP 1:58 PMDeployment Successful!Project: appWhen:05/13/202610:58:40Tag:View JobMessage #releases+..•...
|
34576
|
NULL
|
NULL
|
NULL
|
|
34708
|
1299
|
3
|
2026-05-13T11:34:44.045348+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672084045_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"30","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2526634337481503166
|
-2331678387053307803
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny...
|
34698
|
NULL
|
NULL
|
NULL
|
|
34709
|
1300
|
3
|
2026-05-13T11:34:44.190489+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672084190_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.08843085,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.15482841,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.15403032,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.15323225,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.27360374,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.3949468,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"30","depth":4,"bounds":{"left":0.3723404,"top":0.18355946,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.38464096,"top":0.18355946,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39361703,"top":0.1819633,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40093085,"top":0.1819633,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Jobs\\Mailbox;\n\nuse Illuminate\\Support\\Str;\nuse Carbon\\Carbon;\nuse Google\\Service\\Gmail as GoogleGmail;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Exceptions\\TextRelayException;\nuse Jiminny\\Jobs\\Job;\nuse EmailReplyParser\\Parser\\EmailParser;\nuse Jiminny\\Mail\\Activities\\SmsRelayFailed;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\TextRelay;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Rules\\SmsMessage;\nuse Jiminny\\Services\\Mail\\TextRelayService;\nuse Jiminny\\Services\\Telephony\\TextMessagingService;\nuse Vinkla\\Hashids\\Facades\\Hashids;\nuse Validator;\n\nclass EmailTextRelay extends Job implements ShouldQueue\n{\n use InteractsWithQueue;\n use SerializesModels;\n\n private const REASON_CODE_MAILBOX_MISMATCH = 1000;\n\n private const REASON_CODE_SENDER_UNKNOWN = 2000;\n\n private const REASON_CODE_SENDER_MISMATCH = 2100;\n\n private const REASON_CODE_SENDER_FORBIDDEN = 2200;\n\n private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;\n\n private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;\n\n private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;\n\n private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;\n\n private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;\n\n private const REASON_CODE_INVALID_HASH = 5000;\n\n private const REASON_CODE_UNKNOWN = 10000;\n\n\n private $textRelay;\n\n private $messageId;\n\n private $to;\n\n private $text;\n\n /**\n * @var Activity\n */\n private $activityOrigin;\n\n /**\n * Create a new job instance.\n */\n public function __construct(string $messageId, TextRelay $textRelay)\n {\n $this->messageId = $messageId;\n $this->textRelay = $textRelay;\n }\n\n /**\n * Execute the job.\n */\n public function handle(\n TextMessagingService $messagingService,\n TextRelayService $relayService,\n UserRepository $userRepository\n ): void {\n if (config('jiminny.google_text_host') === null) {\n return;\n }\n\n $mailService = $relayService->getService(config('jiminny.google_text_user'));\n\n try {\n // Retrieve the message from the email server.\n $message = $this->getMessage($mailService, $this->messageId);\n\n $payload = $message->getPayload();\n\n $headers = $this->getHeaders($payload->getHeaders());\n\n $date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);\n\n $this->textRelay->update([\n 'email_sent_at' => $date,\n 'sender' => Str::limit($headers['From'], 191, ''),\n 'recipient' => Str::limit($headers['To'], 191, ''),\n ]);\n\n $this->checkIntegrity($payload, $userRepository);\n\n $user = $this->activityOrigin->user;\n\n // Create the activity and send the SMS.\n $messagingService->setTeam($user->team);\n\n $message = $messagingService->send(\n $user,\n $this->to,\n $this->text\n );\n\n $activity = $messagingService->buildActivity(\n $message->sid,\n Activity::TYPE_SMS_OUTBOUND,\n $user,\n $user->softphone_number,\n $this->to,\n $this->text,\n $this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,\n strtolower($this->activityOrigin->prospect_type),\n null\n );\n\n $this->textRelay->update([\n 'origin_activity_id' => $this->activityOrigin->id,\n 'activity_id' => $activity->id,\n 'status' => TextRelay::STATUS_PROCESSED,\n ]);\n } catch (TextRelayException $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => $e->getCode(),\n ]);\n\n $sender = $this->parseSender($headers['From']);\n\n // If we can pull the sender, tell them that it failed.\n if ($sender) {\n $responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))\n ->onQueue(Constants::QUEUE_EMAILS);\n\n \\Mail::to($sender)->queue($responder);\n }\n } catch (\\Exception $e) {\n $this->textRelay->update([\n 'status' => TextRelay::STATUS_FAILED,\n 'code' => self::REASON_CODE_UNKNOWN,\n ]);\n\n \\Sentry::captureException($e);\n } finally {\n // Delete the message from the email server (it lives for 30 days).\n $this->trashMessage($mailService, $this->messageId);\n }\n }\n\n /**\n * @param GoogleGmail\\MessagePartHeader[] $rawHeaders\n */\n private function getHeaders(array $rawHeaders): array\n {\n $headers = [];\n\n foreach ($rawHeaders as $header) {\n if (\\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {\n $headers[$header->name] = $header->value;\n }\n }\n\n return $headers;\n }\n\n /**\n * @param GoogleGmail\\MessagePart[] $rawBodyParts\n */\n private function getBody(array $rawBodyParts): ?string\n {\n $body = null;\n\n foreach ($rawBodyParts as $bodyPart) {\n /* @var $bodyPart GoogleGmail\\MessagePart */\n if ($bodyPart->mimeType === 'text/plain') {\n $body = $this->base64UrlDecode($bodyPart->getBody()->getData());\n }\n }\n\n return $body;\n }\n\n private function parseSender(string $sender): ?string\n {\n preg_match_all(\n '/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,6}\\b/i',\n $sender,\n $matches,\n PREG_PATTERN_ORDER\n );\n\n return $matches[0][0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipient(string $recipient): string\n {\n preg_match(\n '/\\d+\\.\\d+\\.[a-zA-Z0-9]{10}@txt\\.(?:staging\\.)?jiminny\\.com/i',\n $recipient,\n $matches\n );\n\n if ($matches == false) {\n // This should not happen. If it does, the mailbox allowed an invalid catch-all.\n throw new TextRelayException(\n 'Recipient is missing or invalid.',\n self::REASON_CODE_RECIPIENT_MISSING_INVALID\n );\n }\n\n // Reply-To consists of digits.digits.string@mailbox\n return $matches[0];\n }\n\n /**\n * @throws \\Exception\n */\n private function parseRecipientIntoEntities(string $recipient): array\n {\n // Convert From/To/Activity into their usable types.\n [$from, $to, $encodedActivityId] = explode('.', $recipient);\n\n $from = '+' . $from;\n $to = '+' . $to;\n $activityId = Hashids::decode($encodedActivityId);\n\n return [$from, $to, $activityId];\n }\n\n /**\n * @throws \\Exception\n */\n private function checkIntegrity(GoogleGmail\\MessagePart $payload, UserRepository $userRepository)\n {\n $headers = $this->getHeaders($payload->getHeaders());\n $body = $this->getBody($payload->getParts());\n\n // Parse the email body and check it can actually be sent.\n $email = (new EmailParser())->parse($body);\n $text = $email->getVisibleText();\n\n if ($text === '') {\n throw new TextRelayException(\n 'Message body is un-readable or empty.',\n self::REASON_CODE_MESSAGE_BODY_EMPTY\n );\n }\n\n $validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Message body is too large to send as an SMS.',\n self::REASON_CODE_MESSAGE_BODY_TOO_LARGE\n );\n }\n\n $this->text = $text;\n\n $sender = $this->parseSender($headers['From']);\n\n // Extract the Jiminny recipient.\n $recipient = explode('@', $this->parseRecipient($headers['To']));\n\n // Check this message is intended for us.\n if ($recipient[1] !== config('jiminny.google_text_host')) {\n throw new TextRelayException(\n 'Destination Mailbox does not match.',\n self::REASON_CODE_MAILBOX_MISMATCH\n );\n }\n\n [$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);\n\n $validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient origin number is not valid.',\n self::REASON_CODE_RECIPIENT_ORIGIN_INVALID\n );\n }\n\n $validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);\n if ($validator->fails()) {\n throw new TextRelayException(\n 'Recipient destination number is not valid.',\n self::REASON_CODE_RECIPIENT_DESTINATION_INVALID\n );\n }\n\n $user = $userRepository->findByEmail($sender);\n if ($user === null) {\n throw new TextRelayException(\n 'Sender does not exist.',\n self::REASON_CODE_SENDER_UNKNOWN\n );\n }\n\n if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {\n throw new TextRelayException(\n 'Messaging is not enabled for this account.',\n self::REASON_CODE_SENDER_FORBIDDEN\n );\n }\n\n if ($activityId === null) {\n throw new TextRelayException(\n 'Origin activity has an invalid hash.',\n self::REASON_CODE_INVALID_HASH\n );\n }\n\n $activity = Activity::where('id', $activityId)->first();\n if ($activity && $activity->user_id !== $user->id) {\n throw new TextRelayException(\n 'Sender does not match the origin activity.',\n self::REASON_CODE_SENDER_MISMATCH\n );\n }\n\n $this->activityOrigin = $activity;\n $this->to = $to;\n }\n\n /**\n * Returns a base64 decoded web safe string\n *\n * @param string $string The string to be decoded\n *\n * @return string Decoded string\n */\n private function base64UrlDecode(string $string): string\n {\n return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));\n }\n\n public function getMessage($service, $messageId): GoogleGmail\\Message\n {\n return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);\n }\n\n public function trashMessage($service, $messageId)\n {\n return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.40957448,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.41821808,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.42918882,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.43783244,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.44647607,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4574468,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.46841756,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.4950133,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.50598407,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3810477158052140287
|
-3484599891660154779
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Sync Changes
Hide This Notification
Code changed:
Hide
30
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Jobs\Mailbox;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Google\Service\Gmail as GoogleGmail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Jiminny\Component\Queue\Constants;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Exceptions\TextRelayException;
use Jiminny\Jobs\Job;
use EmailReplyParser\Parser\EmailParser;
use Jiminny\Mail\Activities\SmsRelayFailed;
use Jiminny\Models\Activity;
use Jiminny\Models\TextRelay;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Rules\SmsMessage;
use Jiminny\Services\Mail\TextRelayService;
use Jiminny\Services\Telephony\TextMessagingService;
use Vinkla\Hashids\Facades\Hashids;
use Validator;
class EmailTextRelay extends Job implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
private const REASON_CODE_MAILBOX_MISMATCH = 1000;
private const REASON_CODE_SENDER_UNKNOWN = 2000;
private const REASON_CODE_SENDER_MISMATCH = 2100;
private const REASON_CODE_SENDER_FORBIDDEN = 2200;
private const REASON_CODE_RECIPIENT_ORIGIN_INVALID = 3000;
private const REASON_CODE_RECIPIENT_DESTINATION_INVALID = 3100;
private const REASON_CODE_RECIPIENT_MISSING_INVALID = 3200;
private const REASON_CODE_MESSAGE_BODY_TOO_LARGE = 4000;
private const REASON_CODE_MESSAGE_BODY_EMPTY = 4100;
private const REASON_CODE_INVALID_HASH = 5000;
private const REASON_CODE_UNKNOWN = 10000;
private $textRelay;
private $messageId;
private $to;
private $text;
/**
* @var Activity
*/
private $activityOrigin;
/**
* Create a new job instance.
*/
public function __construct(string $messageId, TextRelay $textRelay)
{
$this->messageId = $messageId;
$this->textRelay = $textRelay;
}
/**
* Execute the job.
*/
public function handle(
TextMessagingService $messagingService,
TextRelayService $relayService,
UserRepository $userRepository
): void {
if (config('jiminny.google_text_host') === null) {
return;
}
$mailService = $relayService->getService(config('jiminny.google_text_user'));
try {
// Retrieve the message from the email server.
$message = $this->getMessage($mailService, $this->messageId);
$payload = $message->getPayload();
$headers = $this->getHeaders($payload->getHeaders());
$date = Carbon::createFromFormat(Carbon::RFC2822, $headers['Date']);
$this->textRelay->update([
'email_sent_at' => $date,
'sender' => Str::limit($headers['From'], 191, ''),
'recipient' => Str::limit($headers['To'], 191, ''),
]);
$this->checkIntegrity($payload, $userRepository);
$user = $this->activityOrigin->user;
// Create the activity and send the SMS.
$messagingService->setTeam($user->team);
$message = $messagingService->send(
$user,
$this->to,
$this->text
);
$activity = $messagingService->buildActivity(
$message->sid,
Activity::TYPE_SMS_OUTBOUND,
$user,
$user->softphone_number,
$this->to,
$this->text,
$this->activityOrigin->prospect ? $this->activityOrigin->prospect->crm_provider_id : null,
strtolower($this->activityOrigin->prospect_type),
null
);
$this->textRelay->update([
'origin_activity_id' => $this->activityOrigin->id,
'activity_id' => $activity->id,
'status' => TextRelay::STATUS_PROCESSED,
]);
} catch (TextRelayException $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => $e->getCode(),
]);
$sender = $this->parseSender($headers['From']);
// If we can pull the sender, tell them that it failed.
if ($sender) {
$responder = (new SmsRelayFailed($this->textRelay, $e->getMessage(), $e->getCode()))
->onQueue(Constants::QUEUE_EMAILS);
\Mail::to($sender)->queue($responder);
}
} catch (\Exception $e) {
$this->textRelay->update([
'status' => TextRelay::STATUS_FAILED,
'code' => self::REASON_CODE_UNKNOWN,
]);
\Sentry::captureException($e);
} finally {
// Delete the message from the email server (it lives for 30 days).
$this->trashMessage($mailService, $this->messageId);
}
}
/**
* @param GoogleGmail\MessagePartHeader[] $rawHeaders
*/
private function getHeaders(array $rawHeaders): array
{
$headers = [];
foreach ($rawHeaders as $header) {
if (\in_array($header->name, ['To', 'From', 'X-Gm-Original-To', 'Date'])) {
$headers[$header->name] = $header->value;
}
}
return $headers;
}
/**
* @param GoogleGmail\MessagePart[] $rawBodyParts
*/
private function getBody(array $rawBodyParts): ?string
{
$body = null;
foreach ($rawBodyParts as $bodyPart) {
/* @var $bodyPart GoogleGmail\MessagePart */
if ($bodyPart->mimeType === 'text/plain') {
$body = $this->base64UrlDecode($bodyPart->getBody()->getData());
}
}
return $body;
}
private function parseSender(string $sender): ?string
{
preg_match_all(
'/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\b/i',
$sender,
$matches,
PREG_PATTERN_ORDER
);
return $matches[0][0];
}
/**
* @throws \Exception
*/
private function parseRecipient(string $recipient): string
{
preg_match(
'/\d+\.\d+\.[a-zA-Z0-9]{10}@txt\.(?:staging\.)?jiminny\.com/i',
$recipient,
$matches
);
if ($matches == false) {
// This should not happen. If it does, the mailbox allowed an invalid catch-all.
throw new TextRelayException(
'Recipient is missing or invalid.',
self::REASON_CODE_RECIPIENT_MISSING_INVALID
);
}
// Reply-To consists of digits.digits.string@mailbox
return $matches[0];
}
/**
* @throws \Exception
*/
private function parseRecipientIntoEntities(string $recipient): array
{
// Convert From/To/Activity into their usable types.
[$from, $to, $encodedActivityId] = explode('.', $recipient);
$from = '+' . $from;
$to = '+' . $to;
$activityId = Hashids::decode($encodedActivityId);
return [$from, $to, $activityId];
}
/**
* @throws \Exception
*/
private function checkIntegrity(GoogleGmail\MessagePart $payload, UserRepository $userRepository)
{
$headers = $this->getHeaders($payload->getHeaders());
$body = $this->getBody($payload->getParts());
// Parse the email body and check it can actually be sent.
$email = (new EmailParser())->parse($body);
$text = $email->getVisibleText();
if ($text === '') {
throw new TextRelayException(
'Message body is un-readable or empty.',
self::REASON_CODE_MESSAGE_BODY_EMPTY
);
}
$validator = Validator::make(['data' => $text], ['data' => new SmsMessage()]);
if ($validator->fails()) {
throw new TextRelayException(
'Message body is too large to send as an SMS.',
self::REASON_CODE_MESSAGE_BODY_TOO_LARGE
);
}
$this->text = $text;
$sender = $this->parseSender($headers['From']);
// Extract the Jiminny recipient.
$recipient = explode('@', $this->parseRecipient($headers['To']));
// Check this message is intended for us.
if ($recipient[1] !== config('jiminny.google_text_host')) {
throw new TextRelayException(
'Destination Mailbox does not match.',
self::REASON_CODE_MAILBOX_MISMATCH
);
}
[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);
$validator = Validator::make(['data' => $from], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient origin number is not valid.',
self::REASON_CODE_RECIPIENT_ORIGIN_INVALID
);
}
$validator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']);
if ($validator->fails()) {
throw new TextRelayException(
'Recipient destination number is not valid.',
self::REASON_CODE_RECIPIENT_DESTINATION_INVALID
);
}
$user = $userRepository->findByEmail($sender);
if ($user === null) {
throw new TextRelayException(
'Sender does not exist.',
self::REASON_CODE_SENDER_UNKNOWN
);
}
if ($user->softphone_number === null || ! $user->hasPermission(PermissionEnum::SMS)) {
throw new TextRelayException(
'Messaging is not enabled for this account.',
self::REASON_CODE_SENDER_FORBIDDEN
);
}
if ($activityId === null) {
throw new TextRelayException(
'Origin activity has an invalid hash.',
self::REASON_CODE_INVALID_HASH
);
}
$activity = Activity::where('id', $activityId)->first();
if ($activity && $activity->user_id !== $user->id) {
throw new TextRelayException(
'Sender does not match the origin activity.',
self::REASON_CODE_SENDER_MISMATCH
);
}
$this->activityOrigin = $activity;
$this->to = $to;
}
/**
* Returns a base64 decoded web safe string
*
* @param string $string The string to be decoded
*
* @return string Decoded string
*/
private function base64UrlDecode(string $string): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $string));
}
public function getMessage($service, $messageId): GoogleGmail\Message
{
return $service->users_messages->get(config('jiminny.google_text_user'), $messageId);
}
public function trashMessage($service, $messageId)
{
return $service->users_messages->trash(config('jiminny.google_text_user'), $messageId);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
34699
|
NULL
|
NULL
|
NULL
|
|
34710
|
1299
|
4
|
2026-05-13T11:34:45.998057+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672085998_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7581618884890279806
|
-8204352174202572862
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
iTerm2ShellEditViewSessionScripts|ProfilesWindowHelpSupport Daily - in 26 mAAPP (-zsh)APP (-zsh)DOCKER• 81DEV (docker)88283-zshdelete mode 100644 app/Component/ES/Worker/WorkerAmount.phpdelete mode 100644 app/Component/ES/Worker/WorkerInterface.phpcreate mode 100644 app/Component/ProphetAi/Exceptions/InsufficientTranscriptException.phpcreate mode 100644 app/Component/Transcription/DTO/Http/Transcription/AssemblyAI/AssemblyAI/NoAssemblyIdException.phpcreate mode 100644 app/Component/Transcription/DTO/Http/Transcription/TranscriptionIsNotCorrectFormatException.phpcreate mode100644app/Console/Commands/Crm/Backfill0pportunityUserFromAccountCommand.phpdelete mode100644 app/Console/Commands/Elasticsearch/AsyncUpdateEsActivities.phpcreate mode 100644 front-end/src/components/shared/modals/EntityPickerModal/__tests__/useEntitiesCache.spec.tscreate mode 100644 tests/Feature/Component/Nudge/ProcessOrganisationImmediateNudgesJobTest.phpcreate mode 100644 tests/Unit/Component/AiAutomation/Services/CrmFillingEligibilityCheckerTest.phpdelete mode 100644 tests/Unit/Component/ES/ElasticSearchWorkerManagerTest.phpdelete mode 100644 tests/Unit/Component/ES/Worker/ActivityWorkerTest.phpdelete mode 100644 tests/Unit/Component/ES/Worker/EntityWorkerTest.phpdelete mode 100644 tests/Unit/Component/ES/Worker/WorkerAmountTest.phpcreate mode 100644 tests/Unit/Component/ParticipantSpeech/Services/ParticipantSpeechesCreatorTest.phpcreatemode 100644 tests/Unit/Http/Controllers/Kiosk/ActivityControllerTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullremote:Enumerating objects: 29,done.remote: Counting objects: 100% (29/29), done.remote: Compressing objects: 100% (20/20), done.remote: Total 29 (delta 14), reused 11 (delta 9), pack-reused 0 (from 0)Unpacking objects: 100% (29/29), 16.36 KiB | 644.00 KiB/s, done.From github.com:jiminny/appObfd964b74..3893b9772cmaster-> origin/master4f960247ed..4fe0405141JY-20820-es-reindex-stream-model-hydration -> origin/JY-20820-es-reindex-stream-model-hydration1ff6f70f48..62a7fe6277remove-phpstan-errors-> origin/remove-phpstan-errorsUpdating 0bfd964b74..3893b9772cFast-forwardapp/Component/Encoding/Job/AnalyzeTrackChannelsJob.phpapp/Component/FFMpeg/Services/GetSpeechIntervalsService.phpapp/Console/Commands/Activities/SetupIntegration/TwilioSetS3RecordingCredentialsCommand.php201894app/Console/Kernel.phpapp/Jobs/ImportRemoteTrackJob.phpapp/Services/Activity/Twilio/S3RecordingCredentialsService.phptests/Feature/Jobs/ImportRemoteTrackJobTest.phptests/Unit/Component/Encoding/Job/AnalyzeTrackChannelsJobTest.phptests/Unit/Component/FFMpeg/Services/GetSpeechIntervalsTest.phptests/Unit/Services/Activity/Twilio/S3RecordingCredentialsServiceTest.php7882285523618010 files changed, 823 insertions(+), 23 deletions(-)create mode 100644 app/Console/Commands/Activities/SetupIntegration/TwilioSetS3RecordingCredentialsCommand.phpcreate mode 100644 app/Services/Activity/Twilio/S3RecordingCredentialsService.phpcreate mode 100644 tests/Unit/Services/Activity/Twilio/S3RecordingCredentialsServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20891-improve-sms-text-relaysSwitched to a new branch 'JY-20891-improve-sms-text-relays'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20891-improve-sms-text-relays) $ |||84100% (4 8• Wed 13 May 14:34:45181screenpipe"О ₴5APP...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34711
|
1300
|
4
|
2026-05-13T11:34:45.953451+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672085953_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.08843085,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7581618884890279806
|
-8204352174202572862
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
PhostormINavigarecodeLaravelFV faVsco.js?9 JY-20891-improProiect© MailboxController.phpg createlnoox.onpC DeleteEmallmessagesscC) TextRelavService.ongc Processtmalsonerass© SmsRelayFailed.phg0 MeetinaBo10 Middleware> → StreaminaC TeamTelephony0 Userclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegnity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)259260c) ChangeEmailJob.pho261DeactivateUserJob.phpc) DeleteScheduledUserAc1263)© SetupDefaultSavedSearCSvncTolntercom.ohv264265© SyncToPlanhat.php© SyncToUserPilot.php266© BaseProcessingJob.phpc) Dummv.loh.nhn© ImportRecallAlRecordingsJ© ImportRemoteTrackJob.phG Job.phpC.lohDicnatcher nhn© JobDispatcherInterface.ph© PurgeSoftDeletedOpporturT SqsVisibilityControl.phpv C Listenersv @ Activitiesv @ ActivityProvider>C JustCallv D UserPilot© TrackProviderinst>C Audic275?D 8otsv 2 Coachina>_lintercomv PlanhatC) CreateActivitvLod© CreateCoachingFC) Createcoachings© CreateCoachingF2852862872882892911© CreateCommenteC) CreateManaderC.© CreatePlayedEverC) CreateSelfCoache(e CrontoCharodEvo•MlilcorDilot(e) Cronto AvnilabilitvNot(e) CronteCanchingSoorStext = sema1l->gecv1s1dlelexcif (Stext === ') {throw new TextRelayException(: 'Message body is un-readable or empty.',code: self::REASON_CODE MESSAGE BODY_EMPTYsvauidator = Validator::make(data' => Stextir 'data' => new SmsMessageOlDs1f Svalidator->farlsonthrow new TextrelayExceptionMessade body is too larde to send as an SMS.'.code: self.•REASON CODE MESSAGE BODY TOO LARG:Sthis->text = $text;$sender = $this->parseSender($headers['From']):// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient[1] |== config( key: 'jiminny.google_text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidator->fails@) {throw new TextRelavExcention('Recipient origin number is not valid.',code: self.•REASON CODE RECIPTENT ORIGIN INVALIDSvalidator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']):irtcuts conflicts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (12 minutes ago)|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]A console [STAGING]630A30MTAV-639—6331634636— 6471 64864$65€651—652— 653=654— 655~65465)=6601 66669663664T6651 668—669_ 676Tx: Auto vSo jiminnyAND td.domain = LOWERSUBSTRINGLNDEX(c.calendar provider 1d, 'd', -1)0GROUP BY t.id, t.name, calendar domain40 41 840 X.05OrDER BY t.name.select * trom users u 1o1n calendans c 1<»>I.n. on c.user 1d = U.1dwhere u.team id = 882select * from activities where id = 14049485: # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities whene id = 54520207• # +eam 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc:select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where 1d = 585;select * trom activity searches where10 = 8/1147select * trom activity search_ tilters where activity search 1d = 8/7141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuld to b1n 4/842446-2151-4000-854t-cc6568290101' = UU1d:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * from rate limitsted_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * fromomated_reports where id = 54;SELECT * FROM users WHERE id IN (24623,29443,29613):SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text_relays where created_at > '2026-05-01'# and id IN (32415, 32416);and id = 20112.select * from users where team id = 2 and email like '%scott%' and id = 29510suppont Dally • In 20h100% S2• Wed 13 May 14:34:45AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User Em+0 ..Ineed only EmailTextRelay? | changed it a bit. REveiw itRead EmailTextRelay.phpTnoughttor 2s>Your changes to EmailTextRelay.php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows codina standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251 - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User:where("emaj]" Ssender)-sfirct() to SuserRenositorv->fiReview:wulserReSitorv: :findBvEmailo checks both emaii and cecondarv email fieldsThe dependency injection is cleaner - UserRepository is only used where needed•V Folllows the codina standards (multi- ine method sianatures• • No breaking changes to the existing logicThis approach is actually better than mine - vou kept the UserRepository usage localized to checkintearity where theucor lookun sctually hannens rather than ucina it in bandle and naccina the licer aroundiThe fix will resolve Scott's issue if he adds rewardgateway.com as his secondary_emait in Jiminny. The SMS relay will nowtind his account when he sends from that email adaress.lo Il «.View alllapp/Services/#SocialAccountService.pho +3 -1app/Http/Controllers/Auth/ ExtensionController.php +1-3llers/API SsoController.php +4 -2annlGunrdel M Gco nhn 48app/Listeners/Users/ ValidateSendingMessage.php +6 -3es/# SxternalldUniqueToHostValidationRule.ohvAsk anvthina (84L)« Code SWF-1.6Reiect alllWN Windsurf Toams 277•56 UTF.9Accent alliio 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34712
|
1299
|
5
|
2026-05-13T11:34:50.031187+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672090031_m1.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1041761519822496290
|
-8195058156491786941
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
iTerm2ShellEditViewSessionScripts|ProfilesWindowHelplihlSupport Daily - in 26 mAAPP (-zsh)APP (-zsh)DOCKERDEV (docker)88283-zshdelete mode 100644 app/Component/ES/Worker/WorkerAmount.phpdelete mode 100644 app/Component/ES/Worker/WorkerInterface.phpcreate mode 100644 app/Component/ProphetAi/Exceptions/InsufficientTranscriptException.phpcreate mode 100644 app/Component/Transcription/DTO/Http/Transcription/AssemblyAI/AssemblyAI/NoAssemblyIdException.phpcreate mode 100644 app/Component/Transcription/DTO/Http/Transcription/TranscriptionIsNotCorrectFormatException.phpcreate mode100644app/Console/Commands/Crm/Backfill0pportunityUserFromAccountCommand.phpdelete mode100644 app/Console/Commands/Elasticsearch/AsyncUpdateEsActivities.phpcreate mode 100644 front-end/src/components/shared/modals/EntityPickerModal/__tests__/useEntitiesCache.spec.tscreate mode 100644 tests/Feature/Component/Nudge/ProcessOrganisationImmediateNudgesJobTest.phpcreate mode 100644 tests/Unit/Component/AiAutomation/Services/CrmFillingEligibilityCheckerTest.phpdelete mode 100644 tests/Unit/Component/ES/ElasticSearchWorkerManagerTest.phpdelete mode 100644 tests/Unit/Component/ES/Worker/ActivityWorkerTest.phpdelete mode 100644 tests/Unit/Component/ES/Worker/EntityWorkerTest.phpdelete mode 100644 tests/Unit/Component/ES/Worker/WorkerAmountTest.phpcreate mode 100644 tests/Unit/Component/ParticipantSpeech/Services/ParticipantSpeechesCreatorTest.phpcreatemode 100644 tests/Unit/Http/Controllers/Kiosk/ActivityControllerTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullremote:Enumerating objects: 29,done.remote: Counting objects: 100% (29/29), done.remote: Compressing objects: 100% (20/20), done.remote: Total 29 (delta 14), reused 11 (delta 9), pack-reused 0 (from 0)Unpacking objects: 100% (29/29), 16.36 KiB | 644.00 KiB/s, done.From github.com:jiminny/appObfd964b74..3893b9772cmaster-> origin/master4f960247ed..4fe0405141JY-20820-es-reindex-stream-model-hydration -> origin/JY-20820-es-reindex-stream-model-hydration1ff6f70f48..62a7fe6277remove-phpstan-errors-> origin/remove-phpstan-errorsUpdating 0bfd964b74..3893b9772cFast-forwardapp/Component/Encoding/Job/AnalyzeTrackChannelsJob.phpapp/Component/FFMpeg/Services/GetSpeechIntervalsService.phpapp/Console/Commands/Activities/SetupIntegration/TwilioSetS3RecordingCredentialsCommand.php201894app/Console/Kernel.phpapp/Jobs/ImportRemoteTrackJob.phpapp/Services/Activity/Twilio/S3RecordingCredentialsService.phptests/Feature/Jobs/ImportRemoteTrackJobTest.phptests/Unit/Component/Encoding/Job/AnalyzeTrackChannelsJobTest.phptests/Unit/Component/FFMpeg/Services/GetSpeechIntervalsTest.phptests/Unit/Services/Activity/Twilio/S3RecordingCredentialsServiceTest.php7882285523618010 files changed, 823 insertions(+), 23 deletions(-)create mode 100644 app/Console/Commands/Activities/SetupIntegration/TwilioSetS3RecordingCredentialsCommand.phpcreate mode 100644 app/Services/Activity/Twilio/S3RecordingCredentialsService.phpcreate mode 100644 tests/Unit/Services/Activity/Twilio/S3RecordingCredentialsServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20891-improve-sms-text-relaysSwitched to a new branch 'JY-20891-improve-sms-text-relays'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20891-improve-sms-text-relays) $ |||84100% C4 8• Wed 13 May 14:34:49181screenpipe"О ₴5APP...
|
34710
|
NULL
|
NULL
|
NULL
|
|
34713
|
1299
|
6
|
2026-05-13T11:34:52.705495+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672092705_m1.jpg...
|
PhpStorm
|
faVsco.js – SocialAccountService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
namespace Jiminny\Services;
/**
* @todo cleanup after #slack-oauth-v2
*/
use AdamPaterson\OAuth2\Client\Provider\SlackResourceOwner;
use Chadhutchins\OAuth2\Client\Provider\Slack;
use ChaseConey\LaravelDatadogHelper\Datadog;
use Daniti\OAuth2\Client\Provider\Pipedrive;
use Daniti\OAuth2\Client\Provider\PipedriveResourceOwner;
use Exception;
use Flipbox\OAuth2\Client\Provider\HubSpot;
use Flipbox\OAuth2\Client\Provider\HubSpotResourceOwner;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Jiminny\Component\Encryption\EncryptedTokenManager;
use Jiminny\Events\Users\CrmAccountReconnected;
use Jiminny\Events\Users\SocialAccountConnected;
use Jiminny\Events\Users\SocialAccountDisconnected;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\InvalidEnumException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Notifications\SlackBotAdded;
use Jiminny\OAuth2\Client\Provider\Aircall;
use Jiminny\OAuth2\Client\Provider\AircallResourceOwner;
use Jiminny\OAuth2\Client\Provider\Bullhorn;
use Jiminny\OAuth2\Client\Provider\Dialpad;
use Jiminny\OAuth2\Client\Provider\DialpadResourceOwner;
use Jiminny\OAuth2\Client\Provider\Salesloft;
use Jiminny\OAuth2\Client\Provider\SalesloftResourceOwner;
use Jiminny\Services\Activity\Talkdesk\Provider\Talkdesk;
use Jiminny\Services\Activity\Talkdesk\Provider\TalkdeskResourceOwner;
use Jiminny\Services\Activity\Zoom\Provider\Zoom;
use Jiminny\Services\Activity\Zoom\Provider\ZoomResourceOwner;
use Jiminny\Services\OAuth2\Provider\BasicAuth;
use Jiminny\Services\OAuth2\Provider\Outreach;
use JsonException;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\GoogleUser;
use League\OAuth2\Client\Provider\LinkedIn;
use League\OAuth2\Client\Provider\LinkedInResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Psr\Log\LoggerInterface;
use Random\RandomException;
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
use Stevenmaguire\OAuth2\Client\Provider\SalesforceResourceOwner;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Provider\AzureResourceOwner;
use Throwable;
use TMannherz\OAuth2\Client\Provider\RingCentral;
use TMannherz\OAuth2\Client\Provider\RingcentralResourceOwner;
class SocialAccountService
{
/**
* Get a fresh tokens 5 minutes before it expires
* That should minimise the number of failed requests due to expired token
* for long-running jobs that reuse the same token for pulling lots of data.
*/
private const int REFRESH_OFFSET_MIN = 5;
private const string TOKEN_STATE_FETCH = 'fetch';
private const string TOKEN_STATE_REFRESH = 'refresh';
private const string TOKEN_RESULT_ATTEMPT = 'attempt';
private const string TOKEN_RESULT_SUCCESS = 'success';
private const string TOKEN_RESULT_FAILURE = 'failure';
private ?AccessTokenInterface $accessToken = null;
private ?string $token = null;
private ?string $refreshToken = null;
private ?int $expires = null;
private ?string $countryCode = null;
private ?string $timezone = null;
private ?array $vendorValues = null;
private ?int $refreshTokenExpires = null;
public function __construct(
private readonly EncryptedTokenManager $encryptedTokenManager,
private readonly LoggerInterface $logger,
private readonly PhoneNumberUtil $phoneNumberUtil,
private readonly Dispatcher $eventDispatcher,
) {
}
public function setVendorValues(array $values): void
{
$this->vendorValues = $values;
}
public function setAccessToken(AccessTokenInterface $accessToken): void
{
$this->accessToken = $accessToken;
// Todo: Also set these other params from this token e.g. refreshToken
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function setRefreshToken(?string $refreshToken): void
{
$this->refreshToken = $refreshToken;
}
public function setCountryCode(string $countryCode): void
{
$this->countryCode = $countryCode;
}
public function setTimezone(string $timezone): void
{
$this->timezone = $timezone;
}
public function setExpires(?int $expiry): void
{
$this->expires = $expiry;
}
public function setRefreshTokenExpires(array $values): void
{
$this->refreshTokenExpires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
/**
* @throws InvalidEnumException
*/
public function getProvider(string $provider): AbstractProvider
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
return new LinkedIn(config('services.linkedin'));
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
$socialProvider = new LinkedIn(config('services.linkedin-conference'));
$socialProvider->withFields([
'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',
]);
return $socialProvider;
case SocialAccount::PROVIDER_SALESFORCE:
return new Salesforce(config('services.salesforce'));
case SocialAccount::PROVIDER_GOOGLE:
return new Google(config('services.google'));
case SocialAccount::PROVIDER_SLACK:
return new Slack(config('services.slack'));
case SocialAccount::PROVIDER_OFFICE:
$config = config('services.office');
// Convert string scope to array format expected by Azure provider
if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {
$config['scopes'] = array_filter(preg_split('/\s+/', trim($config['scope'])));
unset($config['scope']);
}
$socialProvider = new Azure($config);
$socialProvider->urlAPI = '[URL_WITH_CREDENTIALS] Exception
*/
public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
/** @var LinkedInResourceOwner $providerUser */
return $this->mapLinkedInUserData($providerUser);
case SocialAccount::PROVIDER_SALESFORCE:
/** @var SalesforceResourceOwner $providerUser */
return $this->mapSalesforceUserData($providerUser);
case SocialAccount::PROVIDER_HUBSPOT:
/** @var HubSpotResourceOwner $providerUser */
return $this->mapHubSpotUserData($providerUser);
case SocialAccount::PROVIDER_PIPEDRIVE:
/** @var PipedriveResourceOwner $providerUser */
return $this->mapPipedriveUserData($providerUser);
case SocialAccount::PROVIDER_GOOGLE:
/** @var GoogleUser $providerUser */
return $this->mapGoogleUserData($providerUser);
case SocialAccount::PROVIDER_SLACK:
/** @var SlackResourceOwner $providerUser */
return $this->mapSlackUserData($providerUser);
case SocialAccount::PROVIDER_OFFICE:
/** @var AzureResourceOwner $providerUser */
return $this->mapOfficeUserData($providerUser);
case SocialAccount::PROVIDER_OUTREACH:
return $this->mapOutreachUserData($providerUser);
case SocialAccount::PROVIDER_DIALPAD:
/** @var DialpadResourceOwner $providerUser*/
return $this->mapDialpadUserData($providerUser);
case SocialAccount::PROVIDER_AIRCALL:
/** @var AircallResourceOwner $providerUser */
return $this->mapAircallUserData($providerUser);
case SocialAccount::PROVIDER_ZOOM_PHONE:
/** @var ZoomResourceOwner $providerUser */
return $this->mapZoomPhoneUserData($providerUser);
case SocialAccount::PROVIDER_SALESLOFT:
/** @var SalesloftResourceOwner $providerUser */
return $this->mapSalesloftUserData($providerUser);
case SocialAccount::PROVIDER_BULLHORN:
return $this->mapBullhornUserData();
case SocialAccount::PROVIDER_TALKDESK:
/** @var TalkdeskResourceOwner $providerUser */
return $this->mapTalkdeskUserData($providerUser);
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_TELUS:
/** @var RingcentralResourceOwner $providerUser */
return $this->mapRingCentralUserData($providerUser);
default:
throw new InvalidEnumException('Unknown provider.');
}
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
*
* @throws RandomException
*/
public function getRandomState(int $length = 32): string
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return bin2hex(random_bytes($length / 2));
}
private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount
{
return SocialAccount::where([
'provider' => $provider,
'provider_user_id' => $providerUser->getId(),
])->first();
}
/**
* Based on the provider data, try to match to a sociable entity based on email.
* If a match is made, create the social account under that entity.
*
* @throws AuthenticationException
*/
public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User
{
$account = $this->getAssociation($provider, $providerUser);
if ($account !== null && $account->hasUser()) {
return $account->getUser();
}
$userData = $this->mapUserData($provider, $providerUser);
// Check if we have an actual user with this email.
/** @var User|null $user */
$user = User::where('email', $userData['email'])->first();
// If the user is trying to connect to LinkedIn, don't allow this.
// Todo: have an interstitial page to perform 2FA to connect.
if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {
throw new AuthenticationException(
'Sorry, you\'ll need to login through your Jiminny account to access the Conference.',
);
}
return $user;
}
/**
* @throws JsonException
*/
public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount
{
/** @var SocialAccount $account */
$account = $user->socialAccounts()->firstOrNew([
'provider' => $provider,
]);
$account->fill([
'provider_user_id' => $providerUser->getId(),
'provider_user_token' => $this->token,
'expires' => $this->expires,
'state' => SocialAccount::STATE_CONNECTED,
'retry_after' => null,
]);
// This is an optional parameter, don't overwrite the existing one with null if we don't get it.
if ($this->refreshToken) {
$account->fill([
'provider_refresh_token' => $this->refreshToken,
'refresh_token_expires' => $this->refreshTokenExpires,
]);
}
if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {
$account->fill([
'auth_scope' => is_scalar($this->vendorValues['scope'])
? $this->vendorValues['scope']
: json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),
]);
} else {
$account->fill([
'auth_scope' => null,
]);
$this->logger->warning(
'[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',
// pulling directly from the token, just to avoid potential masking of the issue
['token_values' => $this->accessToken->getValues()],
);
}
$account->save();
// Association can be from an updated token so don't re-announce this.
if (
$account->wasRecentlyCreated
&& in_array($provider, SocialAccount::CRM_PROVIDERS, true)
&& $provider !== SocialAccount::PROVIDER_HUBSPOT
&& $providerUser->getId() !== null
) {
$crm = $user->team->crm;
$data = [
'crm_configuration_id' => $crm->id,
'log_notes' => Profile::LOG_NOTE_ENHANCED,
];
$crmProfile = $user->crmProfile()->where([
'crm_provider_id' => $providerUser->getId(),
])->first();
$user->crmProfile()->updateOrCreate([
'crm_provider_id' => $providerUser->getId(),
], $data);
// If updated, fire reconnected
if ($crmProfile !== null) {
$this->eventDispatcher->dispatch(new CrmAccountReconnected($account));
}
}
$this->eventDispatcher->dispatch(new SocialAccountConnected($account));
return $account;
}
public function integrate(string $provider, User $user, Team $team): void
{
if ($provider === SocialAccount::PROVIDER_SLACK) {
if (! isset($this->vendorValues['ok'])
|| $this->vendorValues['ok'] !== true
|| ! isset($this->vendorValues['token_type'])
|| $this->vendorValues['token_type'] !== 'bot'
) {
// code expects V2 token, which differs slightly from V1
throw new LogicException('Invalid token received from Slack OAuth v2 API');
}
$webhook = $this->vendorValues['incoming_webhook'];
$slackTeamId = $this->vendorValues['team']['id'];
$botData = [
'channel' => $webhook['channel'],
'channel_id' => $webhook['channel_id'],
'config_url' => $webhook['configuration_url'],
'webhook_url' => $webhook['url'],
'bot_user_id' => $this->vendorValues['bot_user_id'],
'bot_access_token' => $this->accessToken->getToken(),
];
$slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);
if ($slackBot->wasRecentlyCreated) {
// Send Slack notification.
$user->notify(new SlackBotAdded());
}
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);
$this->logger->info('[SocialAccountService] Fetching token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$account->refresh();
if (
! $forceRefresh
&& ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))
) {
$this->logger->info('[SocialAccountService] Token retrieved', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);
return $this->encryptedTokenManager->getAccessToken($account);
}
try {
$this->logger->info('[SocialAccountService] Token needs refreshing', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
return $this->refreshToken($account, $forceRefresh);
} catch (IdentityProviderException $exception) {
$responseBody = $exception->getResponseBody();
if ($responseBody instanceof Response) {
$responseBody = $responseBody->getBody();
}
if (is_object($responseBody) && method_exists($responseBody, '__toString')) {
$responseBody = $responseBody->__toString();
}
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'responseBody' => $responseBody,
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
} catch (SocialAccountTokenInvalidException $exception) {
$this->logger->error('[SocialAccountService] Cannot obtain token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception::class,
'errorMessage' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {
$this->logger->error('[SocialAccountService] Full refresh required', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
// Something terrible happened their token, they need to reconnect.
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
$this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));
}
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
}
}
public function refreshSocialAccountToken(SocialAccount $socialAccount): void
{
try {
$this->getToken($socialAccount);
} catch (Throwable $e) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $socialAccount->getId(),
'provider' => $socialAccount->getProviderName(),
'reason' => $e->getMessage(),
]);
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);
$newToken = null;
Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)
->block(8, function () use ($account, $forceRefresh, &$newToken): void {
try {
$account->refresh();
$token = $this->encryptedTokenManager->getAccessToken($account);
if (! $forceRefresh && $this->hasValidToken($account)) {
$newToken = $token;
return;
}
if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {
$this->logger->error('[SocialAccountService] Refresh token not found', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog(
$account,
self::TOKEN_STATE_REFRESH,
self::TOKEN_RESULT_FAILURE,
);
throw new SocialAccountTokenInvalidException(
'Refresh token is not set, re-connection required.',
);
}
$this->logger->info('[SocialAccountService] Refreshing token from provider', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),
'state' => $account->getState(),
]);
$newToken = $this->getProvider($account->provider)
->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
])
;
if ($newToken->getToken() === $token->getToken()) {
$this->logger->info('[SocialAccountService] Refreshed with an identical token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
}
} catch (ConnectException | RequestException $exception) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
// This usually occurs due to SSL errors.
throw new SocialAccountTokenInvalidException(
'Token could not be refreshed.',
$exception->getCode(),
$exception,
);
}
$account->provider_user_token = $newToken->getToken();
$account->expires = $newToken->getExpires();
$account->state = SocialAccount::STATE_CONNECTED;
if ($newToken->getRefreshToken()) {
$account->provider_refresh_token = $newToken->getRefreshToken();
$values = $newToken->getValues();
$account->refresh_token_expires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
$account->save();
});
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);
$this->logger->info('[SocialAccountService] Token refreshed', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'state' => $account->getState(),
]);
return $newToken;
}
/**
* @return string[]
*/
private function getAccessScope(string $provider): array
{
$scopes = [];
$providerScopes = config('services.' . $provider . '.scope');
if ($providerScopes) {
$scopes = preg_split('/\s+/', $providerScopes);
}
return $scopes;
}
/**
* @throws InvalidEnumException
*/
public function getAuthorizationOptions(string $provider): array
{
$scopes = ['scope' => $this->getAccessScope($provider)];
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
case SocialAccount::PROVIDER_SALESFORCE:
case SocialAccount::PROVIDER_HUBSPOT:
case SocialAccount::PROVIDER_OUTREACH:
case SocialAccount::PROVIDER_SALESLOFT:
case SocialAccount::PROVIDER_ZOOM_PHONE:
case SocialAccount::PROVIDER_PIPEDRIVE:
case SocialAccount::PROVIDER_SLACK:
case SocialAccount::PROVIDER_AIRCALL:
case SocialAccount::PROVIDER_BULLHORN:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_TELUS:
case SocialAccount::PROVIDER_DIALPAD:
case SocialAccount::PROVIDER_TALKDESK:
return $scopes;
case SocialAccount::PROVIDER_OFFICE:
return $scopes + [
'access_type' => 'offline',
];
case SocialAccount::PROVIDER_GOOGLE:
return $scopes + [
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'approval_prompt' => null,
];
default:
throw new InvalidEnumException();
}
}
private function tokenDoesNotExpire(SocialAccount $account): bool
{
return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);
}
private function hasValidToken(SocialAccount $account): bool
{
return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();
}
private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void
{
Datadog::increment('jiminny.access_token', 1, [
'provider' => $account->getProviderName(),
'state' => $state,
'result' => $result,
]);
}
private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),
];
}
private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
try {
$parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);
$number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);
} catch (NumberParseException) {
$number = null;
}
// Todo: this should check the `organization_id` matches the parent crm configuration.
return [
'country_code' => $this->countryCode,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),
'phone' => $number,
'crm_provider_id' => $rawUserData['organization_id'],
'crm_base_url' => $this->vendorValues['instance_url'],
];
}
/**
* Todo: this should check the `getHubId` matches the parent crm configuration.
*/
private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $providerUser->getHubId(),
'crm_base_url' => $providerUser->toArray()['hub_domain'],
];
}
/**
* Todo: this should check the `getCompanyId` matches the parent crm configuration.
*/
private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $rawUserData['data']['company_id'],
'crm_base_url' => '[URL_WITH_CREDENTIALS] ActivityProviderException
*/
private function mapDialpadUserData(DialpadResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
// They need to be Super Admin to access the Company APIs.
$this->logger->info('[Dialpad] User authenticated', $rawUserData);
if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Dialpad Super Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapAircallUserData(AircallResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
/**
* @throws ActivityProviderException
*/
private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array
{
if ($providerUser->toArray()['data']['team_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Team Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapBullhornUserData(): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
];
}
private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Services;\n\n/**\n * @todo cleanup after #slack-oauth-v2\n */\n\nuse AdamPaterson\\OAuth2\\Client\\Provider\\SlackResourceOwner;\nuse Chadhutchins\\OAuth2\\Client\\Provider\\Slack;\nuse ChaseConey\\LaravelDatadogHelper\\Datadog;\nuse Daniti\\OAuth2\\Client\\Provider\\Pipedrive;\nuse Daniti\\OAuth2\\Client\\Provider\\PipedriveResourceOwner;\nuse Exception;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpot;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpotResourceOwner;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Auth\\AuthenticationException;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Jiminny\\Component\\Encryption\\EncryptedTokenManager;\nuse Jiminny\\Events\\Users\\CrmAccountReconnected;\nuse Jiminny\\Events\\Users\\SocialAccountConnected;\nuse Jiminny\\Events\\Users\\SocialAccountDisconnected;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\InvalidEnumException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Notifications\\SlackBotAdded;\nuse Jiminny\\OAuth2\\Client\\Provider\\Aircall;\nuse Jiminny\\OAuth2\\Client\\Provider\\AircallResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Bullhorn;\nuse Jiminny\\OAuth2\\Client\\Provider\\Dialpad;\nuse Jiminny\\OAuth2\\Client\\Provider\\DialpadResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Salesloft;\nuse Jiminny\\OAuth2\\Client\\Provider\\SalesloftResourceOwner;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\Talkdesk;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\TalkdeskResourceOwner;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\Zoom;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\ZoomResourceOwner;\nuse Jiminny\\Services\\OAuth2\\Provider\\BasicAuth;\nuse Jiminny\\Services\\OAuth2\\Provider\\Outreach;\nuse JsonException;\nuse League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider;\nuse League\\OAuth2\\Client\\Provider\\AbstractProvider;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Provider\\Google;\nuse League\\OAuth2\\Client\\Provider\\GoogleUser;\nuse League\\OAuth2\\Client\\Provider\\LinkedIn;\nuse League\\OAuth2\\Client\\Provider\\LinkedInResourceOwner;\nuse League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse League\\OAuth2\\Client\\Token\\AccessTokenInterface;\nuse libphonenumber\\NumberParseException;\nuse libphonenumber\\PhoneNumberFormat;\nuse libphonenumber\\PhoneNumberUtil;\nuse LogicException;\nuse Psr\\Log\\LoggerInterface;\nuse Random\\RandomException;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\Salesforce;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\SalesforceResourceOwner;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\nuse TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner;\nuse Throwable;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingCentral;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingcentralResourceOwner;\n\nclass SocialAccountService\n{\n /**\n * Get a fresh tokens 5 minutes before it expires\n * That should minimise the number of failed requests due to expired token\n * for long-running jobs that reuse the same token for pulling lots of data.\n */\n private const int REFRESH_OFFSET_MIN = 5;\n\n private const string TOKEN_STATE_FETCH = 'fetch';\n private const string TOKEN_STATE_REFRESH = 'refresh';\n private const string TOKEN_RESULT_ATTEMPT = 'attempt';\n private const string TOKEN_RESULT_SUCCESS = 'success';\n private const string TOKEN_RESULT_FAILURE = 'failure';\n\n private ?AccessTokenInterface $accessToken = null;\n private ?string $token = null;\n private ?string $refreshToken = null;\n private ?int $expires = null;\n private ?string $countryCode = null;\n private ?string $timezone = null;\n private ?array $vendorValues = null;\n\n private ?int $refreshTokenExpires = null;\n\n public function __construct(\n private readonly EncryptedTokenManager $encryptedTokenManager,\n private readonly LoggerInterface $logger,\n private readonly PhoneNumberUtil $phoneNumberUtil,\n private readonly Dispatcher $eventDispatcher,\n ) {\n }\n\n public function setVendorValues(array $values): void\n {\n $this->vendorValues = $values;\n }\n\n public function setAccessToken(AccessTokenInterface $accessToken): void\n {\n $this->accessToken = $accessToken;\n // Todo: Also set these other params from this token e.g. refreshToken\n }\n\n public function setToken(?string $token): void\n {\n $this->token = $token;\n }\n\n public function setRefreshToken(?string $refreshToken): void\n {\n $this->refreshToken = $refreshToken;\n }\n\n public function setCountryCode(string $countryCode): void\n {\n $this->countryCode = $countryCode;\n }\n\n public function setTimezone(string $timezone): void\n {\n $this->timezone = $timezone;\n }\n\n public function setExpires(?int $expiry): void\n {\n $this->expires = $expiry;\n }\n\n public function setRefreshTokenExpires(array $values): void\n {\n $this->refreshTokenExpires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getProvider(string $provider): AbstractProvider\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n return new LinkedIn(config('services.linkedin'));\n\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n $socialProvider = new LinkedIn(config('services.linkedin-conference'));\n $socialProvider->withFields([\n 'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',\n ]);\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_SALESFORCE:\n return new Salesforce(config('services.salesforce'));\n\n case SocialAccount::PROVIDER_GOOGLE:\n return new Google(config('services.google'));\n\n case SocialAccount::PROVIDER_SLACK:\n return new Slack(config('services.slack'));\n\n case SocialAccount::PROVIDER_OFFICE:\n $config = config('services.office');\n\n // Convert string scope to array format expected by Azure provider\n if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {\n $config['scopes'] = array_filter(preg_split('/\\s+/', trim($config['scope'])));\n unset($config['scope']);\n }\n\n $socialProvider = new Azure($config);\n $socialProvider->urlAPI = 'https://graph.microsoft.com/v1.0/';\n $socialProvider->API_VERSION = '1.0';\n $socialProvider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_HUBSPOT:\n return new HubSpot(config('services.hubspot'));\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n return new Pipedrive(config('services.pipedrive'));\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n return new Zoom(config('services.zoom-phone'));\n\n case SocialAccount::PROVIDER_OUTREACH:\n return new Outreach(config('services.outreach'));\n\n case SocialAccount::PROVIDER_SALESLOFT:\n return new Salesloft(config('services.salesloft'));\n\n case SocialAccount::PROVIDER_AIRCALL:\n return new Aircall(config('services.aircall'));\n\n case SocialAccount::PROVIDER_DIALPAD:\n return new Dialpad(config('services.dialpad'));\n\n case SocialAccount::PROVIDER_GONG:\n return new BasicAuth(config('services.gong'));\n\n case SocialAccount::PROVIDER_CLOSE:\n return new BasicAuth(config('services.close'));\n\n case SocialAccount::PROVIDER_AVAYA:\n // Avaya is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.avaya'));\n\n case SocialAccount::PROVIDER_TELUS:\n // Telus is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.telus'));\n\n case SocialAccount::PROVIDER_RINGCENTRAL:\n return new RingCentral(config('services.ringcentral'));\n\n case SocialAccount::PROVIDER_BULLHORN:\n return new Bullhorn(config('services.bullhorn'));\n\n case SocialAccount::PROVIDER_TALKDESK:\n return new Talkdesk(config('services.talkdesk'), [\n // Automatically concatenate Basic token to AuthToken requests\n 'optionProvider' => new HttpBasicAuthOptionProvider(),\n ]);\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n /**\n *\n *\n * @throws Exception\n */\n public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n /** @var LinkedInResourceOwner $providerUser */\n return $this->mapLinkedInUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESFORCE:\n /** @var SalesforceResourceOwner $providerUser */\n return $this->mapSalesforceUserData($providerUser);\n\n case SocialAccount::PROVIDER_HUBSPOT:\n /** @var HubSpotResourceOwner $providerUser */\n return $this->mapHubSpotUserData($providerUser);\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n /** @var PipedriveResourceOwner $providerUser */\n return $this->mapPipedriveUserData($providerUser);\n\n case SocialAccount::PROVIDER_GOOGLE:\n /** @var GoogleUser $providerUser */\n return $this->mapGoogleUserData($providerUser);\n\n case SocialAccount::PROVIDER_SLACK:\n /** @var SlackResourceOwner $providerUser */\n return $this->mapSlackUserData($providerUser);\n\n case SocialAccount::PROVIDER_OFFICE:\n /** @var AzureResourceOwner $providerUser */\n return $this->mapOfficeUserData($providerUser);\n\n case SocialAccount::PROVIDER_OUTREACH:\n return $this->mapOutreachUserData($providerUser);\n\n case SocialAccount::PROVIDER_DIALPAD:\n /** @var DialpadResourceOwner $providerUser*/\n return $this->mapDialpadUserData($providerUser);\n\n case SocialAccount::PROVIDER_AIRCALL:\n /** @var AircallResourceOwner $providerUser */\n return $this->mapAircallUserData($providerUser);\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n /** @var ZoomResourceOwner $providerUser */\n return $this->mapZoomPhoneUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESLOFT:\n /** @var SalesloftResourceOwner $providerUser */\n return $this->mapSalesloftUserData($providerUser);\n\n case SocialAccount::PROVIDER_BULLHORN:\n return $this->mapBullhornUserData();\n\n case SocialAccount::PROVIDER_TALKDESK:\n /** @var TalkdeskResourceOwner $providerUser */\n return $this->mapTalkdeskUserData($providerUser);\n\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_TELUS:\n /** @var RingcentralResourceOwner $providerUser */\n return $this->mapRingCentralUserData($providerUser);\n default:\n throw new InvalidEnumException('Unknown provider.');\n }\n }\n\n /**\n * Returns a new random string to use as the state parameter in an\n * authorization flow.\n *\n * @param int $length Length of the random string to be generated.\n *\n * @throws RandomException\n */\n public function getRandomState(int $length = 32): string\n {\n // Converting bytes to hex will always double length. Hence, we can reduce\n // the amount of bytes by half to produce the correct length.\n return bin2hex(random_bytes($length / 2));\n }\n\n private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount\n {\n return SocialAccount::where([\n 'provider' => $provider,\n 'provider_user_id' => $providerUser->getId(),\n ])->first();\n }\n\n /**\n * Based on the provider data, try to match to a sociable entity based on email.\n * If a match is made, create the social account under that entity.\n *\n * @throws AuthenticationException\n */\n public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User\n {\n $account = $this->getAssociation($provider, $providerUser);\n if ($account !== null && $account->hasUser()) {\n return $account->getUser();\n }\n $userData = $this->mapUserData($provider, $providerUser);\n\n // Check if we have an actual user with this email.\n /** @var User|null $user */\n $user = User::where('email', $userData['email'])->first();\n\n // If the user is trying to connect to LinkedIn, don't allow this.\n // Todo: have an interstitial page to perform 2FA to connect.\n if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {\n throw new AuthenticationException(\n 'Sorry, you\\'ll need to login through your Jiminny account to access the Conference.',\n );\n }\n\n return $user;\n }\n\n /**\n * @throws JsonException\n */\n public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount\n {\n /** @var SocialAccount $account */\n $account = $user->socialAccounts()->firstOrNew([\n 'provider' => $provider,\n ]);\n\n $account->fill([\n 'provider_user_id' => $providerUser->getId(),\n 'provider_user_token' => $this->token,\n 'expires' => $this->expires,\n 'state' => SocialAccount::STATE_CONNECTED,\n 'retry_after' => null,\n ]);\n\n // This is an optional parameter, don't overwrite the existing one with null if we don't get it.\n if ($this->refreshToken) {\n $account->fill([\n 'provider_refresh_token' => $this->refreshToken,\n 'refresh_token_expires' => $this->refreshTokenExpires,\n ]);\n }\n\n if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {\n $account->fill([\n 'auth_scope' => is_scalar($this->vendorValues['scope'])\n ? $this->vendorValues['scope']\n : json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),\n ]);\n } else {\n $account->fill([\n 'auth_scope' => null,\n ]);\n\n $this->logger->warning(\n '[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',\n // pulling directly from the token, just to avoid potential masking of the issue\n ['token_values' => $this->accessToken->getValues()],\n );\n }\n\n $account->save();\n\n // Association can be from an updated token so don't re-announce this.\n if (\n $account->wasRecentlyCreated\n && in_array($provider, SocialAccount::CRM_PROVIDERS, true)\n && $provider !== SocialAccount::PROVIDER_HUBSPOT\n && $providerUser->getId() !== null\n ) {\n $crm = $user->team->crm;\n $data = [\n 'crm_configuration_id' => $crm->id,\n 'log_notes' => Profile::LOG_NOTE_ENHANCED,\n ];\n\n $crmProfile = $user->crmProfile()->where([\n 'crm_provider_id' => $providerUser->getId(),\n ])->first();\n\n $user->crmProfile()->updateOrCreate([\n 'crm_provider_id' => $providerUser->getId(),\n ], $data);\n\n // If updated, fire reconnected\n if ($crmProfile !== null) {\n $this->eventDispatcher->dispatch(new CrmAccountReconnected($account));\n }\n }\n\n $this->eventDispatcher->dispatch(new SocialAccountConnected($account));\n\n return $account;\n }\n\n public function integrate(string $provider, User $user, Team $team): void\n {\n if ($provider === SocialAccount::PROVIDER_SLACK) {\n if (! isset($this->vendorValues['ok'])\n || $this->vendorValues['ok'] !== true\n || ! isset($this->vendorValues['token_type'])\n || $this->vendorValues['token_type'] !== 'bot'\n ) {\n // code expects V2 token, which differs slightly from V1\n throw new LogicException('Invalid token received from Slack OAuth v2 API');\n }\n\n $webhook = $this->vendorValues['incoming_webhook'];\n\n $slackTeamId = $this->vendorValues['team']['id'];\n\n $botData = [\n 'channel' => $webhook['channel'],\n 'channel_id' => $webhook['channel_id'],\n 'config_url' => $webhook['configuration_url'],\n 'webhook_url' => $webhook['url'],\n 'bot_user_id' => $this->vendorValues['bot_user_id'],\n 'bot_access_token' => $this->accessToken->getToken(),\n ];\n\n $slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);\n\n if ($slackBot->wasRecentlyCreated) {\n // Send Slack notification.\n $user->notify(new SlackBotAdded());\n }\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);\n\n $this->logger->info('[SocialAccountService] Fetching token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $account->refresh();\n\n if (\n ! $forceRefresh\n && ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))\n ) {\n $this->logger->info('[SocialAccountService] Token retrieved', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);\n\n return $this->encryptedTokenManager->getAccessToken($account);\n }\n\n try {\n $this->logger->info('[SocialAccountService] Token needs refreshing', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n return $this->refreshToken($account, $forceRefresh);\n } catch (IdentityProviderException $exception) {\n $responseBody = $exception->getResponseBody();\n\n if ($responseBody instanceof Response) {\n $responseBody = $responseBody->getBody();\n }\n\n if (is_object($responseBody) && method_exists($responseBody, '__toString')) {\n $responseBody = $responseBody->__toString();\n }\n\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'responseBody' => $responseBody,\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n } catch (SocialAccountTokenInvalidException $exception) {\n $this->logger->error('[SocialAccountService] Cannot obtain token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception::class,\n 'errorMessage' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {\n $this->logger->error('[SocialAccountService] Full refresh required', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n // Something terrible happened their token, they need to reconnect.\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n $this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));\n }\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n }\n }\n\n public function refreshSocialAccountToken(SocialAccount $socialAccount): void\n {\n try {\n $this->getToken($socialAccount);\n } catch (Throwable $e) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $socialAccount->getId(),\n 'provider' => $socialAccount->getProviderName(),\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);\n\n $newToken = null;\n\n Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)\n ->block(8, function () use ($account, $forceRefresh, &$newToken): void {\n try {\n $account->refresh();\n $token = $this->encryptedTokenManager->getAccessToken($account);\n\n if (! $forceRefresh && $this->hasValidToken($account)) {\n $newToken = $token;\n\n return;\n }\n\n if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {\n $this->logger->error('[SocialAccountService] Refresh token not found', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog(\n $account,\n self::TOKEN_STATE_REFRESH,\n self::TOKEN_RESULT_FAILURE,\n );\n\n throw new SocialAccountTokenInvalidException(\n 'Refresh token is not set, re-connection required.',\n );\n }\n\n $this->logger->info('[SocialAccountService] Refreshing token from provider', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),\n 'state' => $account->getState(),\n ]);\n\n $newToken = $this->getProvider($account->provider)\n ->getAccessToken('refresh_token', [\n 'refresh_token' => $token->getRefreshToken(),\n ])\n ;\n\n if ($newToken->getToken() === $token->getToken()) {\n $this->logger->info('[SocialAccountService] Refreshed with an identical token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n }\n } catch (ConnectException | RequestException $exception) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n // This usually occurs due to SSL errors.\n throw new SocialAccountTokenInvalidException(\n 'Token could not be refreshed.',\n $exception->getCode(),\n $exception,\n );\n }\n\n $account->provider_user_token = $newToken->getToken();\n $account->expires = $newToken->getExpires();\n $account->state = SocialAccount::STATE_CONNECTED;\n\n if ($newToken->getRefreshToken()) {\n $account->provider_refresh_token = $newToken->getRefreshToken();\n $values = $newToken->getValues();\n $account->refresh_token_expires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n $account->save();\n });\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);\n\n $this->logger->info('[SocialAccountService] Token refreshed', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'state' => $account->getState(),\n ]);\n\n return $newToken;\n }\n\n /**\n * @return string[]\n */\n private function getAccessScope(string $provider): array\n {\n $scopes = [];\n $providerScopes = config('services.' . $provider . '.scope');\n\n if ($providerScopes) {\n $scopes = preg_split('/\\s+/', $providerScopes);\n }\n\n return $scopes;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getAuthorizationOptions(string $provider): array\n {\n $scopes = ['scope' => $this->getAccessScope($provider)];\n\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n case SocialAccount::PROVIDER_SALESFORCE:\n case SocialAccount::PROVIDER_HUBSPOT:\n case SocialAccount::PROVIDER_OUTREACH:\n case SocialAccount::PROVIDER_SALESLOFT:\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n case SocialAccount::PROVIDER_PIPEDRIVE:\n case SocialAccount::PROVIDER_SLACK:\n case SocialAccount::PROVIDER_AIRCALL:\n case SocialAccount::PROVIDER_BULLHORN:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_TELUS:\n case SocialAccount::PROVIDER_DIALPAD:\n case SocialAccount::PROVIDER_TALKDESK:\n return $scopes;\n\n case SocialAccount::PROVIDER_OFFICE:\n return $scopes + [\n 'access_type' => 'offline',\n ];\n\n case SocialAccount::PROVIDER_GOOGLE:\n return $scopes + [\n 'access_type' => 'offline',\n 'include_granted_scopes' => 'true',\n 'approval_prompt' => null,\n ];\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n private function tokenDoesNotExpire(SocialAccount $account): bool\n {\n return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);\n }\n\n private function hasValidToken(SocialAccount $account): bool\n {\n return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();\n }\n\n private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void\n {\n Datadog::increment('jiminny.access_token', 1, [\n 'provider' => $account->getProviderName(),\n 'state' => $state,\n 'result' => $result,\n ]);\n }\n\n private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),\n ];\n }\n\n private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n try {\n $parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);\n $number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);\n } catch (NumberParseException) {\n $number = null;\n }\n\n // Todo: this should check the `organization_id` matches the parent crm configuration.\n\n return [\n 'country_code' => $this->countryCode,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),\n 'phone' => $number,\n 'crm_provider_id' => $rawUserData['organization_id'],\n 'crm_base_url' => $this->vendorValues['instance_url'],\n ];\n }\n\n /**\n * Todo: this should check the `getHubId` matches the parent crm configuration.\n */\n private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array\n {\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $providerUser->getHubId(),\n 'crm_base_url' => $providerUser->toArray()['hub_domain'],\n ];\n }\n\n /**\n * Todo: this should check the `getCompanyId` matches the parent crm configuration.\n */\n private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $rawUserData['data']['company_id'],\n 'crm_base_url' => 'https://' . $rawUserData['data']['company_domain'] . '.pipedrive.com',\n ];\n }\n\n private function mapGoogleUserData(GoogleUser $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($providerUser->getEmail()),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapSlackUserData(SlackResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getRealName(),\n ];\n }\n\n private function mapOfficeUserData(AzureResourceOwner $providerUser): array\n {\n $email = $providerUser->getUpn() ?? $providerUser->claim('email');\n\n $this->logger->info('[Office] User authenticated', $providerUser->toArray());\n\n $name = $providerUser->claim('name') ??\n $providerUser->getFirstName() . ' ' . $providerUser->getLastName();\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($email),\n 'name' => $name,\n ];\n }\n\n private function mapOutreachUserData(ResourceOwnerInterface $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n $socialProvider = $this->getProvider(SocialAccount::PROVIDER_OUTREACH);\n $url = 'https://api.outreach.io/api/v2/profiles/';\n\n try {\n $request = $socialProvider->getAuthenticatedRequest(\n 'get',\n $url . $rawUserData['meta']['user']['id'],\n $this->accessToken,\n );\n\n $response = $socialProvider->getParsedResponse($request);\n\n $this->logger->info('[Outreach] User authenticated', $response);\n } catch (Exception) {\n //Just ignore\n }\n\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapDialpadUserData(DialpadResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n // They need to be Super Admin to access the Company APIs.\n $this->logger->info('[Dialpad] User authenticated', $rawUserData);\n\n if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Dialpad Super Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapAircallUserData(AircallResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array\n {\n if ($providerUser->toArray()['data']['team_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Team Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapBullhornUserData(): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n\n private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Services;\n\n/**\n * @todo cleanup after #slack-oauth-v2\n */\n\nuse AdamPaterson\\OAuth2\\Client\\Provider\\SlackResourceOwner;\nuse Chadhutchins\\OAuth2\\Client\\Provider\\Slack;\nuse ChaseConey\\LaravelDatadogHelper\\Datadog;\nuse Daniti\\OAuth2\\Client\\Provider\\Pipedrive;\nuse Daniti\\OAuth2\\Client\\Provider\\PipedriveResourceOwner;\nuse Exception;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpot;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpotResourceOwner;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Auth\\AuthenticationException;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Jiminny\\Component\\Encryption\\EncryptedTokenManager;\nuse Jiminny\\Events\\Users\\CrmAccountReconnected;\nuse Jiminny\\Events\\Users\\SocialAccountConnected;\nuse Jiminny\\Events\\Users\\SocialAccountDisconnected;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\InvalidEnumException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Notifications\\SlackBotAdded;\nuse Jiminny\\OAuth2\\Client\\Provider\\Aircall;\nuse Jiminny\\OAuth2\\Client\\Provider\\AircallResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Bullhorn;\nuse Jiminny\\OAuth2\\Client\\Provider\\Dialpad;\nuse Jiminny\\OAuth2\\Client\\Provider\\DialpadResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Salesloft;\nuse Jiminny\\OAuth2\\Client\\Provider\\SalesloftResourceOwner;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\Talkdesk;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\TalkdeskResourceOwner;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\Zoom;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\ZoomResourceOwner;\nuse Jiminny\\Services\\OAuth2\\Provider\\BasicAuth;\nuse Jiminny\\Services\\OAuth2\\Provider\\Outreach;\nuse JsonException;\nuse League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider;\nuse League\\OAuth2\\Client\\Provider\\AbstractProvider;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Provider\\Google;\nuse League\\OAuth2\\Client\\Provider\\GoogleUser;\nuse League\\OAuth2\\Client\\Provider\\LinkedIn;\nuse League\\OAuth2\\Client\\Provider\\LinkedInResourceOwner;\nuse League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse League\\OAuth2\\Client\\Token\\AccessTokenInterface;\nuse libphonenumber\\NumberParseException;\nuse libphonenumber\\PhoneNumberFormat;\nuse libphonenumber\\PhoneNumberUtil;\nuse LogicException;\nuse Psr\\Log\\LoggerInterface;\nuse Random\\RandomException;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\Salesforce;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\SalesforceResourceOwner;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\nuse TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner;\nuse Throwable;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingCentral;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingcentralResourceOwner;\n\nclass SocialAccountService\n{\n /**\n * Get a fresh tokens 5 minutes before it expires\n * That should minimise the number of failed requests due to expired token\n * for long-running jobs that reuse the same token for pulling lots of data.\n */\n private const int REFRESH_OFFSET_MIN = 5;\n\n private const string TOKEN_STATE_FETCH = 'fetch';\n private const string TOKEN_STATE_REFRESH = 'refresh';\n private const string TOKEN_RESULT_ATTEMPT = 'attempt';\n private const string TOKEN_RESULT_SUCCESS = 'success';\n private const string TOKEN_RESULT_FAILURE = 'failure';\n\n private ?AccessTokenInterface $accessToken = null;\n private ?string $token = null;\n private ?string $refreshToken = null;\n private ?int $expires = null;\n private ?string $countryCode = null;\n private ?string $timezone = null;\n private ?array $vendorValues = null;\n\n private ?int $refreshTokenExpires = null;\n\n public function __construct(\n private readonly EncryptedTokenManager $encryptedTokenManager,\n private readonly LoggerInterface $logger,\n private readonly PhoneNumberUtil $phoneNumberUtil,\n private readonly Dispatcher $eventDispatcher,\n ) {\n }\n\n public function setVendorValues(array $values): void\n {\n $this->vendorValues = $values;\n }\n\n public function setAccessToken(AccessTokenInterface $accessToken): void\n {\n $this->accessToken = $accessToken;\n // Todo: Also set these other params from this token e.g. refreshToken\n }\n\n public function setToken(?string $token): void\n {\n $this->token = $token;\n }\n\n public function setRefreshToken(?string $refreshToken): void\n {\n $this->refreshToken = $refreshToken;\n }\n\n public function setCountryCode(string $countryCode): void\n {\n $this->countryCode = $countryCode;\n }\n\n public function setTimezone(string $timezone): void\n {\n $this->timezone = $timezone;\n }\n\n public function setExpires(?int $expiry): void\n {\n $this->expires = $expiry;\n }\n\n public function setRefreshTokenExpires(array $values): void\n {\n $this->refreshTokenExpires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getProvider(string $provider): AbstractProvider\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n return new LinkedIn(config('services.linkedin'));\n\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n $socialProvider = new LinkedIn(config('services.linkedin-conference'));\n $socialProvider->withFields([\n 'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',\n ]);\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_SALESFORCE:\n return new Salesforce(config('services.salesforce'));\n\n case SocialAccount::PROVIDER_GOOGLE:\n return new Google(config('services.google'));\n\n case SocialAccount::PROVIDER_SLACK:\n return new Slack(config('services.slack'));\n\n case SocialAccount::PROVIDER_OFFICE:\n $config = config('services.office');\n\n // Convert string scope to array format expected by Azure provider\n if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {\n $config['scopes'] = array_filter(preg_split('/\\s+/', trim($config['scope'])));\n unset($config['scope']);\n }\n\n $socialProvider = new Azure($config);\n $socialProvider->urlAPI = 'https://graph.microsoft.com/v1.0/';\n $socialProvider->API_VERSION = '1.0';\n $socialProvider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_HUBSPOT:\n return new HubSpot(config('services.hubspot'));\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n return new Pipedrive(config('services.pipedrive'));\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n return new Zoom(config('services.zoom-phone'));\n\n case SocialAccount::PROVIDER_OUTREACH:\n return new Outreach(config('services.outreach'));\n\n case SocialAccount::PROVIDER_SALESLOFT:\n return new Salesloft(config('services.salesloft'));\n\n case SocialAccount::PROVIDER_AIRCALL:\n return new Aircall(config('services.aircall'));\n\n case SocialAccount::PROVIDER_DIALPAD:\n return new Dialpad(config('services.dialpad'));\n\n case SocialAccount::PROVIDER_GONG:\n return new BasicAuth(config('services.gong'));\n\n case SocialAccount::PROVIDER_CLOSE:\n return new BasicAuth(config('services.close'));\n\n case SocialAccount::PROVIDER_AVAYA:\n // Avaya is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.avaya'));\n\n case SocialAccount::PROVIDER_TELUS:\n // Telus is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.telus'));\n\n case SocialAccount::PROVIDER_RINGCENTRAL:\n return new RingCentral(config('services.ringcentral'));\n\n case SocialAccount::PROVIDER_BULLHORN:\n return new Bullhorn(config('services.bullhorn'));\n\n case SocialAccount::PROVIDER_TALKDESK:\n return new Talkdesk(config('services.talkdesk'), [\n // Automatically concatenate Basic token to AuthToken requests\n 'optionProvider' => new HttpBasicAuthOptionProvider(),\n ]);\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n /**\n *\n *\n * @throws Exception\n */\n public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n /** @var LinkedInResourceOwner $providerUser */\n return $this->mapLinkedInUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESFORCE:\n /** @var SalesforceResourceOwner $providerUser */\n return $this->mapSalesforceUserData($providerUser);\n\n case SocialAccount::PROVIDER_HUBSPOT:\n /** @var HubSpotResourceOwner $providerUser */\n return $this->mapHubSpotUserData($providerUser);\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n /** @var PipedriveResourceOwner $providerUser */\n return $this->mapPipedriveUserData($providerUser);\n\n case SocialAccount::PROVIDER_GOOGLE:\n /** @var GoogleUser $providerUser */\n return $this->mapGoogleUserData($providerUser);\n\n case SocialAccount::PROVIDER_SLACK:\n /** @var SlackResourceOwner $providerUser */\n return $this->mapSlackUserData($providerUser);\n\n case SocialAccount::PROVIDER_OFFICE:\n /** @var AzureResourceOwner $providerUser */\n return $this->mapOfficeUserData($providerUser);\n\n case SocialAccount::PROVIDER_OUTREACH:\n return $this->mapOutreachUserData($providerUser);\n\n case SocialAccount::PROVIDER_DIALPAD:\n /** @var DialpadResourceOwner $providerUser*/\n return $this->mapDialpadUserData($providerUser);\n\n case SocialAccount::PROVIDER_AIRCALL:\n /** @var AircallResourceOwner $providerUser */\n return $this->mapAircallUserData($providerUser);\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n /** @var ZoomResourceOwner $providerUser */\n return $this->mapZoomPhoneUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESLOFT:\n /** @var SalesloftResourceOwner $providerUser */\n return $this->mapSalesloftUserData($providerUser);\n\n case SocialAccount::PROVIDER_BULLHORN:\n return $this->mapBullhornUserData();\n\n case SocialAccount::PROVIDER_TALKDESK:\n /** @var TalkdeskResourceOwner $providerUser */\n return $this->mapTalkdeskUserData($providerUser);\n\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_TELUS:\n /** @var RingcentralResourceOwner $providerUser */\n return $this->mapRingCentralUserData($providerUser);\n default:\n throw new InvalidEnumException('Unknown provider.');\n }\n }\n\n /**\n * Returns a new random string to use as the state parameter in an\n * authorization flow.\n *\n * @param int $length Length of the random string to be generated.\n *\n * @throws RandomException\n */\n public function getRandomState(int $length = 32): string\n {\n // Converting bytes to hex will always double length. Hence, we can reduce\n // the amount of bytes by half to produce the correct length.\n return bin2hex(random_bytes($length / 2));\n }\n\n private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount\n {\n return SocialAccount::where([\n 'provider' => $provider,\n 'provider_user_id' => $providerUser->getId(),\n ])->first();\n }\n\n /**\n * Based on the provider data, try to match to a sociable entity based on email.\n * If a match is made, create the social account under that entity.\n *\n * @throws AuthenticationException\n */\n public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User\n {\n $account = $this->getAssociation($provider, $providerUser);\n if ($account !== null && $account->hasUser()) {\n return $account->getUser();\n }\n $userData = $this->mapUserData($provider, $providerUser);\n\n // Check if we have an actual user with this email.\n /** @var User|null $user */\n $user = User::where('email', $userData['email'])->first();\n\n // If the user is trying to connect to LinkedIn, don't allow this.\n // Todo: have an interstitial page to perform 2FA to connect.\n if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {\n throw new AuthenticationException(\n 'Sorry, you\\'ll need to login through your Jiminny account to access the Conference.',\n );\n }\n\n return $user;\n }\n\n /**\n * @throws JsonException\n */\n public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount\n {\n /** @var SocialAccount $account */\n $account = $user->socialAccounts()->firstOrNew([\n 'provider' => $provider,\n ]);\n\n $account->fill([\n 'provider_user_id' => $providerUser->getId(),\n 'provider_user_token' => $this->token,\n 'expires' => $this->expires,\n 'state' => SocialAccount::STATE_CONNECTED,\n 'retry_after' => null,\n ]);\n\n // This is an optional parameter, don't overwrite the existing one with null if we don't get it.\n if ($this->refreshToken) {\n $account->fill([\n 'provider_refresh_token' => $this->refreshToken,\n 'refresh_token_expires' => $this->refreshTokenExpires,\n ]);\n }\n\n if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {\n $account->fill([\n 'auth_scope' => is_scalar($this->vendorValues['scope'])\n ? $this->vendorValues['scope']\n : json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),\n ]);\n } else {\n $account->fill([\n 'auth_scope' => null,\n ]);\n\n $this->logger->warning(\n '[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',\n // pulling directly from the token, just to avoid potential masking of the issue\n ['token_values' => $this->accessToken->getValues()],\n );\n }\n\n $account->save();\n\n // Association can be from an updated token so don't re-announce this.\n if (\n $account->wasRecentlyCreated\n && in_array($provider, SocialAccount::CRM_PROVIDERS, true)\n && $provider !== SocialAccount::PROVIDER_HUBSPOT\n && $providerUser->getId() !== null\n ) {\n $crm = $user->team->crm;\n $data = [\n 'crm_configuration_id' => $crm->id,\n 'log_notes' => Profile::LOG_NOTE_ENHANCED,\n ];\n\n $crmProfile = $user->crmProfile()->where([\n 'crm_provider_id' => $providerUser->getId(),\n ])->first();\n\n $user->crmProfile()->updateOrCreate([\n 'crm_provider_id' => $providerUser->getId(),\n ], $data);\n\n // If updated, fire reconnected\n if ($crmProfile !== null) {\n $this->eventDispatcher->dispatch(new CrmAccountReconnected($account));\n }\n }\n\n $this->eventDispatcher->dispatch(new SocialAccountConnected($account));\n\n return $account;\n }\n\n public function integrate(string $provider, User $user, Team $team): void\n {\n if ($provider === SocialAccount::PROVIDER_SLACK) {\n if (! isset($this->vendorValues['ok'])\n || $this->vendorValues['ok'] !== true\n || ! isset($this->vendorValues['token_type'])\n || $this->vendorValues['token_type'] !== 'bot'\n ) {\n // code expects V2 token, which differs slightly from V1\n throw new LogicException('Invalid token received from Slack OAuth v2 API');\n }\n\n $webhook = $this->vendorValues['incoming_webhook'];\n\n $slackTeamId = $this->vendorValues['team']['id'];\n\n $botData = [\n 'channel' => $webhook['channel'],\n 'channel_id' => $webhook['channel_id'],\n 'config_url' => $webhook['configuration_url'],\n 'webhook_url' => $webhook['url'],\n 'bot_user_id' => $this->vendorValues['bot_user_id'],\n 'bot_access_token' => $this->accessToken->getToken(),\n ];\n\n $slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);\n\n if ($slackBot->wasRecentlyCreated) {\n // Send Slack notification.\n $user->notify(new SlackBotAdded());\n }\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);\n\n $this->logger->info('[SocialAccountService] Fetching token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $account->refresh();\n\n if (\n ! $forceRefresh\n && ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))\n ) {\n $this->logger->info('[SocialAccountService] Token retrieved', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);\n\n return $this->encryptedTokenManager->getAccessToken($account);\n }\n\n try {\n $this->logger->info('[SocialAccountService] Token needs refreshing', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n return $this->refreshToken($account, $forceRefresh);\n } catch (IdentityProviderException $exception) {\n $responseBody = $exception->getResponseBody();\n\n if ($responseBody instanceof Response) {\n $responseBody = $responseBody->getBody();\n }\n\n if (is_object($responseBody) && method_exists($responseBody, '__toString')) {\n $responseBody = $responseBody->__toString();\n }\n\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'responseBody' => $responseBody,\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n } catch (SocialAccountTokenInvalidException $exception) {\n $this->logger->error('[SocialAccountService] Cannot obtain token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception::class,\n 'errorMessage' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {\n $this->logger->error('[SocialAccountService] Full refresh required', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n // Something terrible happened their token, they need to reconnect.\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n $this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));\n }\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n }\n }\n\n public function refreshSocialAccountToken(SocialAccount $socialAccount): void\n {\n try {\n $this->getToken($socialAccount);\n } catch (Throwable $e) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $socialAccount->getId(),\n 'provider' => $socialAccount->getProviderName(),\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);\n\n $newToken = null;\n\n Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)\n ->block(8, function () use ($account, $forceRefresh, &$newToken): void {\n try {\n $account->refresh();\n $token = $this->encryptedTokenManager->getAccessToken($account);\n\n if (! $forceRefresh && $this->hasValidToken($account)) {\n $newToken = $token;\n\n return;\n }\n\n if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {\n $this->logger->error('[SocialAccountService] Refresh token not found', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog(\n $account,\n self::TOKEN_STATE_REFRESH,\n self::TOKEN_RESULT_FAILURE,\n );\n\n throw new SocialAccountTokenInvalidException(\n 'Refresh token is not set, re-connection required.',\n );\n }\n\n $this->logger->info('[SocialAccountService] Refreshing token from provider', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),\n 'state' => $account->getState(),\n ]);\n\n $newToken = $this->getProvider($account->provider)\n ->getAccessToken('refresh_token', [\n 'refresh_token' => $token->getRefreshToken(),\n ])\n ;\n\n if ($newToken->getToken() === $token->getToken()) {\n $this->logger->info('[SocialAccountService] Refreshed with an identical token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n }\n } catch (ConnectException | RequestException $exception) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n // This usually occurs due to SSL errors.\n throw new SocialAccountTokenInvalidException(\n 'Token could not be refreshed.',\n $exception->getCode(),\n $exception,\n );\n }\n\n $account->provider_user_token = $newToken->getToken();\n $account->expires = $newToken->getExpires();\n $account->state = SocialAccount::STATE_CONNECTED;\n\n if ($newToken->getRefreshToken()) {\n $account->provider_refresh_token = $newToken->getRefreshToken();\n $values = $newToken->getValues();\n $account->refresh_token_expires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n $account->save();\n });\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);\n\n $this->logger->info('[SocialAccountService] Token refreshed', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'state' => $account->getState(),\n ]);\n\n return $newToken;\n }\n\n /**\n * @return string[]\n */\n private function getAccessScope(string $provider): array\n {\n $scopes = [];\n $providerScopes = config('services.' . $provider . '.scope');\n\n if ($providerScopes) {\n $scopes = preg_split('/\\s+/', $providerScopes);\n }\n\n return $scopes;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getAuthorizationOptions(string $provider): array\n {\n $scopes = ['scope' => $this->getAccessScope($provider)];\n\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n case SocialAccount::PROVIDER_SALESFORCE:\n case SocialAccount::PROVIDER_HUBSPOT:\n case SocialAccount::PROVIDER_OUTREACH:\n case SocialAccount::PROVIDER_SALESLOFT:\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n case SocialAccount::PROVIDER_PIPEDRIVE:\n case SocialAccount::PROVIDER_SLACK:\n case SocialAccount::PROVIDER_AIRCALL:\n case SocialAccount::PROVIDER_BULLHORN:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_TELUS:\n case SocialAccount::PROVIDER_DIALPAD:\n case SocialAccount::PROVIDER_TALKDESK:\n return $scopes;\n\n case SocialAccount::PROVIDER_OFFICE:\n return $scopes + [\n 'access_type' => 'offline',\n ];\n\n case SocialAccount::PROVIDER_GOOGLE:\n return $scopes + [\n 'access_type' => 'offline',\n 'include_granted_scopes' => 'true',\n 'approval_prompt' => null,\n ];\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n private function tokenDoesNotExpire(SocialAccount $account): bool\n {\n return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);\n }\n\n private function hasValidToken(SocialAccount $account): bool\n {\n return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();\n }\n\n private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void\n {\n Datadog::increment('jiminny.access_token', 1, [\n 'provider' => $account->getProviderName(),\n 'state' => $state,\n 'result' => $result,\n ]);\n }\n\n private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),\n ];\n }\n\n private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n try {\n $parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);\n $number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);\n } catch (NumberParseException) {\n $number = null;\n }\n\n // Todo: this should check the `organization_id` matches the parent crm configuration.\n\n return [\n 'country_code' => $this->countryCode,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),\n 'phone' => $number,\n 'crm_provider_id' => $rawUserData['organization_id'],\n 'crm_base_url' => $this->vendorValues['instance_url'],\n ];\n }\n\n /**\n * Todo: this should check the `getHubId` matches the parent crm configuration.\n */\n private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array\n {\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $providerUser->getHubId(),\n 'crm_base_url' => $providerUser->toArray()['hub_domain'],\n ];\n }\n\n /**\n * Todo: this should check the `getCompanyId` matches the parent crm configuration.\n */\n private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $rawUserData['data']['company_id'],\n 'crm_base_url' => 'https://' . $rawUserData['data']['company_domain'] . '.pipedrive.com',\n ];\n }\n\n private function mapGoogleUserData(GoogleUser $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($providerUser->getEmail()),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapSlackUserData(SlackResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getRealName(),\n ];\n }\n\n private function mapOfficeUserData(AzureResourceOwner $providerUser): array\n {\n $email = $providerUser->getUpn() ?? $providerUser->claim('email');\n\n $this->logger->info('[Office] User authenticated', $providerUser->toArray());\n\n $name = $providerUser->claim('name') ??\n $providerUser->getFirstName() . ' ' . $providerUser->getLastName();\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($email),\n 'name' => $name,\n ];\n }\n\n private function mapOutreachUserData(ResourceOwnerInterface $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n $socialProvider = $this->getProvider(SocialAccount::PROVIDER_OUTREACH);\n $url = 'https://api.outreach.io/api/v2/profiles/';\n\n try {\n $request = $socialProvider->getAuthenticatedRequest(\n 'get',\n $url . $rawUserData['meta']['user']['id'],\n $this->accessToken,\n );\n\n $response = $socialProvider->getParsedResponse($request);\n\n $this->logger->info('[Outreach] User authenticated', $response);\n } catch (Exception) {\n //Just ignore\n }\n\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapDialpadUserData(DialpadResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n // They need to be Super Admin to access the Company APIs.\n $this->logger->info('[Dialpad] User authenticated', $rawUserData);\n\n if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Dialpad Super Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapAircallUserData(AircallResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array\n {\n if ($providerUser->toArray()['data']['team_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Team Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapBullhornUserData(): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n\n private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
-1193490926271754211
|
-8880471945877483717
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
namespace Jiminny\Services;
/**
* @todo cleanup after #slack-oauth-v2
*/
use AdamPaterson\OAuth2\Client\Provider\SlackResourceOwner;
use Chadhutchins\OAuth2\Client\Provider\Slack;
use ChaseConey\LaravelDatadogHelper\Datadog;
use Daniti\OAuth2\Client\Provider\Pipedrive;
use Daniti\OAuth2\Client\Provider\PipedriveResourceOwner;
use Exception;
use Flipbox\OAuth2\Client\Provider\HubSpot;
use Flipbox\OAuth2\Client\Provider\HubSpotResourceOwner;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Jiminny\Component\Encryption\EncryptedTokenManager;
use Jiminny\Events\Users\CrmAccountReconnected;
use Jiminny\Events\Users\SocialAccountConnected;
use Jiminny\Events\Users\SocialAccountDisconnected;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\InvalidEnumException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Notifications\SlackBotAdded;
use Jiminny\OAuth2\Client\Provider\Aircall;
use Jiminny\OAuth2\Client\Provider\AircallResourceOwner;
use Jiminny\OAuth2\Client\Provider\Bullhorn;
use Jiminny\OAuth2\Client\Provider\Dialpad;
use Jiminny\OAuth2\Client\Provider\DialpadResourceOwner;
use Jiminny\OAuth2\Client\Provider\Salesloft;
use Jiminny\OAuth2\Client\Provider\SalesloftResourceOwner;
use Jiminny\Services\Activity\Talkdesk\Provider\Talkdesk;
use Jiminny\Services\Activity\Talkdesk\Provider\TalkdeskResourceOwner;
use Jiminny\Services\Activity\Zoom\Provider\Zoom;
use Jiminny\Services\Activity\Zoom\Provider\ZoomResourceOwner;
use Jiminny\Services\OAuth2\Provider\BasicAuth;
use Jiminny\Services\OAuth2\Provider\Outreach;
use JsonException;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\GoogleUser;
use League\OAuth2\Client\Provider\LinkedIn;
use League\OAuth2\Client\Provider\LinkedInResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Psr\Log\LoggerInterface;
use Random\RandomException;
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
use Stevenmaguire\OAuth2\Client\Provider\SalesforceResourceOwner;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Provider\AzureResourceOwner;
use Throwable;
use TMannherz\OAuth2\Client\Provider\RingCentral;
use TMannherz\OAuth2\Client\Provider\RingcentralResourceOwner;
class SocialAccountService
{
/**
* Get a fresh tokens 5 minutes before it expires
* That should minimise the number of failed requests due to expired token
* for long-running jobs that reuse the same token for pulling lots of data.
*/
private const int REFRESH_OFFSET_MIN = 5;
private const string TOKEN_STATE_FETCH = 'fetch';
private const string TOKEN_STATE_REFRESH = 'refresh';
private const string TOKEN_RESULT_ATTEMPT = 'attempt';
private const string TOKEN_RESULT_SUCCESS = 'success';
private const string TOKEN_RESULT_FAILURE = 'failure';
private ?AccessTokenInterface $accessToken = null;
private ?string $token = null;
private ?string $refreshToken = null;
private ?int $expires = null;
private ?string $countryCode = null;
private ?string $timezone = null;
private ?array $vendorValues = null;
private ?int $refreshTokenExpires = null;
public function __construct(
private readonly EncryptedTokenManager $encryptedTokenManager,
private readonly LoggerInterface $logger,
private readonly PhoneNumberUtil $phoneNumberUtil,
private readonly Dispatcher $eventDispatcher,
) {
}
public function setVendorValues(array $values): void
{
$this->vendorValues = $values;
}
public function setAccessToken(AccessTokenInterface $accessToken): void
{
$this->accessToken = $accessToken;
// Todo: Also set these other params from this token e.g. refreshToken
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function setRefreshToken(?string $refreshToken): void
{
$this->refreshToken = $refreshToken;
}
public function setCountryCode(string $countryCode): void
{
$this->countryCode = $countryCode;
}
public function setTimezone(string $timezone): void
{
$this->timezone = $timezone;
}
public function setExpires(?int $expiry): void
{
$this->expires = $expiry;
}
public function setRefreshTokenExpires(array $values): void
{
$this->refreshTokenExpires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
/**
* @throws InvalidEnumException
*/
public function getProvider(string $provider): AbstractProvider
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
return new LinkedIn(config('services.linkedin'));
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
$socialProvider = new LinkedIn(config('services.linkedin-conference'));
$socialProvider->withFields([
'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',
]);
return $socialProvider;
case SocialAccount::PROVIDER_SALESFORCE:
return new Salesforce(config('services.salesforce'));
case SocialAccount::PROVIDER_GOOGLE:
return new Google(config('services.google'));
case SocialAccount::PROVIDER_SLACK:
return new Slack(config('services.slack'));
case SocialAccount::PROVIDER_OFFICE:
$config = config('services.office');
// Convert string scope to array format expected by Azure provider
if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {
$config['scopes'] = array_filter(preg_split('/\s+/', trim($config['scope'])));
unset($config['scope']);
}
$socialProvider = new Azure($config);
$socialProvider->urlAPI = '[URL_WITH_CREDENTIALS] Exception
*/
public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
/** @var LinkedInResourceOwner $providerUser */
return $this->mapLinkedInUserData($providerUser);
case SocialAccount::PROVIDER_SALESFORCE:
/** @var SalesforceResourceOwner $providerUser */
return $this->mapSalesforceUserData($providerUser);
case SocialAccount::PROVIDER_HUBSPOT:
/** @var HubSpotResourceOwner $providerUser */
return $this->mapHubSpotUserData($providerUser);
case SocialAccount::PROVIDER_PIPEDRIVE:
/** @var PipedriveResourceOwner $providerUser */
return $this->mapPipedriveUserData($providerUser);
case SocialAccount::PROVIDER_GOOGLE:
/** @var GoogleUser $providerUser */
return $this->mapGoogleUserData($providerUser);
case SocialAccount::PROVIDER_SLACK:
/** @var SlackResourceOwner $providerUser */
return $this->mapSlackUserData($providerUser);
case SocialAccount::PROVIDER_OFFICE:
/** @var AzureResourceOwner $providerUser */
return $this->mapOfficeUserData($providerUser);
case SocialAccount::PROVIDER_OUTREACH:
return $this->mapOutreachUserData($providerUser);
case SocialAccount::PROVIDER_DIALPAD:
/** @var DialpadResourceOwner $providerUser*/
return $this->mapDialpadUserData($providerUser);
case SocialAccount::PROVIDER_AIRCALL:
/** @var AircallResourceOwner $providerUser */
return $this->mapAircallUserData($providerUser);
case SocialAccount::PROVIDER_ZOOM_PHONE:
/** @var ZoomResourceOwner $providerUser */
return $this->mapZoomPhoneUserData($providerUser);
case SocialAccount::PROVIDER_SALESLOFT:
/** @var SalesloftResourceOwner $providerUser */
return $this->mapSalesloftUserData($providerUser);
case SocialAccount::PROVIDER_BULLHORN:
return $this->mapBullhornUserData();
case SocialAccount::PROVIDER_TALKDESK:
/** @var TalkdeskResourceOwner $providerUser */
return $this->mapTalkdeskUserData($providerUser);
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_TELUS:
/** @var RingcentralResourceOwner $providerUser */
return $this->mapRingCentralUserData($providerUser);
default:
throw new InvalidEnumException('Unknown provider.');
}
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
*
* @throws RandomException
*/
public function getRandomState(int $length = 32): string
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return bin2hex(random_bytes($length / 2));
}
private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount
{
return SocialAccount::where([
'provider' => $provider,
'provider_user_id' => $providerUser->getId(),
])->first();
}
/**
* Based on the provider data, try to match to a sociable entity based on email.
* If a match is made, create the social account under that entity.
*
* @throws AuthenticationException
*/
public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User
{
$account = $this->getAssociation($provider, $providerUser);
if ($account !== null && $account->hasUser()) {
return $account->getUser();
}
$userData = $this->mapUserData($provider, $providerUser);
// Check if we have an actual user with this email.
/** @var User|null $user */
$user = User::where('email', $userData['email'])->first();
// If the user is trying to connect to LinkedIn, don't allow this.
// Todo: have an interstitial page to perform 2FA to connect.
if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {
throw new AuthenticationException(
'Sorry, you\'ll need to login through your Jiminny account to access the Conference.',
);
}
return $user;
}
/**
* @throws JsonException
*/
public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount
{
/** @var SocialAccount $account */
$account = $user->socialAccounts()->firstOrNew([
'provider' => $provider,
]);
$account->fill([
'provider_user_id' => $providerUser->getId(),
'provider_user_token' => $this->token,
'expires' => $this->expires,
'state' => SocialAccount::STATE_CONNECTED,
'retry_after' => null,
]);
// This is an optional parameter, don't overwrite the existing one with null if we don't get it.
if ($this->refreshToken) {
$account->fill([
'provider_refresh_token' => $this->refreshToken,
'refresh_token_expires' => $this->refreshTokenExpires,
]);
}
if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {
$account->fill([
'auth_scope' => is_scalar($this->vendorValues['scope'])
? $this->vendorValues['scope']
: json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),
]);
} else {
$account->fill([
'auth_scope' => null,
]);
$this->logger->warning(
'[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',
// pulling directly from the token, just to avoid potential masking of the issue
['token_values' => $this->accessToken->getValues()],
);
}
$account->save();
// Association can be from an updated token so don't re-announce this.
if (
$account->wasRecentlyCreated
&& in_array($provider, SocialAccount::CRM_PROVIDERS, true)
&& $provider !== SocialAccount::PROVIDER_HUBSPOT
&& $providerUser->getId() !== null
) {
$crm = $user->team->crm;
$data = [
'crm_configuration_id' => $crm->id,
'log_notes' => Profile::LOG_NOTE_ENHANCED,
];
$crmProfile = $user->crmProfile()->where([
'crm_provider_id' => $providerUser->getId(),
])->first();
$user->crmProfile()->updateOrCreate([
'crm_provider_id' => $providerUser->getId(),
], $data);
// If updated, fire reconnected
if ($crmProfile !== null) {
$this->eventDispatcher->dispatch(new CrmAccountReconnected($account));
}
}
$this->eventDispatcher->dispatch(new SocialAccountConnected($account));
return $account;
}
public function integrate(string $provider, User $user, Team $team): void
{
if ($provider === SocialAccount::PROVIDER_SLACK) {
if (! isset($this->vendorValues['ok'])
|| $this->vendorValues['ok'] !== true
|| ! isset($this->vendorValues['token_type'])
|| $this->vendorValues['token_type'] !== 'bot'
) {
// code expects V2 token, which differs slightly from V1
throw new LogicException('Invalid token received from Slack OAuth v2 API');
}
$webhook = $this->vendorValues['incoming_webhook'];
$slackTeamId = $this->vendorValues['team']['id'];
$botData = [
'channel' => $webhook['channel'],
'channel_id' => $webhook['channel_id'],
'config_url' => $webhook['configuration_url'],
'webhook_url' => $webhook['url'],
'bot_user_id' => $this->vendorValues['bot_user_id'],
'bot_access_token' => $this->accessToken->getToken(),
];
$slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);
if ($slackBot->wasRecentlyCreated) {
// Send Slack notification.
$user->notify(new SlackBotAdded());
}
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);
$this->logger->info('[SocialAccountService] Fetching token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$account->refresh();
if (
! $forceRefresh
&& ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))
) {
$this->logger->info('[SocialAccountService] Token retrieved', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);
return $this->encryptedTokenManager->getAccessToken($account);
}
try {
$this->logger->info('[SocialAccountService] Token needs refreshing', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
return $this->refreshToken($account, $forceRefresh);
} catch (IdentityProviderException $exception) {
$responseBody = $exception->getResponseBody();
if ($responseBody instanceof Response) {
$responseBody = $responseBody->getBody();
}
if (is_object($responseBody) && method_exists($responseBody, '__toString')) {
$responseBody = $responseBody->__toString();
}
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'responseBody' => $responseBody,
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
} catch (SocialAccountTokenInvalidException $exception) {
$this->logger->error('[SocialAccountService] Cannot obtain token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception::class,
'errorMessage' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {
$this->logger->error('[SocialAccountService] Full refresh required', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
// Something terrible happened their token, they need to reconnect.
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
$this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));
}
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
}
}
public function refreshSocialAccountToken(SocialAccount $socialAccount): void
{
try {
$this->getToken($socialAccount);
} catch (Throwable $e) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $socialAccount->getId(),
'provider' => $socialAccount->getProviderName(),
'reason' => $e->getMessage(),
]);
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);
$newToken = null;
Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)
->block(8, function () use ($account, $forceRefresh, &$newToken): void {
try {
$account->refresh();
$token = $this->encryptedTokenManager->getAccessToken($account);
if (! $forceRefresh && $this->hasValidToken($account)) {
$newToken = $token;
return;
}
if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {
$this->logger->error('[SocialAccountService] Refresh token not found', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog(
$account,
self::TOKEN_STATE_REFRESH,
self::TOKEN_RESULT_FAILURE,
);
throw new SocialAccountTokenInvalidException(
'Refresh token is not set, re-connection required.',
);
}
$this->logger->info('[SocialAccountService] Refreshing token from provider', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),
'state' => $account->getState(),
]);
$newToken = $this->getProvider($account->provider)
->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
])
;
if ($newToken->getToken() === $token->getToken()) {
$this->logger->info('[SocialAccountService] Refreshed with an identical token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
}
} catch (ConnectException | RequestException $exception) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
// This usually occurs due to SSL errors.
throw new SocialAccountTokenInvalidException(
'Token could not be refreshed.',
$exception->getCode(),
$exception,
);
}
$account->provider_user_token = $newToken->getToken();
$account->expires = $newToken->getExpires();
$account->state = SocialAccount::STATE_CONNECTED;
if ($newToken->getRefreshToken()) {
$account->provider_refresh_token = $newToken->getRefreshToken();
$values = $newToken->getValues();
$account->refresh_token_expires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
$account->save();
});
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);
$this->logger->info('[SocialAccountService] Token refreshed', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'state' => $account->getState(),
]);
return $newToken;
}
/**
* @return string[]
*/
private function getAccessScope(string $provider): array
{
$scopes = [];
$providerScopes = config('services.' . $provider . '.scope');
if ($providerScopes) {
$scopes = preg_split('/\s+/', $providerScopes);
}
return $scopes;
}
/**
* @throws InvalidEnumException
*/
public function getAuthorizationOptions(string $provider): array
{
$scopes = ['scope' => $this->getAccessScope($provider)];
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
case SocialAccount::PROVIDER_SALESFORCE:
case SocialAccount::PROVIDER_HUBSPOT:
case SocialAccount::PROVIDER_OUTREACH:
case SocialAccount::PROVIDER_SALESLOFT:
case SocialAccount::PROVIDER_ZOOM_PHONE:
case SocialAccount::PROVIDER_PIPEDRIVE:
case SocialAccount::PROVIDER_SLACK:
case SocialAccount::PROVIDER_AIRCALL:
case SocialAccount::PROVIDER_BULLHORN:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_TELUS:
case SocialAccount::PROVIDER_DIALPAD:
case SocialAccount::PROVIDER_TALKDESK:
return $scopes;
case SocialAccount::PROVIDER_OFFICE:
return $scopes + [
'access_type' => 'offline',
];
case SocialAccount::PROVIDER_GOOGLE:
return $scopes + [
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'approval_prompt' => null,
];
default:
throw new InvalidEnumException();
}
}
private function tokenDoesNotExpire(SocialAccount $account): bool
{
return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);
}
private function hasValidToken(SocialAccount $account): bool
{
return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();
}
private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void
{
Datadog::increment('jiminny.access_token', 1, [
'provider' => $account->getProviderName(),
'state' => $state,
'result' => $result,
]);
}
private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),
];
}
private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
try {
$parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);
$number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);
} catch (NumberParseException) {
$number = null;
}
// Todo: this should check the `organization_id` matches the parent crm configuration.
return [
'country_code' => $this->countryCode,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),
'phone' => $number,
'crm_provider_id' => $rawUserData['organization_id'],
'crm_base_url' => $this->vendorValues['instance_url'],
];
}
/**
* Todo: this should check the `getHubId` matches the parent crm configuration.
*/
private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $providerUser->getHubId(),
'crm_base_url' => $providerUser->toArray()['hub_domain'],
];
}
/**
* Todo: this should check the `getCompanyId` matches the parent crm configuration.
*/
private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $rawUserData['data']['company_id'],
'crm_base_url' => '[URL_WITH_CREDENTIALS] ActivityProviderException
*/
private function mapDialpadUserData(DialpadResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
// They need to be Super Admin to access the Company APIs.
$this->logger->info('[Dialpad] User authenticated', $rawUserData);
if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Dialpad Super Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapAircallUserData(AircallResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
/**
* @throws ActivityProviderException
*/
private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array
{
if ($providerUser->toArray()['data']['team_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Team Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapBullhornUserData(): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
];
}
private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34714
|
1300
|
5
|
2026-05-13T11:34:50.017494+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672090017_m2.jpg...
|
PhpStorm
|
faVsco.js – EmailTextRelay.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.08843085,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.10472074,"top":0.15482841,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.11735372,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"TextRelayException","depth":4,"bounds":{"left":0.12832446,"top":0.15403032,"width":0.043882977,"height":0.015961692},"on_screen":true,"value":"TextRelayException","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.18118352,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.19115691,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.19980054,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.20844415,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1/12","depth":4,"bounds":{"left":0.22207446,"top":0.15323225,"width":0.025598405,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.24767287,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.25631648,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.2649601,"top":0.15243416,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1041761519822496290
|
-8195058156491786941
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
TextRelayException
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
1/12
Previous Occurrence
Next Occurrence
Filter Search Results
PhostormINavicarecodeLaravelKeractorFV faVsco.js°9 JY-20891-improvProiect v© MailboxController.phpg createlnoox.onpC DeleteEmallmessagesscC) TextRelavService.ongc Processtmalsonerass© SmsRelayFailed.phg0 MeetinaBo1C Middleware> → StreaminaC Teamw TelephonyC Userclass EmailTextRelay extends Job implements ShouldQueueprivate function checkIntegnity(GoogleGmaiZ\MessagePart Spayload, UserRepository SuserRepository)259c) ChangeEmailJob.pho260261DeactivateUserJob.phpc) DeleteScheduleduserAc263(C) SetuoDefaultSavedSeanCSvncTolntercom.ohv264265© SyncToPlanhat.php© SyncToUserPilot.php266© BaseProcessingJob.phpc) Dummv.loh.nhn© ImportRecallAlRecordingsJ© ImportRemoteTrackJob.phG Job.phpC.lohDicnatcher nhn© JobDispatcherInterface.ph© PurgeSoftDeletedOpporturT SqsVisibilityControl.phpv C Listenersv @ Activitiesv @ ActivityProvider>C JustCallv D UserPilot© TrackProviderinst>C Audic275?D 8otsv 2 Coachina>_lintercomv PlanhatC) CreateActivitvLod© CreateCoachingFC) Createcoachings© CreateCoachingF2852862872882891291© CreateCommenteC) CreateManaderC.© CreatePlayedEverC) CreateSelfCoache(e CrontoCharodEvo•MllcorDilot(e) Cronto AvnilabilitvNot(e) CronteCanchingSoorStext = sema1l->gecv1s1dlelexcif (Stext === ") {throw new TextRelayException(: 'Message body is un-readable or empty.'.code: self::REASON_CODE MESSAGE BODY_EMPTYsvauidator = Validator::make(data' => Stextir 'data' => new SmsMessageOlD1f Svalidator->farlsonthrow new TextrelayExceptionMessade body is too larde to send as an SMS.'.code: self.•REASON CODE MESSAGE BODY TOO LARG:Sthis->text = Stext.$sender = $this->parseSender($headers['From']):// Extract the Jiminny recipient.Srecipient = explode( separator: '@', Sthis->parseRecipient(Sheaders['To'))):// Check this message is intended for us.if (Srecipient[1] l== config( key: 'jiminny.google_text_host')) {throw new TextRelayException('Destination Mailbox does not match.'.code: self::REASON_CODE_MAILBOX_MISMATCH[$from, $to, $activityId] = $this->parseRecipientIntoEntities($recipient[0]);Svalidator = Validator::make(['data' => $from], ['data' => 'phone: INTERNATIONAL']);if (Svalidator->fails@) {throw new TextRelavExcention('Recipient origin number is not valid.',code: self.•REASON CODE RECIPTENT ORIGIN INVALIDSvalidator = Validator::make(['data' => $to], ['data' => 'phone:INTERNATIONAL']):irtcuts conflicts: Clone Caret Below and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (12 minutes ago)= custom.log|aravel.l0gA SF (jiminny@localhost]4 HS_local [jiminny@localhost]& console (PROD] X A console [EU]A console [STAGING]A30 K1 A V630-639—6331634639636— 6471 64864$65€651—652— 653=654— 655~65465)=6601 66669663664- 6651 668—669_ 676Tx: Auto vSo jiminnyAND td.domain = LOWERSUBSTRINGLNDEX(c.calendar provider 1d, 'd', -1)0GROUP BY t.id, t.name, calendar domain040 A1 A40 V 65 ^OrDER BY t.name.select * trom users u 1o1n calendans c 1<»>I.n. on c.user 1d = U.1dwhere u.team id = 882select * from activities where id = 14049485: # team 563 crm 537select * from activities where id = 73272382; # team 563 crm 537select * from activities where id = 64400389; # team 563 crm 537select * from activities where id = 58081273; # team 563 crm 537select * from activities whene id = 54520207• # +eam 563 crm 537select * from participants where activity_id = 58081273;select * from activities where crm_configuration_id = 537 and provider = 'aircalland account_id = 19003658 order by updated_at desc:select * from contacts where crm_configuration_id = 537 and id = 35957759;select * from accounts where crm confiquration id = 537 and id = 19003658:select * from automated report results where id = 1976:select * from automated_reports where id = 583;select * trom activity searches where10 = 8/1147select * trom activity search_ tilters where activity search 1d = 8/7141SELECT * FROM activities WHERE uuid to bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuidor uuld to b1nl 4/842446-2151-4000-854t-cc6568290101' = UU1d:SELE * FROM erm confiqurations WHERE provider = 'hubspot':select * from rate limitsted_report_results where media type = 'pdf' and status = 2and id IN (18, 1872);select * fromomated_reports where id = 54;SELECT * FROM users WHERE id IN (24623,29443,29613):SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;select * from text_relays where created_at > '2026-05-01'# and id IN (32415, 32416);and id = 20112.select * from users where team id = 2 and email like '%scott%' and id = 29510suppont Dally • In 20h100% 2• Wed 13 May 14:34:49AskJiminnyReportActivityServiceTest vcascadeTrial Owner Role SeleRetactoring User Ema+0 ..Ineed only EmailTextRelay? | changed it a bit. REveiw itRead EmailTextRelay.phpTnoughttor 2s>Your changes to EmailTextRelay.php look good:Changes Made:1. Multi-line method signature (lines 80-84) - Follows codina standards for better readability2. Pass SuserRepository to checkIntegrity (line 107) - Keeps dependency injection focused3. Updated checkintegrity signature (line 251 - Now accepts UserRepository SuserRepository4. Undated user lookun (line 308) - Chanaed from User::where("emaj]" Ssender)-sfirct() to SuserRenositorv->fiReview:wllserReSitorv: :findBvEmailo checks both emaii and cecondarv email fieldsThe dependency injection is cleaner - UserRepository is only used where needed•V Folllows the codina standards (multi- ine method sianatures• • No breaking changes to the existing logicThis approach is actually better than mine - vou kept the UserRepository usage localized to checkintearity where theucor lookun sctually hannens rather than ucina it in bandle and naccina the licer aroundiThe fix will resolve Scott's issue if he adds rewardgateway.com as his secondary_emait in Jiminny. The SMS relay will nowtind his account when he sends from that email adaress.lo Il «.app/Services/SocialAccountService.phpices/# SocialAccountService.php +3 -1app/Http/Controllers/Auth/@ ExtensionController.php +1 -3llers/API SsoController.php +4 -2annlGunrdel M Gco nhn 48app/Listeners/Users/ ValidateSendingMessage.php +6 -3es/# SxternalldUniqueToHostValidationRule.ohvAsk anvthina 84L)« Code SWF-1.6View allReiect alllAccent alliWN Windsurf Toams 277•56 UTF.9io 4 spaces...
|
34711
|
NULL
|
NULL
|
NULL
|
|
34715
|
1299
|
7
|
2026-05-13T11:34:54.529052+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672094529_m1.jpg...
|
PhpStorm
|
faVsco.js – SocialAccountService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
6
8
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services;
/**
* @todo cleanup after #slack-oauth-v2
*/
use AdamPaterson\OAuth2\Client\Provider\SlackResourceOwner;
use Chadhutchins\OAuth2\Client\Provider\Slack;
use ChaseConey\LaravelDatadogHelper\Datadog;
use Daniti\OAuth2\Client\Provider\Pipedrive;
use Daniti\OAuth2\Client\Provider\PipedriveResourceOwner;
use Exception;
use Flipbox\OAuth2\Client\Provider\HubSpot;
use Flipbox\OAuth2\Client\Provider\HubSpotResourceOwner;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Jiminny\Component\Encryption\EncryptedTokenManager;
use Jiminny\Events\Users\CrmAccountReconnected;
use Jiminny\Events\Users\SocialAccountConnected;
use Jiminny\Events\Users\SocialAccountDisconnected;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\InvalidEnumException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Notifications\SlackBotAdded;
use Jiminny\OAuth2\Client\Provider\Aircall;
use Jiminny\OAuth2\Client\Provider\AircallResourceOwner;
use Jiminny\OAuth2\Client\Provider\Bullhorn;
use Jiminny\OAuth2\Client\Provider\Dialpad;
use Jiminny\OAuth2\Client\Provider\DialpadResourceOwner;
use Jiminny\OAuth2\Client\Provider\Salesloft;
use Jiminny\OAuth2\Client\Provider\SalesloftResourceOwner;
use Jiminny\Services\Activity\Talkdesk\Provider\Talkdesk;
use Jiminny\Services\Activity\Talkdesk\Provider\TalkdeskResourceOwner;
use Jiminny\Services\Activity\Zoom\Provider\Zoom;
use Jiminny\Services\Activity\Zoom\Provider\ZoomResourceOwner;
use Jiminny\Services\OAuth2\Provider\BasicAuth;
use Jiminny\Services\OAuth2\Provider\Outreach;
use JsonException;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\GoogleUser;
use League\OAuth2\Client\Provider\LinkedIn;
use League\OAuth2\Client\Provider\LinkedInResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Psr\Log\LoggerInterface;
use Random\RandomException;
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
use Stevenmaguire\OAuth2\Client\Provider\SalesforceResourceOwner;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Provider\AzureResourceOwner;
use Throwable;
use TMannherz\OAuth2\Client\Provider\RingCentral;
use TMannherz\OAuth2\Client\Provider\RingcentralResourceOwner;
class SocialAccountService
{
/**
* Get a fresh tokens 5 minutes before it expires
* That should minimise the number of failed requests due to expired token
* for long-running jobs that reuse the same token for pulling lots of data.
*/
private const int REFRESH_OFFSET_MIN = 5;
private const string TOKEN_STATE_FETCH = 'fetch';
private const string TOKEN_STATE_REFRESH = 'refresh';
private const string TOKEN_RESULT_ATTEMPT = 'attempt';
private const string TOKEN_RESULT_SUCCESS = 'success';
private const string TOKEN_RESULT_FAILURE = 'failure';
private ?AccessTokenInterface $accessToken = null;
private ?string $token = null;
private ?string $refreshToken = null;
private ?int $expires = null;
private ?string $countryCode = null;
private ?string $timezone = null;
private ?array $vendorValues = null;
private ?int $refreshTokenExpires = null;
public function __construct(
private readonly EncryptedTokenManager $encryptedTokenManager,
private readonly LoggerInterface $logger,
private readonly PhoneNumberUtil $phoneNumberUtil,
private readonly Dispatcher $eventDispatcher,
) {
}
public function setVendorValues(array $values): void
{
$this->vendorValues = $values;
}
public function setAccessToken(AccessTokenInterface $accessToken): void
{
$this->accessToken = $accessToken;
// Todo: Also set these other params from this token e.g. refreshToken
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function setRefreshToken(?string $refreshToken): void
{
$this->refreshToken = $refreshToken;
}
public function setCountryCode(string $countryCode): void
{
$this->countryCode = $countryCode;
}
public function setTimezone(string $timezone): void
{
$this->timezone = $timezone;
}
public function setExpires(?int $expiry): void
{
$this->expires = $expiry;
}
public function setRefreshTokenExpires(array $values): void
{
$this->refreshTokenExpires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
/**
* @throws InvalidEnumException
*/
public function getProvider(string $provider): AbstractProvider
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
return new LinkedIn(config('services.linkedin'));
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
$socialProvider = new LinkedIn(config('services.linkedin-conference'));
$socialProvider->withFields([
'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',
]);
return $socialProvider;
case SocialAccount::PROVIDER_SALESFORCE:
return new Salesforce(config('services.salesforce'));
case SocialAccount::PROVIDER_GOOGLE:
return new Google(config('services.google'));
case SocialAccount::PROVIDER_SLACK:
return new Slack(config('services.slack'));
case SocialAccount::PROVIDER_OFFICE:
$config = config('services.office');
// Convert string scope to array format expected by Azure provider
if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {
$config['scopes'] = array_filter(preg_split('/\s+/', trim($config['scope'])));
unset($config['scope']);
}
$socialProvider = new Azure($config);
$socialProvider->urlAPI = '[URL_WITH_CREDENTIALS] Exception
*/
public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
/** @var LinkedInResourceOwner $providerUser */
return $this->mapLinkedInUserData($providerUser);
case SocialAccount::PROVIDER_SALESFORCE:
/** @var SalesforceResourceOwner $providerUser */
return $this->mapSalesforceUserData($providerUser);
case SocialAccount::PROVIDER_HUBSPOT:
/** @var HubSpotResourceOwner $providerUser */
return $this->mapHubSpotUserData($providerUser);
case SocialAccount::PROVIDER_PIPEDRIVE:
/** @var PipedriveResourceOwner $providerUser */
return $this->mapPipedriveUserData($providerUser);
case SocialAccount::PROVIDER_GOOGLE:
/** @var GoogleUser $providerUser */
return $this->mapGoogleUserData($providerUser);
case SocialAccount::PROVIDER_SLACK:
/** @var SlackResourceOwner $providerUser */
return $this->mapSlackUserData($providerUser);
case SocialAccount::PROVIDER_OFFICE:
/** @var AzureResourceOwner $providerUser */
return $this->mapOfficeUserData($providerUser);
case SocialAccount::PROVIDER_OUTREACH:
return $this->mapOutreachUserData($providerUser);
case SocialAccount::PROVIDER_DIALPAD:
/** @var DialpadResourceOwner $providerUser*/
return $this->mapDialpadUserData($providerUser);
case SocialAccount::PROVIDER_AIRCALL:
/** @var AircallResourceOwner $providerUser */
return $this->mapAircallUserData($providerUser);
case SocialAccount::PROVIDER_ZOOM_PHONE:
/** @var ZoomResourceOwner $providerUser */
return $this->mapZoomPhoneUserData($providerUser);
case SocialAccount::PROVIDER_SALESLOFT:
/** @var SalesloftResourceOwner $providerUser */
return $this->mapSalesloftUserData($providerUser);
case SocialAccount::PROVIDER_BULLHORN:
return $this->mapBullhornUserData();
case SocialAccount::PROVIDER_TALKDESK:
/** @var TalkdeskResourceOwner $providerUser */
return $this->mapTalkdeskUserData($providerUser);
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_TELUS:
/** @var RingcentralResourceOwner $providerUser */
return $this->mapRingCentralUserData($providerUser);
default:
throw new InvalidEnumException('Unknown provider.');
}
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
*
* @throws RandomException
*/
public function getRandomState(int $length = 32): string
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return bin2hex(random_bytes($length / 2));
}
private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount
{
return SocialAccount::where([
'provider' => $provider,
'provider_user_id' => $providerUser->getId(),
])->first();
}
/**
* Based on the provider data, try to match to a sociable entity based on email.
* If a match is made, create the social account under that entity.
*
* @throws AuthenticationException
*/
public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User
{
$account = $this->getAssociation($provider, $providerUser);
if ($account !== null && $account->hasUser()) {
return $account->getUser();
}
$userData = $this->mapUserData($provider, $providerUser);
// Check if we have an actual user with this email.
/** @var User|null $user */
$user = User::where('email', $userData['email'])->first();
// If the user is trying to connect to LinkedIn, don't allow this.
// Todo: have an interstitial page to perform 2FA to connect.
if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {
throw new AuthenticationException(
'Sorry, you\'ll need to login through your Jiminny account to access the Conference.',
);
}
return $user;
}
/**
* @throws JsonException
*/
public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount
{
/** @var SocialAccount $account */
$account = $user->socialAccounts()->firstOrNew([
'provider' => $provider,
]);
$account->fill([
'provider_user_id' => $providerUser->getId(),
'provider_user_token' => $this->token,
'expires' => $this->expires,
'state' => SocialAccount::STATE_CONNECTED,
'retry_after' => null,
]);
// This is an optional parameter, don't overwrite the existing one with null if we don't get it.
if ($this->refreshToken) {
$account->fill([
'provider_refresh_token' => $this->refreshToken,
'refresh_token_expires' => $this->refreshTokenExpires,
]);
}
if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {
$account->fill([
'auth_scope' => is_scalar($this->vendorValues['scope'])
? $this->vendorValues['scope']
: json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),
]);
} else {
$account->fill([
'auth_scope' => null,
]);
$this->logger->warning(
'[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',
// pulling directly from the token, just to avoid potential masking of the issue
['token_values' => $this->accessToken->getValues()],
);
}
$account->save();
// Association can be from an updated token so don't re-announce this.
if (
$account->wasRecentlyCreated
&& in_array($provider, SocialAccount::CRM_PROVIDERS, true)
&& $provider !== SocialAccount::PROVIDER_HUBSPOT
&& $providerUser->getId() !== null
) {
$crm = $user->team->crm;
$data = [
'crm_configuration_id' => $crm->id,
'log_notes' => Profile::LOG_NOTE_ENHANCED,
];
$crmProfile = $user->crmProfile()->where([
'crm_provider_id' => $providerUser->getId(),
])->first();
$user->crmProfile()->updateOrCreate([
'crm_provider_id' => $providerUser->getId(),
], $data);
// If updated, fire reconnected
if ($crmProfile !== null) {
$this->eventDispatcher->dispatch(new CrmAccountReconnected($account));
}
}
$this->eventDispatcher->dispatch(new SocialAccountConnected($account));
return $account;
}
public function integrate(string $provider, User $user, Team $team): void
{
if ($provider === SocialAccount::PROVIDER_SLACK) {
if (! isset($this->vendorValues['ok'])
|| $this->vendorValues['ok'] !== true
|| ! isset($this->vendorValues['token_type'])
|| $this->vendorValues['token_type'] !== 'bot'
) {
// code expects V2 token, which differs slightly from V1
throw new LogicException('Invalid token received from Slack OAuth v2 API');
}
$webhook = $this->vendorValues['incoming_webhook'];
$slackTeamId = $this->vendorValues['team']['id'];
$botData = [
'channel' => $webhook['channel'],
'channel_id' => $webhook['channel_id'],
'config_url' => $webhook['configuration_url'],
'webhook_url' => $webhook['url'],
'bot_user_id' => $this->vendorValues['bot_user_id'],
'bot_access_token' => $this->accessToken->getToken(),
];
$slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);
if ($slackBot->wasRecentlyCreated) {
// Send Slack notification.
$user->notify(new SlackBotAdded());
}
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);
$this->logger->info('[SocialAccountService] Fetching token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$account->refresh();
if (
! $forceRefresh
&& ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))
) {
$this->logger->info('[SocialAccountService] Token retrieved', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);
return $this->encryptedTokenManager->getAccessToken($account);
}
try {
$this->logger->info('[SocialAccountService] Token needs refreshing', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
return $this->refreshToken($account, $forceRefresh);
} catch (IdentityProviderException $exception) {
$responseBody = $exception->getResponseBody();
if ($responseBody instanceof Response) {
$responseBody = $responseBody->getBody();
}
if (is_object($responseBody) && method_exists($responseBody, '__toString')) {
$responseBody = $responseBody->__toString();
}
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'responseBody' => $responseBody,
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
} catch (SocialAccountTokenInvalidException $exception) {
$this->logger->error('[SocialAccountService] Cannot obtain token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception::class,
'errorMessage' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {
$this->logger->error('[SocialAccountService] Full refresh required', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
// Something terrible happened their token, they need to reconnect.
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
$this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));
}
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
}
}
public function refreshSocialAccountToken(SocialAccount $socialAccount): void
{
try {
$this->getToken($socialAccount);
} catch (Throwable $e) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $socialAccount->getId(),
'provider' => $socialAccount->getProviderName(),
'reason' => $e->getMessage(),
]);
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);
$newToken = null;
Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)
->block(8, function () use ($account, $forceRefresh, &$newToken): void {
try {
$account->refresh();
$token = $this->encryptedTokenManager->getAccessToken($account);
if (! $forceRefresh && $this->hasValidToken($account)) {
$newToken = $token;
return;
}
if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {
$this->logger->error('[SocialAccountService] Refresh token not found', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog(
$account,
self::TOKEN_STATE_REFRESH,
self::TOKEN_RESULT_FAILURE,
);
throw new SocialAccountTokenInvalidException(
'Refresh token is not set, re-connection required.',
);
}
$this->logger->info('[SocialAccountService] Refreshing token from provider', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),
'state' => $account->getState(),
]);
$newToken = $this->getProvider($account->provider)
->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
])
;
if ($newToken->getToken() === $token->getToken()) {
$this->logger->info('[SocialAccountService] Refreshed with an identical token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
}
} catch (ConnectException | RequestException $exception) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
// This usually occurs due to SSL errors.
throw new SocialAccountTokenInvalidException(
'Token could not be refreshed.',
$exception->getCode(),
$exception,
);
}
$account->provider_user_token = $newToken->getToken();
$account->expires = $newToken->getExpires();
$account->state = SocialAccount::STATE_CONNECTED;
if ($newToken->getRefreshToken()) {
$account->provider_refresh_token = $newToken->getRefreshToken();
$values = $newToken->getValues();
$account->refresh_token_expires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
$account->save();
});
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);
$this->logger->info('[SocialAccountService] Token refreshed', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'state' => $account->getState(),
]);
return $newToken;
}
/**
* @return string[]
*/
private function getAccessScope(string $provider): array
{
$scopes = [];
$providerScopes = config('services.' . $provider . '.scope');
if ($providerScopes) {
$scopes = preg_split('/\s+/', $providerScopes);
}
return $scopes;
}
/**
* @throws InvalidEnumException
*/
public function getAuthorizationOptions(string $provider): array
{
$scopes = ['scope' => $this->getAccessScope($provider)];
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
case SocialAccount::PROVIDER_SALESFORCE:
case SocialAccount::PROVIDER_HUBSPOT:
case SocialAccount::PROVIDER_OUTREACH:
case SocialAccount::PROVIDER_SALESLOFT:
case SocialAccount::PROVIDER_ZOOM_PHONE:
case SocialAccount::PROVIDER_PIPEDRIVE:
case SocialAccount::PROVIDER_SLACK:
case SocialAccount::PROVIDER_AIRCALL:
case SocialAccount::PROVIDER_BULLHORN:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_TELUS:
case SocialAccount::PROVIDER_DIALPAD:
case SocialAccount::PROVIDER_TALKDESK:
return $scopes;
case SocialAccount::PROVIDER_OFFICE:
return $scopes + [
'access_type' => 'offline',
];
case SocialAccount::PROVIDER_GOOGLE:
return $scopes + [
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'approval_prompt' => null,
];
default:
throw new InvalidEnumException();
}
}
private function tokenDoesNotExpire(SocialAccount $account): bool
{
return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);
}
private function hasValidToken(SocialAccount $account): bool
{
return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();
}
private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void
{
Datadog::increment('jiminny.access_token', 1, [
'provider' => $account->getProviderName(),
'state' => $state,
'result' => $result,
]);
}
private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),
];
}
private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
try {
$parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);
$number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);
} catch (NumberParseException) {
$number = null;
}
// Todo: this should check the `organization_id` matches the parent crm configuration.
return [
'country_code' => $this->countryCode,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),
'phone' => $number,
'crm_provider_id' => $rawUserData['organization_id'],
'crm_base_url' => $this->vendorValues['instance_url'],
];
}
/**
* Todo: this should check the `getHubId` matches the parent crm configuration.
*/
private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $providerUser->getHubId(),
'crm_base_url' => $providerUser->toArray()['hub_domain'],
];
}
/**
* Todo: this should check the `getCompanyId` matches the parent crm configuration.
*/
private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $rawUserData['data']['company_id'],
'crm_base_url' => '[URL_WITH_CREDENTIALS] ActivityProviderException
*/
private function mapDialpadUserData(DialpadResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
// They need to be Super Admin to access the Company APIs.
$this->logger->info('[Dialpad] User authenticated', $rawUserData);
if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Dialpad Super Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapAircallUserData(AircallResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
/**
* @throws ActivityProviderException
*/
private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array
{
if ($providerUser->toArray()['data']['team_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Team Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapBullhornUserData(): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
];
}
private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
}
Execute
Explain Plan...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Services;\n\n/**\n * @todo cleanup after #slack-oauth-v2\n */\n\nuse AdamPaterson\\OAuth2\\Client\\Provider\\SlackResourceOwner;\nuse Chadhutchins\\OAuth2\\Client\\Provider\\Slack;\nuse ChaseConey\\LaravelDatadogHelper\\Datadog;\nuse Daniti\\OAuth2\\Client\\Provider\\Pipedrive;\nuse Daniti\\OAuth2\\Client\\Provider\\PipedriveResourceOwner;\nuse Exception;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpot;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpotResourceOwner;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Auth\\AuthenticationException;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Jiminny\\Component\\Encryption\\EncryptedTokenManager;\nuse Jiminny\\Events\\Users\\CrmAccountReconnected;\nuse Jiminny\\Events\\Users\\SocialAccountConnected;\nuse Jiminny\\Events\\Users\\SocialAccountDisconnected;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\InvalidEnumException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Notifications\\SlackBotAdded;\nuse Jiminny\\OAuth2\\Client\\Provider\\Aircall;\nuse Jiminny\\OAuth2\\Client\\Provider\\AircallResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Bullhorn;\nuse Jiminny\\OAuth2\\Client\\Provider\\Dialpad;\nuse Jiminny\\OAuth2\\Client\\Provider\\DialpadResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Salesloft;\nuse Jiminny\\OAuth2\\Client\\Provider\\SalesloftResourceOwner;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\Talkdesk;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\TalkdeskResourceOwner;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\Zoom;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\ZoomResourceOwner;\nuse Jiminny\\Services\\OAuth2\\Provider\\BasicAuth;\nuse Jiminny\\Services\\OAuth2\\Provider\\Outreach;\nuse JsonException;\nuse League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider;\nuse League\\OAuth2\\Client\\Provider\\AbstractProvider;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Provider\\Google;\nuse League\\OAuth2\\Client\\Provider\\GoogleUser;\nuse League\\OAuth2\\Client\\Provider\\LinkedIn;\nuse League\\OAuth2\\Client\\Provider\\LinkedInResourceOwner;\nuse League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse League\\OAuth2\\Client\\Token\\AccessTokenInterface;\nuse libphonenumber\\NumberParseException;\nuse libphonenumber\\PhoneNumberFormat;\nuse libphonenumber\\PhoneNumberUtil;\nuse LogicException;\nuse Psr\\Log\\LoggerInterface;\nuse Random\\RandomException;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\Salesforce;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\SalesforceResourceOwner;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\nuse TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner;\nuse Throwable;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingCentral;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingcentralResourceOwner;\n\nclass SocialAccountService\n{\n /**\n * Get a fresh tokens 5 minutes before it expires\n * That should minimise the number of failed requests due to expired token\n * for long-running jobs that reuse the same token for pulling lots of data.\n */\n private const int REFRESH_OFFSET_MIN = 5;\n\n private const string TOKEN_STATE_FETCH = 'fetch';\n private const string TOKEN_STATE_REFRESH = 'refresh';\n private const string TOKEN_RESULT_ATTEMPT = 'attempt';\n private const string TOKEN_RESULT_SUCCESS = 'success';\n private const string TOKEN_RESULT_FAILURE = 'failure';\n\n private ?AccessTokenInterface $accessToken = null;\n private ?string $token = null;\n private ?string $refreshToken = null;\n private ?int $expires = null;\n private ?string $countryCode = null;\n private ?string $timezone = null;\n private ?array $vendorValues = null;\n\n private ?int $refreshTokenExpires = null;\n\n public function __construct(\n private readonly EncryptedTokenManager $encryptedTokenManager,\n private readonly LoggerInterface $logger,\n private readonly PhoneNumberUtil $phoneNumberUtil,\n private readonly Dispatcher $eventDispatcher,\n ) {\n }\n\n public function setVendorValues(array $values): void\n {\n $this->vendorValues = $values;\n }\n\n public function setAccessToken(AccessTokenInterface $accessToken): void\n {\n $this->accessToken = $accessToken;\n // Todo: Also set these other params from this token e.g. refreshToken\n }\n\n public function setToken(?string $token): void\n {\n $this->token = $token;\n }\n\n public function setRefreshToken(?string $refreshToken): void\n {\n $this->refreshToken = $refreshToken;\n }\n\n public function setCountryCode(string $countryCode): void\n {\n $this->countryCode = $countryCode;\n }\n\n public function setTimezone(string $timezone): void\n {\n $this->timezone = $timezone;\n }\n\n public function setExpires(?int $expiry): void\n {\n $this->expires = $expiry;\n }\n\n public function setRefreshTokenExpires(array $values): void\n {\n $this->refreshTokenExpires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getProvider(string $provider): AbstractProvider\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n return new LinkedIn(config('services.linkedin'));\n\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n $socialProvider = new LinkedIn(config('services.linkedin-conference'));\n $socialProvider->withFields([\n 'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',\n ]);\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_SALESFORCE:\n return new Salesforce(config('services.salesforce'));\n\n case SocialAccount::PROVIDER_GOOGLE:\n return new Google(config('services.google'));\n\n case SocialAccount::PROVIDER_SLACK:\n return new Slack(config('services.slack'));\n\n case SocialAccount::PROVIDER_OFFICE:\n $config = config('services.office');\n\n // Convert string scope to array format expected by Azure provider\n if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {\n $config['scopes'] = array_filter(preg_split('/\\s+/', trim($config['scope'])));\n unset($config['scope']);\n }\n\n $socialProvider = new Azure($config);\n $socialProvider->urlAPI = 'https://graph.microsoft.com/v1.0/';\n $socialProvider->API_VERSION = '1.0';\n $socialProvider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_HUBSPOT:\n return new HubSpot(config('services.hubspot'));\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n return new Pipedrive(config('services.pipedrive'));\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n return new Zoom(config('services.zoom-phone'));\n\n case SocialAccount::PROVIDER_OUTREACH:\n return new Outreach(config('services.outreach'));\n\n case SocialAccount::PROVIDER_SALESLOFT:\n return new Salesloft(config('services.salesloft'));\n\n case SocialAccount::PROVIDER_AIRCALL:\n return new Aircall(config('services.aircall'));\n\n case SocialAccount::PROVIDER_DIALPAD:\n return new Dialpad(config('services.dialpad'));\n\n case SocialAccount::PROVIDER_GONG:\n return new BasicAuth(config('services.gong'));\n\n case SocialAccount::PROVIDER_CLOSE:\n return new BasicAuth(config('services.close'));\n\n case SocialAccount::PROVIDER_AVAYA:\n // Avaya is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.avaya'));\n\n case SocialAccount::PROVIDER_TELUS:\n // Telus is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.telus'));\n\n case SocialAccount::PROVIDER_RINGCENTRAL:\n return new RingCentral(config('services.ringcentral'));\n\n case SocialAccount::PROVIDER_BULLHORN:\n return new Bullhorn(config('services.bullhorn'));\n\n case SocialAccount::PROVIDER_TALKDESK:\n return new Talkdesk(config('services.talkdesk'), [\n // Automatically concatenate Basic token to AuthToken requests\n 'optionProvider' => new HttpBasicAuthOptionProvider(),\n ]);\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n /**\n *\n *\n * @throws Exception\n */\n public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n /** @var LinkedInResourceOwner $providerUser */\n return $this->mapLinkedInUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESFORCE:\n /** @var SalesforceResourceOwner $providerUser */\n return $this->mapSalesforceUserData($providerUser);\n\n case SocialAccount::PROVIDER_HUBSPOT:\n /** @var HubSpotResourceOwner $providerUser */\n return $this->mapHubSpotUserData($providerUser);\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n /** @var PipedriveResourceOwner $providerUser */\n return $this->mapPipedriveUserData($providerUser);\n\n case SocialAccount::PROVIDER_GOOGLE:\n /** @var GoogleUser $providerUser */\n return $this->mapGoogleUserData($providerUser);\n\n case SocialAccount::PROVIDER_SLACK:\n /** @var SlackResourceOwner $providerUser */\n return $this->mapSlackUserData($providerUser);\n\n case SocialAccount::PROVIDER_OFFICE:\n /** @var AzureResourceOwner $providerUser */\n return $this->mapOfficeUserData($providerUser);\n\n case SocialAccount::PROVIDER_OUTREACH:\n return $this->mapOutreachUserData($providerUser);\n\n case SocialAccount::PROVIDER_DIALPAD:\n /** @var DialpadResourceOwner $providerUser*/\n return $this->mapDialpadUserData($providerUser);\n\n case SocialAccount::PROVIDER_AIRCALL:\n /** @var AircallResourceOwner $providerUser */\n return $this->mapAircallUserData($providerUser);\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n /** @var ZoomResourceOwner $providerUser */\n return $this->mapZoomPhoneUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESLOFT:\n /** @var SalesloftResourceOwner $providerUser */\n return $this->mapSalesloftUserData($providerUser);\n\n case SocialAccount::PROVIDER_BULLHORN:\n return $this->mapBullhornUserData();\n\n case SocialAccount::PROVIDER_TALKDESK:\n /** @var TalkdeskResourceOwner $providerUser */\n return $this->mapTalkdeskUserData($providerUser);\n\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_TELUS:\n /** @var RingcentralResourceOwner $providerUser */\n return $this->mapRingCentralUserData($providerUser);\n default:\n throw new InvalidEnumException('Unknown provider.');\n }\n }\n\n /**\n * Returns a new random string to use as the state parameter in an\n * authorization flow.\n *\n * @param int $length Length of the random string to be generated.\n *\n * @throws RandomException\n */\n public function getRandomState(int $length = 32): string\n {\n // Converting bytes to hex will always double length. Hence, we can reduce\n // the amount of bytes by half to produce the correct length.\n return bin2hex(random_bytes($length / 2));\n }\n\n private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount\n {\n return SocialAccount::where([\n 'provider' => $provider,\n 'provider_user_id' => $providerUser->getId(),\n ])->first();\n }\n\n /**\n * Based on the provider data, try to match to a sociable entity based on email.\n * If a match is made, create the social account under that entity.\n *\n * @throws AuthenticationException\n */\n public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User\n {\n $account = $this->getAssociation($provider, $providerUser);\n if ($account !== null && $account->hasUser()) {\n return $account->getUser();\n }\n $userData = $this->mapUserData($provider, $providerUser);\n\n // Check if we have an actual user with this email.\n /** @var User|null $user */\n $user = User::where('email', $userData['email'])->first();\n\n // If the user is trying to connect to LinkedIn, don't allow this.\n // Todo: have an interstitial page to perform 2FA to connect.\n if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {\n throw new AuthenticationException(\n 'Sorry, you\\'ll need to login through your Jiminny account to access the Conference.',\n );\n }\n\n return $user;\n }\n\n /**\n * @throws JsonException\n */\n public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount\n {\n /** @var SocialAccount $account */\n $account = $user->socialAccounts()->firstOrNew([\n 'provider' => $provider,\n ]);\n\n $account->fill([\n 'provider_user_id' => $providerUser->getId(),\n 'provider_user_token' => $this->token,\n 'expires' => $this->expires,\n 'state' => SocialAccount::STATE_CONNECTED,\n 'retry_after' => null,\n ]);\n\n // This is an optional parameter, don't overwrite the existing one with null if we don't get it.\n if ($this->refreshToken) {\n $account->fill([\n 'provider_refresh_token' => $this->refreshToken,\n 'refresh_token_expires' => $this->refreshTokenExpires,\n ]);\n }\n\n if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {\n $account->fill([\n 'auth_scope' => is_scalar($this->vendorValues['scope'])\n ? $this->vendorValues['scope']\n : json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),\n ]);\n } else {\n $account->fill([\n 'auth_scope' => null,\n ]);\n\n $this->logger->warning(\n '[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',\n // pulling directly from the token, just to avoid potential masking of the issue\n ['token_values' => $this->accessToken->getValues()],\n );\n }\n\n $account->save();\n\n // Association can be from an updated token so don't re-announce this.\n if (\n $account->wasRecentlyCreated\n && in_array($provider, SocialAccount::CRM_PROVIDERS, true)\n && $provider !== SocialAccount::PROVIDER_HUBSPOT\n && $providerUser->getId() !== null\n ) {\n $crm = $user->team->crm;\n $data = [\n 'crm_configuration_id' => $crm->id,\n 'log_notes' => Profile::LOG_NOTE_ENHANCED,\n ];\n\n $crmProfile = $user->crmProfile()->where([\n 'crm_provider_id' => $providerUser->getId(),\n ])->first();\n\n $user->crmProfile()->updateOrCreate([\n 'crm_provider_id' => $providerUser->getId(),\n ], $data);\n\n // If updated, fire reconnected\n if ($crmProfile !== null) {\n $this->eventDispatcher->dispatch(new CrmAccountReconnected($account));\n }\n }\n\n $this->eventDispatcher->dispatch(new SocialAccountConnected($account));\n\n return $account;\n }\n\n public function integrate(string $provider, User $user, Team $team): void\n {\n if ($provider === SocialAccount::PROVIDER_SLACK) {\n if (! isset($this->vendorValues['ok'])\n || $this->vendorValues['ok'] !== true\n || ! isset($this->vendorValues['token_type'])\n || $this->vendorValues['token_type'] !== 'bot'\n ) {\n // code expects V2 token, which differs slightly from V1\n throw new LogicException('Invalid token received from Slack OAuth v2 API');\n }\n\n $webhook = $this->vendorValues['incoming_webhook'];\n\n $slackTeamId = $this->vendorValues['team']['id'];\n\n $botData = [\n 'channel' => $webhook['channel'],\n 'channel_id' => $webhook['channel_id'],\n 'config_url' => $webhook['configuration_url'],\n 'webhook_url' => $webhook['url'],\n 'bot_user_id' => $this->vendorValues['bot_user_id'],\n 'bot_access_token' => $this->accessToken->getToken(),\n ];\n\n $slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);\n\n if ($slackBot->wasRecentlyCreated) {\n // Send Slack notification.\n $user->notify(new SlackBotAdded());\n }\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);\n\n $this->logger->info('[SocialAccountService] Fetching token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $account->refresh();\n\n if (\n ! $forceRefresh\n && ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))\n ) {\n $this->logger->info('[SocialAccountService] Token retrieved', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);\n\n return $this->encryptedTokenManager->getAccessToken($account);\n }\n\n try {\n $this->logger->info('[SocialAccountService] Token needs refreshing', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n return $this->refreshToken($account, $forceRefresh);\n } catch (IdentityProviderException $exception) {\n $responseBody = $exception->getResponseBody();\n\n if ($responseBody instanceof Response) {\n $responseBody = $responseBody->getBody();\n }\n\n if (is_object($responseBody) && method_exists($responseBody, '__toString')) {\n $responseBody = $responseBody->__toString();\n }\n\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'responseBody' => $responseBody,\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n } catch (SocialAccountTokenInvalidException $exception) {\n $this->logger->error('[SocialAccountService] Cannot obtain token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception::class,\n 'errorMessage' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {\n $this->logger->error('[SocialAccountService] Full refresh required', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n // Something terrible happened their token, they need to reconnect.\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n $this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));\n }\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n }\n }\n\n public function refreshSocialAccountToken(SocialAccount $socialAccount): void\n {\n try {\n $this->getToken($socialAccount);\n } catch (Throwable $e) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $socialAccount->getId(),\n 'provider' => $socialAccount->getProviderName(),\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);\n\n $newToken = null;\n\n Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)\n ->block(8, function () use ($account, $forceRefresh, &$newToken): void {\n try {\n $account->refresh();\n $token = $this->encryptedTokenManager->getAccessToken($account);\n\n if (! $forceRefresh && $this->hasValidToken($account)) {\n $newToken = $token;\n\n return;\n }\n\n if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {\n $this->logger->error('[SocialAccountService] Refresh token not found', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog(\n $account,\n self::TOKEN_STATE_REFRESH,\n self::TOKEN_RESULT_FAILURE,\n );\n\n throw new SocialAccountTokenInvalidException(\n 'Refresh token is not set, re-connection required.',\n );\n }\n\n $this->logger->info('[SocialAccountService] Refreshing token from provider', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),\n 'state' => $account->getState(),\n ]);\n\n $newToken = $this->getProvider($account->provider)\n ->getAccessToken('refresh_token', [\n 'refresh_token' => $token->getRefreshToken(),\n ])\n ;\n\n if ($newToken->getToken() === $token->getToken()) {\n $this->logger->info('[SocialAccountService] Refreshed with an identical token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n }\n } catch (ConnectException | RequestException $exception) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n // This usually occurs due to SSL errors.\n throw new SocialAccountTokenInvalidException(\n 'Token could not be refreshed.',\n $exception->getCode(),\n $exception,\n );\n }\n\n $account->provider_user_token = $newToken->getToken();\n $account->expires = $newToken->getExpires();\n $account->state = SocialAccount::STATE_CONNECTED;\n\n if ($newToken->getRefreshToken()) {\n $account->provider_refresh_token = $newToken->getRefreshToken();\n $values = $newToken->getValues();\n $account->refresh_token_expires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n $account->save();\n });\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);\n\n $this->logger->info('[SocialAccountService] Token refreshed', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'state' => $account->getState(),\n ]);\n\n return $newToken;\n }\n\n /**\n * @return string[]\n */\n private function getAccessScope(string $provider): array\n {\n $scopes = [];\n $providerScopes = config('services.' . $provider . '.scope');\n\n if ($providerScopes) {\n $scopes = preg_split('/\\s+/', $providerScopes);\n }\n\n return $scopes;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getAuthorizationOptions(string $provider): array\n {\n $scopes = ['scope' => $this->getAccessScope($provider)];\n\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n case SocialAccount::PROVIDER_SALESFORCE:\n case SocialAccount::PROVIDER_HUBSPOT:\n case SocialAccount::PROVIDER_OUTREACH:\n case SocialAccount::PROVIDER_SALESLOFT:\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n case SocialAccount::PROVIDER_PIPEDRIVE:\n case SocialAccount::PROVIDER_SLACK:\n case SocialAccount::PROVIDER_AIRCALL:\n case SocialAccount::PROVIDER_BULLHORN:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_TELUS:\n case SocialAccount::PROVIDER_DIALPAD:\n case SocialAccount::PROVIDER_TALKDESK:\n return $scopes;\n\n case SocialAccount::PROVIDER_OFFICE:\n return $scopes + [\n 'access_type' => 'offline',\n ];\n\n case SocialAccount::PROVIDER_GOOGLE:\n return $scopes + [\n 'access_type' => 'offline',\n 'include_granted_scopes' => 'true',\n 'approval_prompt' => null,\n ];\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n private function tokenDoesNotExpire(SocialAccount $account): bool\n {\n return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);\n }\n\n private function hasValidToken(SocialAccount $account): bool\n {\n return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();\n }\n\n private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void\n {\n Datadog::increment('jiminny.access_token', 1, [\n 'provider' => $account->getProviderName(),\n 'state' => $state,\n 'result' => $result,\n ]);\n }\n\n private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),\n ];\n }\n\n private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n try {\n $parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);\n $number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);\n } catch (NumberParseException) {\n $number = null;\n }\n\n // Todo: this should check the `organization_id` matches the parent crm configuration.\n\n return [\n 'country_code' => $this->countryCode,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),\n 'phone' => $number,\n 'crm_provider_id' => $rawUserData['organization_id'],\n 'crm_base_url' => $this->vendorValues['instance_url'],\n ];\n }\n\n /**\n * Todo: this should check the `getHubId` matches the parent crm configuration.\n */\n private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array\n {\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $providerUser->getHubId(),\n 'crm_base_url' => $providerUser->toArray()['hub_domain'],\n ];\n }\n\n /**\n * Todo: this should check the `getCompanyId` matches the parent crm configuration.\n */\n private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $rawUserData['data']['company_id'],\n 'crm_base_url' => 'https://' . $rawUserData['data']['company_domain'] . '.pipedrive.com',\n ];\n }\n\n private function mapGoogleUserData(GoogleUser $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($providerUser->getEmail()),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapSlackUserData(SlackResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getRealName(),\n ];\n }\n\n private function mapOfficeUserData(AzureResourceOwner $providerUser): array\n {\n $email = $providerUser->getUpn() ?? $providerUser->claim('email');\n\n $this->logger->info('[Office] User authenticated', $providerUser->toArray());\n\n $name = $providerUser->claim('name') ??\n $providerUser->getFirstName() . ' ' . $providerUser->getLastName();\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($email),\n 'name' => $name,\n ];\n }\n\n private function mapOutreachUserData(ResourceOwnerInterface $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n $socialProvider = $this->getProvider(SocialAccount::PROVIDER_OUTREACH);\n $url = 'https://api.outreach.io/api/v2/profiles/';\n\n try {\n $request = $socialProvider->getAuthenticatedRequest(\n 'get',\n $url . $rawUserData['meta']['user']['id'],\n $this->accessToken,\n );\n\n $response = $socialProvider->getParsedResponse($request);\n\n $this->logger->info('[Outreach] User authenticated', $response);\n } catch (Exception) {\n //Just ignore\n }\n\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapDialpadUserData(DialpadResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n // They need to be Super Admin to access the Company APIs.\n $this->logger->info('[Dialpad] User authenticated', $rawUserData);\n\n if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Dialpad Super Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapAircallUserData(AircallResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array\n {\n if ($providerUser->toArray()['data']['team_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Team Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapBullhornUserData(): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n\n private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Services;\n\n/**\n * @todo cleanup after #slack-oauth-v2\n */\n\nuse AdamPaterson\\OAuth2\\Client\\Provider\\SlackResourceOwner;\nuse Chadhutchins\\OAuth2\\Client\\Provider\\Slack;\nuse ChaseConey\\LaravelDatadogHelper\\Datadog;\nuse Daniti\\OAuth2\\Client\\Provider\\Pipedrive;\nuse Daniti\\OAuth2\\Client\\Provider\\PipedriveResourceOwner;\nuse Exception;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpot;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpotResourceOwner;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Auth\\AuthenticationException;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Jiminny\\Component\\Encryption\\EncryptedTokenManager;\nuse Jiminny\\Events\\Users\\CrmAccountReconnected;\nuse Jiminny\\Events\\Users\\SocialAccountConnected;\nuse Jiminny\\Events\\Users\\SocialAccountDisconnected;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\InvalidEnumException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Notifications\\SlackBotAdded;\nuse Jiminny\\OAuth2\\Client\\Provider\\Aircall;\nuse Jiminny\\OAuth2\\Client\\Provider\\AircallResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Bullhorn;\nuse Jiminny\\OAuth2\\Client\\Provider\\Dialpad;\nuse Jiminny\\OAuth2\\Client\\Provider\\DialpadResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Salesloft;\nuse Jiminny\\OAuth2\\Client\\Provider\\SalesloftResourceOwner;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\Talkdesk;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\TalkdeskResourceOwner;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\Zoom;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\ZoomResourceOwner;\nuse Jiminny\\Services\\OAuth2\\Provider\\BasicAuth;\nuse Jiminny\\Services\\OAuth2\\Provider\\Outreach;\nuse JsonException;\nuse League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider;\nuse League\\OAuth2\\Client\\Provider\\AbstractProvider;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Provider\\Google;\nuse League\\OAuth2\\Client\\Provider\\GoogleUser;\nuse League\\OAuth2\\Client\\Provider\\LinkedIn;\nuse League\\OAuth2\\Client\\Provider\\LinkedInResourceOwner;\nuse League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse League\\OAuth2\\Client\\Token\\AccessTokenInterface;\nuse libphonenumber\\NumberParseException;\nuse libphonenumber\\PhoneNumberFormat;\nuse libphonenumber\\PhoneNumberUtil;\nuse LogicException;\nuse Psr\\Log\\LoggerInterface;\nuse Random\\RandomException;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\Salesforce;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\SalesforceResourceOwner;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\nuse TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner;\nuse Throwable;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingCentral;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingcentralResourceOwner;\n\nclass SocialAccountService\n{\n /**\n * Get a fresh tokens 5 minutes before it expires\n * That should minimise the number of failed requests due to expired token\n * for long-running jobs that reuse the same token for pulling lots of data.\n */\n private const int REFRESH_OFFSET_MIN = 5;\n\n private const string TOKEN_STATE_FETCH = 'fetch';\n private const string TOKEN_STATE_REFRESH = 'refresh';\n private const string TOKEN_RESULT_ATTEMPT = 'attempt';\n private const string TOKEN_RESULT_SUCCESS = 'success';\n private const string TOKEN_RESULT_FAILURE = 'failure';\n\n private ?AccessTokenInterface $accessToken = null;\n private ?string $token = null;\n private ?string $refreshToken = null;\n private ?int $expires = null;\n private ?string $countryCode = null;\n private ?string $timezone = null;\n private ?array $vendorValues = null;\n\n private ?int $refreshTokenExpires = null;\n\n public function __construct(\n private readonly EncryptedTokenManager $encryptedTokenManager,\n private readonly LoggerInterface $logger,\n private readonly PhoneNumberUtil $phoneNumberUtil,\n private readonly Dispatcher $eventDispatcher,\n ) {\n }\n\n public function setVendorValues(array $values): void\n {\n $this->vendorValues = $values;\n }\n\n public function setAccessToken(AccessTokenInterface $accessToken): void\n {\n $this->accessToken = $accessToken;\n // Todo: Also set these other params from this token e.g. refreshToken\n }\n\n public function setToken(?string $token): void\n {\n $this->token = $token;\n }\n\n public function setRefreshToken(?string $refreshToken): void\n {\n $this->refreshToken = $refreshToken;\n }\n\n public function setCountryCode(string $countryCode): void\n {\n $this->countryCode = $countryCode;\n }\n\n public function setTimezone(string $timezone): void\n {\n $this->timezone = $timezone;\n }\n\n public function setExpires(?int $expiry): void\n {\n $this->expires = $expiry;\n }\n\n public function setRefreshTokenExpires(array $values): void\n {\n $this->refreshTokenExpires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getProvider(string $provider): AbstractProvider\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n return new LinkedIn(config('services.linkedin'));\n\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n $socialProvider = new LinkedIn(config('services.linkedin-conference'));\n $socialProvider->withFields([\n 'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',\n ]);\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_SALESFORCE:\n return new Salesforce(config('services.salesforce'));\n\n case SocialAccount::PROVIDER_GOOGLE:\n return new Google(config('services.google'));\n\n case SocialAccount::PROVIDER_SLACK:\n return new Slack(config('services.slack'));\n\n case SocialAccount::PROVIDER_OFFICE:\n $config = config('services.office');\n\n // Convert string scope to array format expected by Azure provider\n if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {\n $config['scopes'] = array_filter(preg_split('/\\s+/', trim($config['scope'])));\n unset($config['scope']);\n }\n\n $socialProvider = new Azure($config);\n $socialProvider->urlAPI = 'https://graph.microsoft.com/v1.0/';\n $socialProvider->API_VERSION = '1.0';\n $socialProvider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_HUBSPOT:\n return new HubSpot(config('services.hubspot'));\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n return new Pipedrive(config('services.pipedrive'));\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n return new Zoom(config('services.zoom-phone'));\n\n case SocialAccount::PROVIDER_OUTREACH:\n return new Outreach(config('services.outreach'));\n\n case SocialAccount::PROVIDER_SALESLOFT:\n return new Salesloft(config('services.salesloft'));\n\n case SocialAccount::PROVIDER_AIRCALL:\n return new Aircall(config('services.aircall'));\n\n case SocialAccount::PROVIDER_DIALPAD:\n return new Dialpad(config('services.dialpad'));\n\n case SocialAccount::PROVIDER_GONG:\n return new BasicAuth(config('services.gong'));\n\n case SocialAccount::PROVIDER_CLOSE:\n return new BasicAuth(config('services.close'));\n\n case SocialAccount::PROVIDER_AVAYA:\n // Avaya is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.avaya'));\n\n case SocialAccount::PROVIDER_TELUS:\n // Telus is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.telus'));\n\n case SocialAccount::PROVIDER_RINGCENTRAL:\n return new RingCentral(config('services.ringcentral'));\n\n case SocialAccount::PROVIDER_BULLHORN:\n return new Bullhorn(config('services.bullhorn'));\n\n case SocialAccount::PROVIDER_TALKDESK:\n return new Talkdesk(config('services.talkdesk'), [\n // Automatically concatenate Basic token to AuthToken requests\n 'optionProvider' => new HttpBasicAuthOptionProvider(),\n ]);\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n /**\n *\n *\n * @throws Exception\n */\n public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n /** @var LinkedInResourceOwner $providerUser */\n return $this->mapLinkedInUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESFORCE:\n /** @var SalesforceResourceOwner $providerUser */\n return $this->mapSalesforceUserData($providerUser);\n\n case SocialAccount::PROVIDER_HUBSPOT:\n /** @var HubSpotResourceOwner $providerUser */\n return $this->mapHubSpotUserData($providerUser);\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n /** @var PipedriveResourceOwner $providerUser */\n return $this->mapPipedriveUserData($providerUser);\n\n case SocialAccount::PROVIDER_GOOGLE:\n /** @var GoogleUser $providerUser */\n return $this->mapGoogleUserData($providerUser);\n\n case SocialAccount::PROVIDER_SLACK:\n /** @var SlackResourceOwner $providerUser */\n return $this->mapSlackUserData($providerUser);\n\n case SocialAccount::PROVIDER_OFFICE:\n /** @var AzureResourceOwner $providerUser */\n return $this->mapOfficeUserData($providerUser);\n\n case SocialAccount::PROVIDER_OUTREACH:\n return $this->mapOutreachUserData($providerUser);\n\n case SocialAccount::PROVIDER_DIALPAD:\n /** @var DialpadResourceOwner $providerUser*/\n return $this->mapDialpadUserData($providerUser);\n\n case SocialAccount::PROVIDER_AIRCALL:\n /** @var AircallResourceOwner $providerUser */\n return $this->mapAircallUserData($providerUser);\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n /** @var ZoomResourceOwner $providerUser */\n return $this->mapZoomPhoneUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESLOFT:\n /** @var SalesloftResourceOwner $providerUser */\n return $this->mapSalesloftUserData($providerUser);\n\n case SocialAccount::PROVIDER_BULLHORN:\n return $this->mapBullhornUserData();\n\n case SocialAccount::PROVIDER_TALKDESK:\n /** @var TalkdeskResourceOwner $providerUser */\n return $this->mapTalkdeskUserData($providerUser);\n\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_TELUS:\n /** @var RingcentralResourceOwner $providerUser */\n return $this->mapRingCentralUserData($providerUser);\n default:\n throw new InvalidEnumException('Unknown provider.');\n }\n }\n\n /**\n * Returns a new random string to use as the state parameter in an\n * authorization flow.\n *\n * @param int $length Length of the random string to be generated.\n *\n * @throws RandomException\n */\n public function getRandomState(int $length = 32): string\n {\n // Converting bytes to hex will always double length. Hence, we can reduce\n // the amount of bytes by half to produce the correct length.\n return bin2hex(random_bytes($length / 2));\n }\n\n private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount\n {\n return SocialAccount::where([\n 'provider' => $provider,\n 'provider_user_id' => $providerUser->getId(),\n ])->first();\n }\n\n /**\n * Based on the provider data, try to match to a sociable entity based on email.\n * If a match is made, create the social account under that entity.\n *\n * @throws AuthenticationException\n */\n public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User\n {\n $account = $this->getAssociation($provider, $providerUser);\n if ($account !== null && $account->hasUser()) {\n return $account->getUser();\n }\n $userData = $this->mapUserData($provider, $providerUser);\n\n // Check if we have an actual user with this email.\n /** @var User|null $user */\n $user = User::where('email', $userData['email'])->first();\n\n // If the user is trying to connect to LinkedIn, don't allow this.\n // Todo: have an interstitial page to perform 2FA to connect.\n if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {\n throw new AuthenticationException(\n 'Sorry, you\\'ll need to login through your Jiminny account to access the Conference.',\n );\n }\n\n return $user;\n }\n\n /**\n * @throws JsonException\n */\n public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount\n {\n /** @var SocialAccount $account */\n $account = $user->socialAccounts()->firstOrNew([\n 'provider' => $provider,\n ]);\n\n $account->fill([\n 'provider_user_id' => $providerUser->getId(),\n 'provider_user_token' => $this->token,\n 'expires' => $this->expires,\n 'state' => SocialAccount::STATE_CONNECTED,\n 'retry_after' => null,\n ]);\n\n // This is an optional parameter, don't overwrite the existing one with null if we don't get it.\n if ($this->refreshToken) {\n $account->fill([\n 'provider_refresh_token' => $this->refreshToken,\n 'refresh_token_expires' => $this->refreshTokenExpires,\n ]);\n }\n\n if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {\n $account->fill([\n 'auth_scope' => is_scalar($this->vendorValues['scope'])\n ? $this->vendorValues['scope']\n : json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),\n ]);\n } else {\n $account->fill([\n 'auth_scope' => null,\n ]);\n\n $this->logger->warning(\n '[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',\n // pulling directly from the token, just to avoid potential masking of the issue\n ['token_values' => $this->accessToken->getValues()],\n );\n }\n\n $account->save();\n\n // Association can be from an updated token so don't re-announce this.\n if (\n $account->wasRecentlyCreated\n && in_array($provider, SocialAccount::CRM_PROVIDERS, true)\n && $provider !== SocialAccount::PROVIDER_HUBSPOT\n && $providerUser->getId() !== null\n ) {\n $crm = $user->team->crm;\n $data = [\n 'crm_configuration_id' => $crm->id,\n 'log_notes' => Profile::LOG_NOTE_ENHANCED,\n ];\n\n $crmProfile = $user->crmProfile()->where([\n 'crm_provider_id' => $providerUser->getId(),\n ])->first();\n\n $user->crmProfile()->updateOrCreate([\n 'crm_provider_id' => $providerUser->getId(),\n ], $data);\n\n // If updated, fire reconnected\n if ($crmProfile !== null) {\n $this->eventDispatcher->dispatch(new CrmAccountReconnected($account));\n }\n }\n\n $this->eventDispatcher->dispatch(new SocialAccountConnected($account));\n\n return $account;\n }\n\n public function integrate(string $provider, User $user, Team $team): void\n {\n if ($provider === SocialAccount::PROVIDER_SLACK) {\n if (! isset($this->vendorValues['ok'])\n || $this->vendorValues['ok'] !== true\n || ! isset($this->vendorValues['token_type'])\n || $this->vendorValues['token_type'] !== 'bot'\n ) {\n // code expects V2 token, which differs slightly from V1\n throw new LogicException('Invalid token received from Slack OAuth v2 API');\n }\n\n $webhook = $this->vendorValues['incoming_webhook'];\n\n $slackTeamId = $this->vendorValues['team']['id'];\n\n $botData = [\n 'channel' => $webhook['channel'],\n 'channel_id' => $webhook['channel_id'],\n 'config_url' => $webhook['configuration_url'],\n 'webhook_url' => $webhook['url'],\n 'bot_user_id' => $this->vendorValues['bot_user_id'],\n 'bot_access_token' => $this->accessToken->getToken(),\n ];\n\n $slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);\n\n if ($slackBot->wasRecentlyCreated) {\n // Send Slack notification.\n $user->notify(new SlackBotAdded());\n }\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);\n\n $this->logger->info('[SocialAccountService] Fetching token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $account->refresh();\n\n if (\n ! $forceRefresh\n && ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))\n ) {\n $this->logger->info('[SocialAccountService] Token retrieved', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);\n\n return $this->encryptedTokenManager->getAccessToken($account);\n }\n\n try {\n $this->logger->info('[SocialAccountService] Token needs refreshing', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n return $this->refreshToken($account, $forceRefresh);\n } catch (IdentityProviderException $exception) {\n $responseBody = $exception->getResponseBody();\n\n if ($responseBody instanceof Response) {\n $responseBody = $responseBody->getBody();\n }\n\n if (is_object($responseBody) && method_exists($responseBody, '__toString')) {\n $responseBody = $responseBody->__toString();\n }\n\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'responseBody' => $responseBody,\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n } catch (SocialAccountTokenInvalidException $exception) {\n $this->logger->error('[SocialAccountService] Cannot obtain token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception::class,\n 'errorMessage' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {\n $this->logger->error('[SocialAccountService] Full refresh required', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n // Something terrible happened their token, they need to reconnect.\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n $this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));\n }\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n }\n }\n\n public function refreshSocialAccountToken(SocialAccount $socialAccount): void\n {\n try {\n $this->getToken($socialAccount);\n } catch (Throwable $e) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $socialAccount->getId(),\n 'provider' => $socialAccount->getProviderName(),\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);\n\n $newToken = null;\n\n Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)\n ->block(8, function () use ($account, $forceRefresh, &$newToken): void {\n try {\n $account->refresh();\n $token = $this->encryptedTokenManager->getAccessToken($account);\n\n if (! $forceRefresh && $this->hasValidToken($account)) {\n $newToken = $token;\n\n return;\n }\n\n if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {\n $this->logger->error('[SocialAccountService] Refresh token not found', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog(\n $account,\n self::TOKEN_STATE_REFRESH,\n self::TOKEN_RESULT_FAILURE,\n );\n\n throw new SocialAccountTokenInvalidException(\n 'Refresh token is not set, re-connection required.',\n );\n }\n\n $this->logger->info('[SocialAccountService] Refreshing token from provider', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),\n 'state' => $account->getState(),\n ]);\n\n $newToken = $this->getProvider($account->provider)\n ->getAccessToken('refresh_token', [\n 'refresh_token' => $token->getRefreshToken(),\n ])\n ;\n\n if ($newToken->getToken() === $token->getToken()) {\n $this->logger->info('[SocialAccountService] Refreshed with an identical token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n }\n } catch (ConnectException | RequestException $exception) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n // This usually occurs due to SSL errors.\n throw new SocialAccountTokenInvalidException(\n 'Token could not be refreshed.',\n $exception->getCode(),\n $exception,\n );\n }\n\n $account->provider_user_token = $newToken->getToken();\n $account->expires = $newToken->getExpires();\n $account->state = SocialAccount::STATE_CONNECTED;\n\n if ($newToken->getRefreshToken()) {\n $account->provider_refresh_token = $newToken->getRefreshToken();\n $values = $newToken->getValues();\n $account->refresh_token_expires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n $account->save();\n });\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);\n\n $this->logger->info('[SocialAccountService] Token refreshed', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'state' => $account->getState(),\n ]);\n\n return $newToken;\n }\n\n /**\n * @return string[]\n */\n private function getAccessScope(string $provider): array\n {\n $scopes = [];\n $providerScopes = config('services.' . $provider . '.scope');\n\n if ($providerScopes) {\n $scopes = preg_split('/\\s+/', $providerScopes);\n }\n\n return $scopes;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getAuthorizationOptions(string $provider): array\n {\n $scopes = ['scope' => $this->getAccessScope($provider)];\n\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n case SocialAccount::PROVIDER_SALESFORCE:\n case SocialAccount::PROVIDER_HUBSPOT:\n case SocialAccount::PROVIDER_OUTREACH:\n case SocialAccount::PROVIDER_SALESLOFT:\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n case SocialAccount::PROVIDER_PIPEDRIVE:\n case SocialAccount::PROVIDER_SLACK:\n case SocialAccount::PROVIDER_AIRCALL:\n case SocialAccount::PROVIDER_BULLHORN:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_TELUS:\n case SocialAccount::PROVIDER_DIALPAD:\n case SocialAccount::PROVIDER_TALKDESK:\n return $scopes;\n\n case SocialAccount::PROVIDER_OFFICE:\n return $scopes + [\n 'access_type' => 'offline',\n ];\n\n case SocialAccount::PROVIDER_GOOGLE:\n return $scopes + [\n 'access_type' => 'offline',\n 'include_granted_scopes' => 'true',\n 'approval_prompt' => null,\n ];\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n private function tokenDoesNotExpire(SocialAccount $account): bool\n {\n return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);\n }\n\n private function hasValidToken(SocialAccount $account): bool\n {\n return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();\n }\n\n private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void\n {\n Datadog::increment('jiminny.access_token', 1, [\n 'provider' => $account->getProviderName(),\n 'state' => $state,\n 'result' => $result,\n ]);\n }\n\n private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),\n ];\n }\n\n private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n try {\n $parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);\n $number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);\n } catch (NumberParseException) {\n $number = null;\n }\n\n // Todo: this should check the `organization_id` matches the parent crm configuration.\n\n return [\n 'country_code' => $this->countryCode,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),\n 'phone' => $number,\n 'crm_provider_id' => $rawUserData['organization_id'],\n 'crm_base_url' => $this->vendorValues['instance_url'],\n ];\n }\n\n /**\n * Todo: this should check the `getHubId` matches the parent crm configuration.\n */\n private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array\n {\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $providerUser->getHubId(),\n 'crm_base_url' => $providerUser->toArray()['hub_domain'],\n ];\n }\n\n /**\n * Todo: this should check the `getCompanyId` matches the parent crm configuration.\n */\n private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $rawUserData['data']['company_id'],\n 'crm_base_url' => 'https://' . $rawUserData['data']['company_domain'] . '.pipedrive.com',\n ];\n }\n\n private function mapGoogleUserData(GoogleUser $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($providerUser->getEmail()),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapSlackUserData(SlackResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getRealName(),\n ];\n }\n\n private function mapOfficeUserData(AzureResourceOwner $providerUser): array\n {\n $email = $providerUser->getUpn() ?? $providerUser->claim('email');\n\n $this->logger->info('[Office] User authenticated', $providerUser->toArray());\n\n $name = $providerUser->claim('name') ??\n $providerUser->getFirstName() . ' ' . $providerUser->getLastName();\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($email),\n 'name' => $name,\n ];\n }\n\n private function mapOutreachUserData(ResourceOwnerInterface $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n $socialProvider = $this->getProvider(SocialAccount::PROVIDER_OUTREACH);\n $url = 'https://api.outreach.io/api/v2/profiles/';\n\n try {\n $request = $socialProvider->getAuthenticatedRequest(\n 'get',\n $url . $rawUserData['meta']['user']['id'],\n $this->accessToken,\n );\n\n $response = $socialProvider->getParsedResponse($request);\n\n $this->logger->info('[Outreach] User authenticated', $response);\n } catch (Exception) {\n //Just ignore\n }\n\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapDialpadUserData(DialpadResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n // They need to be Super Admin to access the Company APIs.\n $this->logger->info('[Dialpad] User authenticated', $rawUserData);\n\n if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Dialpad Super Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapAircallUserData(AircallResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array\n {\n if ($providerUser->toArray()['data']['team_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Team Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapBullhornUserData(): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n\n private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5357074168035599503
|
-8880471945877483717
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
6
8
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services;
/**
* @todo cleanup after #slack-oauth-v2
*/
use AdamPaterson\OAuth2\Client\Provider\SlackResourceOwner;
use Chadhutchins\OAuth2\Client\Provider\Slack;
use ChaseConey\LaravelDatadogHelper\Datadog;
use Daniti\OAuth2\Client\Provider\Pipedrive;
use Daniti\OAuth2\Client\Provider\PipedriveResourceOwner;
use Exception;
use Flipbox\OAuth2\Client\Provider\HubSpot;
use Flipbox\OAuth2\Client\Provider\HubSpotResourceOwner;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Jiminny\Component\Encryption\EncryptedTokenManager;
use Jiminny\Events\Users\CrmAccountReconnected;
use Jiminny\Events\Users\SocialAccountConnected;
use Jiminny\Events\Users\SocialAccountDisconnected;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\InvalidEnumException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Notifications\SlackBotAdded;
use Jiminny\OAuth2\Client\Provider\Aircall;
use Jiminny\OAuth2\Client\Provider\AircallResourceOwner;
use Jiminny\OAuth2\Client\Provider\Bullhorn;
use Jiminny\OAuth2\Client\Provider\Dialpad;
use Jiminny\OAuth2\Client\Provider\DialpadResourceOwner;
use Jiminny\OAuth2\Client\Provider\Salesloft;
use Jiminny\OAuth2\Client\Provider\SalesloftResourceOwner;
use Jiminny\Services\Activity\Talkdesk\Provider\Talkdesk;
use Jiminny\Services\Activity\Talkdesk\Provider\TalkdeskResourceOwner;
use Jiminny\Services\Activity\Zoom\Provider\Zoom;
use Jiminny\Services\Activity\Zoom\Provider\ZoomResourceOwner;
use Jiminny\Services\OAuth2\Provider\BasicAuth;
use Jiminny\Services\OAuth2\Provider\Outreach;
use JsonException;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\GoogleUser;
use League\OAuth2\Client\Provider\LinkedIn;
use League\OAuth2\Client\Provider\LinkedInResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Psr\Log\LoggerInterface;
use Random\RandomException;
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
use Stevenmaguire\OAuth2\Client\Provider\SalesforceResourceOwner;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Provider\AzureResourceOwner;
use Throwable;
use TMannherz\OAuth2\Client\Provider\RingCentral;
use TMannherz\OAuth2\Client\Provider\RingcentralResourceOwner;
class SocialAccountService
{
/**
* Get a fresh tokens 5 minutes before it expires
* That should minimise the number of failed requests due to expired token
* for long-running jobs that reuse the same token for pulling lots of data.
*/
private const int REFRESH_OFFSET_MIN = 5;
private const string TOKEN_STATE_FETCH = 'fetch';
private const string TOKEN_STATE_REFRESH = 'refresh';
private const string TOKEN_RESULT_ATTEMPT = 'attempt';
private const string TOKEN_RESULT_SUCCESS = 'success';
private const string TOKEN_RESULT_FAILURE = 'failure';
private ?AccessTokenInterface $accessToken = null;
private ?string $token = null;
private ?string $refreshToken = null;
private ?int $expires = null;
private ?string $countryCode = null;
private ?string $timezone = null;
private ?array $vendorValues = null;
private ?int $refreshTokenExpires = null;
public function __construct(
private readonly EncryptedTokenManager $encryptedTokenManager,
private readonly LoggerInterface $logger,
private readonly PhoneNumberUtil $phoneNumberUtil,
private readonly Dispatcher $eventDispatcher,
) {
}
public function setVendorValues(array $values): void
{
$this->vendorValues = $values;
}
public function setAccessToken(AccessTokenInterface $accessToken): void
{
$this->accessToken = $accessToken;
// Todo: Also set these other params from this token e.g. refreshToken
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function setRefreshToken(?string $refreshToken): void
{
$this->refreshToken = $refreshToken;
}
public function setCountryCode(string $countryCode): void
{
$this->countryCode = $countryCode;
}
public function setTimezone(string $timezone): void
{
$this->timezone = $timezone;
}
public function setExpires(?int $expiry): void
{
$this->expires = $expiry;
}
public function setRefreshTokenExpires(array $values): void
{
$this->refreshTokenExpires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
/**
* @throws InvalidEnumException
*/
public function getProvider(string $provider): AbstractProvider
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
return new LinkedIn(config('services.linkedin'));
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
$socialProvider = new LinkedIn(config('services.linkedin-conference'));
$socialProvider->withFields([
'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',
]);
return $socialProvider;
case SocialAccount::PROVIDER_SALESFORCE:
return new Salesforce(config('services.salesforce'));
case SocialAccount::PROVIDER_GOOGLE:
return new Google(config('services.google'));
case SocialAccount::PROVIDER_SLACK:
return new Slack(config('services.slack'));
case SocialAccount::PROVIDER_OFFICE:
$config = config('services.office');
// Convert string scope to array format expected by Azure provider
if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {
$config['scopes'] = array_filter(preg_split('/\s+/', trim($config['scope'])));
unset($config['scope']);
}
$socialProvider = new Azure($config);
$socialProvider->urlAPI = '[URL_WITH_CREDENTIALS] Exception
*/
public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
/** @var LinkedInResourceOwner $providerUser */
return $this->mapLinkedInUserData($providerUser);
case SocialAccount::PROVIDER_SALESFORCE:
/** @var SalesforceResourceOwner $providerUser */
return $this->mapSalesforceUserData($providerUser);
case SocialAccount::PROVIDER_HUBSPOT:
/** @var HubSpotResourceOwner $providerUser */
return $this->mapHubSpotUserData($providerUser);
case SocialAccount::PROVIDER_PIPEDRIVE:
/** @var PipedriveResourceOwner $providerUser */
return $this->mapPipedriveUserData($providerUser);
case SocialAccount::PROVIDER_GOOGLE:
/** @var GoogleUser $providerUser */
return $this->mapGoogleUserData($providerUser);
case SocialAccount::PROVIDER_SLACK:
/** @var SlackResourceOwner $providerUser */
return $this->mapSlackUserData($providerUser);
case SocialAccount::PROVIDER_OFFICE:
/** @var AzureResourceOwner $providerUser */
return $this->mapOfficeUserData($providerUser);
case SocialAccount::PROVIDER_OUTREACH:
return $this->mapOutreachUserData($providerUser);
case SocialAccount::PROVIDER_DIALPAD:
/** @var DialpadResourceOwner $providerUser*/
return $this->mapDialpadUserData($providerUser);
case SocialAccount::PROVIDER_AIRCALL:
/** @var AircallResourceOwner $providerUser */
return $this->mapAircallUserData($providerUser);
case SocialAccount::PROVIDER_ZOOM_PHONE:
/** @var ZoomResourceOwner $providerUser */
return $this->mapZoomPhoneUserData($providerUser);
case SocialAccount::PROVIDER_SALESLOFT:
/** @var SalesloftResourceOwner $providerUser */
return $this->mapSalesloftUserData($providerUser);
case SocialAccount::PROVIDER_BULLHORN:
return $this->mapBullhornUserData();
case SocialAccount::PROVIDER_TALKDESK:
/** @var TalkdeskResourceOwner $providerUser */
return $this->mapTalkdeskUserData($providerUser);
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_TELUS:
/** @var RingcentralResourceOwner $providerUser */
return $this->mapRingCentralUserData($providerUser);
default:
throw new InvalidEnumException('Unknown provider.');
}
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
*
* @throws RandomException
*/
public function getRandomState(int $length = 32): string
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return bin2hex(random_bytes($length / 2));
}
private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount
{
return SocialAccount::where([
'provider' => $provider,
'provider_user_id' => $providerUser->getId(),
])->first();
}
/**
* Based on the provider data, try to match to a sociable entity based on email.
* If a match is made, create the social account under that entity.
*
* @throws AuthenticationException
*/
public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User
{
$account = $this->getAssociation($provider, $providerUser);
if ($account !== null && $account->hasUser()) {
return $account->getUser();
}
$userData = $this->mapUserData($provider, $providerUser);
// Check if we have an actual user with this email.
/** @var User|null $user */
$user = User::where('email', $userData['email'])->first();
// If the user is trying to connect to LinkedIn, don't allow this.
// Todo: have an interstitial page to perform 2FA to connect.
if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {
throw new AuthenticationException(
'Sorry, you\'ll need to login through your Jiminny account to access the Conference.',
);
}
return $user;
}
/**
* @throws JsonException
*/
public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount
{
/** @var SocialAccount $account */
$account = $user->socialAccounts()->firstOrNew([
'provider' => $provider,
]);
$account->fill([
'provider_user_id' => $providerUser->getId(),
'provider_user_token' => $this->token,
'expires' => $this->expires,
'state' => SocialAccount::STATE_CONNECTED,
'retry_after' => null,
]);
// This is an optional parameter, don't overwrite the existing one with null if we don't get it.
if ($this->refreshToken) {
$account->fill([
'provider_refresh_token' => $this->refreshToken,
'refresh_token_expires' => $this->refreshTokenExpires,
]);
}
if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {
$account->fill([
'auth_scope' => is_scalar($this->vendorValues['scope'])
? $this->vendorValues['scope']
: json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),
]);
} else {
$account->fill([
'auth_scope' => null,
]);
$this->logger->warning(
'[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',
// pulling directly from the token, just to avoid potential masking of the issue
['token_values' => $this->accessToken->getValues()],
);
}
$account->save();
// Association can be from an updated token so don't re-announce this.
if (
$account->wasRecentlyCreated
&& in_array($provider, SocialAccount::CRM_PROVIDERS, true)
&& $provider !== SocialAccount::PROVIDER_HUBSPOT
&& $providerUser->getId() !== null
) {
$crm = $user->team->crm;
$data = [
'crm_configuration_id' => $crm->id,
'log_notes' => Profile::LOG_NOTE_ENHANCED,
];
$crmProfile = $user->crmProfile()->where([
'crm_provider_id' => $providerUser->getId(),
])->first();
$user->crmProfile()->updateOrCreate([
'crm_provider_id' => $providerUser->getId(),
], $data);
// If updated, fire reconnected
if ($crmProfile !== null) {
$this->eventDispatcher->dispatch(new CrmAccountReconnected($account));
}
}
$this->eventDispatcher->dispatch(new SocialAccountConnected($account));
return $account;
}
public function integrate(string $provider, User $user, Team $team): void
{
if ($provider === SocialAccount::PROVIDER_SLACK) {
if (! isset($this->vendorValues['ok'])
|| $this->vendorValues['ok'] !== true
|| ! isset($this->vendorValues['token_type'])
|| $this->vendorValues['token_type'] !== 'bot'
) {
// code expects V2 token, which differs slightly from V1
throw new LogicException('Invalid token received from Slack OAuth v2 API');
}
$webhook = $this->vendorValues['incoming_webhook'];
$slackTeamId = $this->vendorValues['team']['id'];
$botData = [
'channel' => $webhook['channel'],
'channel_id' => $webhook['channel_id'],
'config_url' => $webhook['configuration_url'],
'webhook_url' => $webhook['url'],
'bot_user_id' => $this->vendorValues['bot_user_id'],
'bot_access_token' => $this->accessToken->getToken(),
];
$slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);
if ($slackBot->wasRecentlyCreated) {
// Send Slack notification.
$user->notify(new SlackBotAdded());
}
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);
$this->logger->info('[SocialAccountService] Fetching token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$account->refresh();
if (
! $forceRefresh
&& ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))
) {
$this->logger->info('[SocialAccountService] Token retrieved', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);
return $this->encryptedTokenManager->getAccessToken($account);
}
try {
$this->logger->info('[SocialAccountService] Token needs refreshing', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
return $this->refreshToken($account, $forceRefresh);
} catch (IdentityProviderException $exception) {
$responseBody = $exception->getResponseBody();
if ($responseBody instanceof Response) {
$responseBody = $responseBody->getBody();
}
if (is_object($responseBody) && method_exists($responseBody, '__toString')) {
$responseBody = $responseBody->__toString();
}
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'responseBody' => $responseBody,
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
} catch (SocialAccountTokenInvalidException $exception) {
$this->logger->error('[SocialAccountService] Cannot obtain token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception::class,
'errorMessage' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {
$this->logger->error('[SocialAccountService] Full refresh required', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
// Something terrible happened their token, they need to reconnect.
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
$this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));
}
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
}
}
public function refreshSocialAccountToken(SocialAccount $socialAccount): void
{
try {
$this->getToken($socialAccount);
} catch (Throwable $e) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $socialAccount->getId(),
'provider' => $socialAccount->getProviderName(),
'reason' => $e->getMessage(),
]);
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);
$newToken = null;
Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)
->block(8, function () use ($account, $forceRefresh, &$newToken): void {
try {
$account->refresh();
$token = $this->encryptedTokenManager->getAccessToken($account);
if (! $forceRefresh && $this->hasValidToken($account)) {
$newToken = $token;
return;
}
if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {
$this->logger->error('[SocialAccountService] Refresh token not found', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog(
$account,
self::TOKEN_STATE_REFRESH,
self::TOKEN_RESULT_FAILURE,
);
throw new SocialAccountTokenInvalidException(
'Refresh token is not set, re-connection required.',
);
}
$this->logger->info('[SocialAccountService] Refreshing token from provider', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),
'state' => $account->getState(),
]);
$newToken = $this->getProvider($account->provider)
->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
])
;
if ($newToken->getToken() === $token->getToken()) {
$this->logger->info('[SocialAccountService] Refreshed with an identical token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
}
} catch (ConnectException | RequestException $exception) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
// This usually occurs due to SSL errors.
throw new SocialAccountTokenInvalidException(
'Token could not be refreshed.',
$exception->getCode(),
$exception,
);
}
$account->provider_user_token = $newToken->getToken();
$account->expires = $newToken->getExpires();
$account->state = SocialAccount::STATE_CONNECTED;
if ($newToken->getRefreshToken()) {
$account->provider_refresh_token = $newToken->getRefreshToken();
$values = $newToken->getValues();
$account->refresh_token_expires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
$account->save();
});
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);
$this->logger->info('[SocialAccountService] Token refreshed', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'state' => $account->getState(),
]);
return $newToken;
}
/**
* @return string[]
*/
private function getAccessScope(string $provider): array
{
$scopes = [];
$providerScopes = config('services.' . $provider . '.scope');
if ($providerScopes) {
$scopes = preg_split('/\s+/', $providerScopes);
}
return $scopes;
}
/**
* @throws InvalidEnumException
*/
public function getAuthorizationOptions(string $provider): array
{
$scopes = ['scope' => $this->getAccessScope($provider)];
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
case SocialAccount::PROVIDER_SALESFORCE:
case SocialAccount::PROVIDER_HUBSPOT:
case SocialAccount::PROVIDER_OUTREACH:
case SocialAccount::PROVIDER_SALESLOFT:
case SocialAccount::PROVIDER_ZOOM_PHONE:
case SocialAccount::PROVIDER_PIPEDRIVE:
case SocialAccount::PROVIDER_SLACK:
case SocialAccount::PROVIDER_AIRCALL:
case SocialAccount::PROVIDER_BULLHORN:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_TELUS:
case SocialAccount::PROVIDER_DIALPAD:
case SocialAccount::PROVIDER_TALKDESK:
return $scopes;
case SocialAccount::PROVIDER_OFFICE:
return $scopes + [
'access_type' => 'offline',
];
case SocialAccount::PROVIDER_GOOGLE:
return $scopes + [
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'approval_prompt' => null,
];
default:
throw new InvalidEnumException();
}
}
private function tokenDoesNotExpire(SocialAccount $account): bool
{
return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);
}
private function hasValidToken(SocialAccount $account): bool
{
return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();
}
private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void
{
Datadog::increment('jiminny.access_token', 1, [
'provider' => $account->getProviderName(),
'state' => $state,
'result' => $result,
]);
}
private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),
];
}
private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
try {
$parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);
$number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);
} catch (NumberParseException) {
$number = null;
}
// Todo: this should check the `organization_id` matches the parent crm configuration.
return [
'country_code' => $this->countryCode,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),
'phone' => $number,
'crm_provider_id' => $rawUserData['organization_id'],
'crm_base_url' => $this->vendorValues['instance_url'],
];
}
/**
* Todo: this should check the `getHubId` matches the parent crm configuration.
*/
private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $providerUser->getHubId(),
'crm_base_url' => $providerUser->toArray()['hub_domain'],
];
}
/**
* Todo: this should check the `getCompanyId` matches the parent crm configuration.
*/
private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $rawUserData['data']['company_id'],
'crm_base_url' => '[URL_WITH_CREDENTIALS] ActivityProviderException
*/
private function mapDialpadUserData(DialpadResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
// They need to be Super Admin to access the Company APIs.
$this->logger->info('[Dialpad] User authenticated', $rawUserData);
if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Dialpad Super Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapAircallUserData(AircallResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
/**
* @throws ActivityProviderException
*/
private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array
{
if ($providerUser->toArray()['data']['team_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Team Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapBullhornUserData(): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
];
}
private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
}
Execute
Explain Plan...
|
34713
|
NULL
|
NULL
|
NULL
|
|
34716
|
1300
|
6
|
2026-05-13T11:34:54.528746+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672094528_m2.jpg...
|
PhpStorm
|
faVsco.js – SocialAccountService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
6
8
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services;
/**
* @todo cleanup after #slack-oauth-v2
*/
use AdamPaterson\OAuth2\Client\Provider\SlackResourceOwner;
use Chadhutchins\OAuth2\Client\Provider\Slack;
use ChaseConey\LaravelDatadogHelper\Datadog;
use Daniti\OAuth2\Client\Provider\Pipedrive;
use Daniti\OAuth2\Client\Provider\PipedriveResourceOwner;
use Exception;
use Flipbox\OAuth2\Client\Provider\HubSpot;
use Flipbox\OAuth2\Client\Provider\HubSpotResourceOwner;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Jiminny\Component\Encryption\EncryptedTokenManager;
use Jiminny\Events\Users\CrmAccountReconnected;
use Jiminny\Events\Users\SocialAccountConnected;
use Jiminny\Events\Users\SocialAccountDisconnected;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\InvalidEnumException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Notifications\SlackBotAdded;
use Jiminny\OAuth2\Client\Provider\Aircall;
use Jiminny\OAuth2\Client\Provider\AircallResourceOwner;
use Jiminny\OAuth2\Client\Provider\Bullhorn;
use Jiminny\OAuth2\Client\Provider\Dialpad;
use Jiminny\OAuth2\Client\Provider\DialpadResourceOwner;
use Jiminny\OAuth2\Client\Provider\Salesloft;
use Jiminny\OAuth2\Client\Provider\SalesloftResourceOwner;
use Jiminny\Services\Activity\Talkdesk\Provider\Talkdesk;
use Jiminny\Services\Activity\Talkdesk\Provider\TalkdeskResourceOwner;
use Jiminny\Services\Activity\Zoom\Provider\Zoom;
use Jiminny\Services\Activity\Zoom\Provider\ZoomResourceOwner;
use Jiminny\Services\OAuth2\Provider\BasicAuth;
use Jiminny\Services\OAuth2\Provider\Outreach;
use JsonException;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\GoogleUser;
use League\OAuth2\Client\Provider\LinkedIn;
use League\OAuth2\Client\Provider\LinkedInResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Psr\Log\LoggerInterface;
use Random\RandomException;
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
use Stevenmaguire\OAuth2\Client\Provider\SalesforceResourceOwner;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Provider\AzureResourceOwner;
use Throwable;
use TMannherz\OAuth2\Client\Provider\RingCentral;
use TMannherz\OAuth2\Client\Provider\RingcentralResourceOwner;
class SocialAccountService
{
/**
* Get a fresh tokens 5 minutes before it expires
* That should minimise the number of failed requests due to expired token
* for long-running jobs that reuse the same token for pulling lots of data.
*/
private const int REFRESH_OFFSET_MIN = 5;
private const string TOKEN_STATE_FETCH = 'fetch';
private const string TOKEN_STATE_REFRESH = 'refresh';
private const string TOKEN_RESULT_ATTEMPT = 'attempt';
private const string TOKEN_RESULT_SUCCESS = 'success';
private const string TOKEN_RESULT_FAILURE = 'failure';
private ?AccessTokenInterface $accessToken = null;
private ?string $token = null;
private ?string $refreshToken = null;
private ?int $expires = null;
private ?string $countryCode = null;
private ?string $timezone = null;
private ?array $vendorValues = null;
private ?int $refreshTokenExpires = null;
public function __construct(
private readonly EncryptedTokenManager $encryptedTokenManager,
private readonly LoggerInterface $logger,
private readonly PhoneNumberUtil $phoneNumberUtil,
private readonly Dispatcher $eventDispatcher,
) {
}
public function setVendorValues(array $values): void
{
$this->vendorValues = $values;
}
public function setAccessToken(AccessTokenInterface $accessToken): void
{
$this->accessToken = $accessToken;
// Todo: Also set these other params from this token e.g. refreshToken
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function setRefreshToken(?string $refreshToken): void
{
$this->refreshToken = $refreshToken;
}
public function setCountryCode(string $countryCode): void
{
$this->countryCode = $countryCode;
}
public function setTimezone(string $timezone): void
{
$this->timezone = $timezone;
}
public function setExpires(?int $expiry): void
{
$this->expires = $expiry;
}
public function setRefreshTokenExpires(array $values): void
{
$this->refreshTokenExpires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
/**
* @throws InvalidEnumException
*/
public function getProvider(string $provider): AbstractProvider
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
return new LinkedIn(config('services.linkedin'));
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
$socialProvider = new LinkedIn(config('services.linkedin-conference'));
$socialProvider->withFields([
'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',
]);
return $socialProvider;
case SocialAccount::PROVIDER_SALESFORCE:
return new Salesforce(config('services.salesforce'));
case SocialAccount::PROVIDER_GOOGLE:
return new Google(config('services.google'));
case SocialAccount::PROVIDER_SLACK:
return new Slack(config('services.slack'));
case SocialAccount::PROVIDER_OFFICE:
$config = config('services.office');
// Convert string scope to array format expected by Azure provider
if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {
$config['scopes'] = array_filter(preg_split('/\s+/', trim($config['scope'])));
unset($config['scope']);
}
$socialProvider = new Azure($config);
$socialProvider->urlAPI = '[URL_WITH_CREDENTIALS] Exception
*/
public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
/** @var LinkedInResourceOwner $providerUser */
return $this->mapLinkedInUserData($providerUser);
case SocialAccount::PROVIDER_SALESFORCE:
/** @var SalesforceResourceOwner $providerUser */
return $this->mapSalesforceUserData($providerUser);
case SocialAccount::PROVIDER_HUBSPOT:
/** @var HubSpotResourceOwner $providerUser */
return $this->mapHubSpotUserData($providerUser);
case SocialAccount::PROVIDER_PIPEDRIVE:
/** @var PipedriveResourceOwner $providerUser */
return $this->mapPipedriveUserData($providerUser);
case SocialAccount::PROVIDER_GOOGLE:
/** @var GoogleUser $providerUser */
return $this->mapGoogleUserData($providerUser);
case SocialAccount::PROVIDER_SLACK:
/** @var SlackResourceOwner $providerUser */
return $this->mapSlackUserData($providerUser);
case SocialAccount::PROVIDER_OFFICE:
/** @var AzureResourceOwner $providerUser */
return $this->mapOfficeUserData($providerUser);
case SocialAccount::PROVIDER_OUTREACH:
return $this->mapOutreachUserData($providerUser);
case SocialAccount::PROVIDER_DIALPAD:
/** @var DialpadResourceOwner $providerUser*/
return $this->mapDialpadUserData($providerUser);
case SocialAccount::PROVIDER_AIRCALL:
/** @var AircallResourceOwner $providerUser */
return $this->mapAircallUserData($providerUser);
case SocialAccount::PROVIDER_ZOOM_PHONE:
/** @var ZoomResourceOwner $providerUser */
return $this->mapZoomPhoneUserData($providerUser);
case SocialAccount::PROVIDER_SALESLOFT:
/** @var SalesloftResourceOwner $providerUser */
return $this->mapSalesloftUserData($providerUser);
case SocialAccount::PROVIDER_BULLHORN:
return $this->mapBullhornUserData();
case SocialAccount::PROVIDER_TALKDESK:
/** @var TalkdeskResourceOwner $providerUser */
return $this->mapTalkdeskUserData($providerUser);
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_TELUS:
/** @var RingcentralResourceOwner $providerUser */
return $this->mapRingCentralUserData($providerUser);
default:
throw new InvalidEnumException('Unknown provider.');
}
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
*
* @throws RandomException
*/
public function getRandomState(int $length = 32): string
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return bin2hex(random_bytes($length / 2));
}
private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount
{
return SocialAccount::where([
'provider' => $provider,
'provider_user_id' => $providerUser->getId(),
])->first();
}
/**
* Based on the provider data, try to match to a sociable entity based on email.
* If a match is made, create the social account under that entity.
*
* @throws AuthenticationException
*/
public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User
{
$account = $this->getAssociation($provider, $providerUser);
if ($account !== null && $account->hasUser()) {
return $account->getUser();
}
$userData = $this->mapUserData($provider, $providerUser);
// Check if we have an actual user with this email.
/** @var User|null $user */
$user = User::where('email', $userData['email'])->first();
// If the user is trying to connect to LinkedIn, don't allow this.
// Todo: have an interstitial page to perform 2FA to connect.
if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {
throw new AuthenticationException(
'Sorry, you\'ll need to login through your Jiminny account to access the Conference.',
);
}
return $user;
}
/**
* @throws JsonException
*/
public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount
{
/** @var SocialAccount $account */
$account = $user->socialAccounts()->firstOrNew([
'provider' => $provider,
]);
$account->fill([
'provider_user_id' => $providerUser->getId(),
'provider_user_token' => $this->token,
'expires' => $this->expires,
'state' => SocialAccount::STATE_CONNECTED,
'retry_after' => null,
]);
// This is an optional parameter, don't overwrite the existing one with null if we don't get it.
if ($this->refreshToken) {
$account->fill([
'provider_refresh_token' => $this->refreshToken,
'refresh_token_expires' => $this->refreshTokenExpires,
]);
}
if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {
$account->fill([
'auth_scope' => is_scalar($this->vendorValues['scope'])
? $this->vendorValues['scope']
: json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),
]);
} else {
$account->fill([
'auth_scope' => null,
]);
$this->logger->warning(
'[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',
// pulling directly from the token, just to avoid potential masking of the issue
['token_values' => $this->accessToken->getValues()],
);
}
$account->save();
// Association can be from an updated token so don't re-announce this.
if (
$account->wasRecentlyCreated
&& in_array($provider, SocialAccount::CRM_PROVIDERS, true)
&& $provider !== SocialAccount::PROVIDER_HUBSPOT
&& $providerUser->getId() !== null
) {
$crm = $user->team->crm;
$data = [
'crm_configuration_id' => $crm->id,
'log_notes' => Profile::LOG_NOTE_ENHANCED,
];
$crmProfile = $user->crmProfile()->where([
'crm_provider_id' => $providerUser->getId(),
])->first();
$user->crmProfile()->updateOrCreate([
'crm_provider_id' => $providerUser->getId(),
], $data);
// If updated, fire reconnected
if ($crmProfile !== null) {
$this->eventDispatcher->dispatch(new CrmAccountReconnected($account));
}
}
$this->eventDispatcher->dispatch(new SocialAccountConnected($account));
return $account;
}
public function integrate(string $provider, User $user, Team $team): void
{
if ($provider === SocialAccount::PROVIDER_SLACK) {
if (! isset($this->vendorValues['ok'])
|| $this->vendorValues['ok'] !== true
|| ! isset($this->vendorValues['token_type'])
|| $this->vendorValues['token_type'] !== 'bot'
) {
// code expects V2 token, which differs slightly from V1
throw new LogicException('Invalid token received from Slack OAuth v2 API');
}
$webhook = $this->vendorValues['incoming_webhook'];
$slackTeamId = $this->vendorValues['team']['id'];
$botData = [
'channel' => $webhook['channel'],
'channel_id' => $webhook['channel_id'],
'config_url' => $webhook['configuration_url'],
'webhook_url' => $webhook['url'],
'bot_user_id' => $this->vendorValues['bot_user_id'],
'bot_access_token' => $this->accessToken->getToken(),
];
$slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);
if ($slackBot->wasRecentlyCreated) {
// Send Slack notification.
$user->notify(new SlackBotAdded());
}
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);
$this->logger->info('[SocialAccountService] Fetching token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$account->refresh();
if (
! $forceRefresh
&& ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))
) {
$this->logger->info('[SocialAccountService] Token retrieved', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);
return $this->encryptedTokenManager->getAccessToken($account);
}
try {
$this->logger->info('[SocialAccountService] Token needs refreshing', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
return $this->refreshToken($account, $forceRefresh);
} catch (IdentityProviderException $exception) {
$responseBody = $exception->getResponseBody();
if ($responseBody instanceof Response) {
$responseBody = $responseBody->getBody();
}
if (is_object($responseBody) && method_exists($responseBody, '__toString')) {
$responseBody = $responseBody->__toString();
}
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'responseBody' => $responseBody,
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
} catch (SocialAccountTokenInvalidException $exception) {
$this->logger->error('[SocialAccountService] Cannot obtain token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception::class,
'errorMessage' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {
$this->logger->error('[SocialAccountService] Full refresh required', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
// Something terrible happened their token, they need to reconnect.
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
$this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));
}
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
}
}
public function refreshSocialAccountToken(SocialAccount $socialAccount): void
{
try {
$this->getToken($socialAccount);
} catch (Throwable $e) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $socialAccount->getId(),
'provider' => $socialAccount->getProviderName(),
'reason' => $e->getMessage(),
]);
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);
$newToken = null;
Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)
->block(8, function () use ($account, $forceRefresh, &$newToken): void {
try {
$account->refresh();
$token = $this->encryptedTokenManager->getAccessToken($account);
if (! $forceRefresh && $this->hasValidToken($account)) {
$newToken = $token;
return;
}
if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {
$this->logger->error('[SocialAccountService] Refresh token not found', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog(
$account,
self::TOKEN_STATE_REFRESH,
self::TOKEN_RESULT_FAILURE,
);
throw new SocialAccountTokenInvalidException(
'Refresh token is not set, re-connection required.',
);
}
$this->logger->info('[SocialAccountService] Refreshing token from provider', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),
'state' => $account->getState(),
]);
$newToken = $this->getProvider($account->provider)
->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
])
;
if ($newToken->getToken() === $token->getToken()) {
$this->logger->info('[SocialAccountService] Refreshed with an identical token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
}
} catch (ConnectException | RequestException $exception) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
// This usually occurs due to SSL errors.
throw new SocialAccountTokenInvalidException(
'Token could not be refreshed.',
$exception->getCode(),
$exception,
);
}
$account->provider_user_token = $newToken->getToken();
$account->expires = $newToken->getExpires();
$account->state = SocialAccount::STATE_CONNECTED;
if ($newToken->getRefreshToken()) {
$account->provider_refresh_token = $newToken->getRefreshToken();
$values = $newToken->getValues();
$account->refresh_token_expires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
$account->save();
});
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);
$this->logger->info('[SocialAccountService] Token refreshed', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'state' => $account->getState(),
]);
return $newToken;
}
/**
* @return string[]
*/
private function getAccessScope(string $provider): array
{
$scopes = [];
$providerScopes = config('services.' . $provider . '.scope');
if ($providerScopes) {
$scopes = preg_split('/\s+/', $providerScopes);
}
return $scopes;
}
/**
* @throws InvalidEnumException
*/
public function getAuthorizationOptions(string $provider): array
{
$scopes = ['scope' => $this->getAccessScope($provider)];
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
case SocialAccount::PROVIDER_SALESFORCE:
case SocialAccount::PROVIDER_HUBSPOT:
case SocialAccount::PROVIDER_OUTREACH:
case SocialAccount::PROVIDER_SALESLOFT:
case SocialAccount::PROVIDER_ZOOM_PHONE:
case SocialAccount::PROVIDER_PIPEDRIVE:
case SocialAccount::PROVIDER_SLACK:
case SocialAccount::PROVIDER_AIRCALL:
case SocialAccount::PROVIDER_BULLHORN:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_TELUS:
case SocialAccount::PROVIDER_DIALPAD:
case SocialAccount::PROVIDER_TALKDESK:
return $scopes;
case SocialAccount::PROVIDER_OFFICE:
return $scopes + [
'access_type' => 'offline',
];
case SocialAccount::PROVIDER_GOOGLE:
return $scopes + [
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'approval_prompt' => null,
];
default:
throw new InvalidEnumException();
}
}
private function tokenDoesNotExpire(SocialAccount $account): bool
{
return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);
}
private function hasValidToken(SocialAccount $account): bool
{
return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();
}
private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void
{
Datadog::increment('jiminny.access_token', 1, [
'provider' => $account->getProviderName(),
'state' => $state,
'result' => $result,
]);
}
private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),
];
}
private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
try {
$parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);
$number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);
} catch (NumberParseException) {
$number = null;
}
// Todo: this should check the `organization_id` matches the parent crm configuration.
return [
'country_code' => $this->countryCode,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),
'phone' => $number,
'crm_provider_id' => $rawUserData['organization_id'],
'crm_base_url' => $this->vendorValues['instance_url'],
];
}
/**
* Todo: this should check the `getHubId` matches the parent crm configuration.
*/
private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $providerUser->getHubId(),
'crm_base_url' => $providerUser->toArray()['hub_domain'],
];
}
/**
* Todo: this should check the `getCompanyId` matches the parent crm configuration.
*/
private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $rawUserData['data']['company_id'],
'crm_base_url' => '[URL_WITH_CREDENTIALS] ActivityProviderException
*/
private function mapDialpadUserData(DialpadResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
// They need to be Super Admin to access the Company APIs.
$this->logger->info('[Dialpad] User authenticated', $rawUserData);
if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Dialpad Super Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapAircallUserData(AircallResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
/**
* @throws ActivityProviderException
*/
private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array
{
if ($providerUser->toArray()['data']['team_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Team Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapBullhornUserData(): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
];
}
private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.08843085,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.37400267,"top":0.15003991,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.38397607,"top":0.15003991,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39361703,"top":0.14844373,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40093085,"top":0.14844373,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Services;\n\n/**\n * @todo cleanup after #slack-oauth-v2\n */\n\nuse AdamPaterson\\OAuth2\\Client\\Provider\\SlackResourceOwner;\nuse Chadhutchins\\OAuth2\\Client\\Provider\\Slack;\nuse ChaseConey\\LaravelDatadogHelper\\Datadog;\nuse Daniti\\OAuth2\\Client\\Provider\\Pipedrive;\nuse Daniti\\OAuth2\\Client\\Provider\\PipedriveResourceOwner;\nuse Exception;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpot;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpotResourceOwner;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Auth\\AuthenticationException;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Jiminny\\Component\\Encryption\\EncryptedTokenManager;\nuse Jiminny\\Events\\Users\\CrmAccountReconnected;\nuse Jiminny\\Events\\Users\\SocialAccountConnected;\nuse Jiminny\\Events\\Users\\SocialAccountDisconnected;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\InvalidEnumException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Notifications\\SlackBotAdded;\nuse Jiminny\\OAuth2\\Client\\Provider\\Aircall;\nuse Jiminny\\OAuth2\\Client\\Provider\\AircallResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Bullhorn;\nuse Jiminny\\OAuth2\\Client\\Provider\\Dialpad;\nuse Jiminny\\OAuth2\\Client\\Provider\\DialpadResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Salesloft;\nuse Jiminny\\OAuth2\\Client\\Provider\\SalesloftResourceOwner;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\Talkdesk;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\TalkdeskResourceOwner;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\Zoom;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\ZoomResourceOwner;\nuse Jiminny\\Services\\OAuth2\\Provider\\BasicAuth;\nuse Jiminny\\Services\\OAuth2\\Provider\\Outreach;\nuse JsonException;\nuse League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider;\nuse League\\OAuth2\\Client\\Provider\\AbstractProvider;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Provider\\Google;\nuse League\\OAuth2\\Client\\Provider\\GoogleUser;\nuse League\\OAuth2\\Client\\Provider\\LinkedIn;\nuse League\\OAuth2\\Client\\Provider\\LinkedInResourceOwner;\nuse League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse League\\OAuth2\\Client\\Token\\AccessTokenInterface;\nuse libphonenumber\\NumberParseException;\nuse libphonenumber\\PhoneNumberFormat;\nuse libphonenumber\\PhoneNumberUtil;\nuse LogicException;\nuse Psr\\Log\\LoggerInterface;\nuse Random\\RandomException;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\Salesforce;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\SalesforceResourceOwner;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\nuse TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner;\nuse Throwable;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingCentral;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingcentralResourceOwner;\n\nclass SocialAccountService\n{\n /**\n * Get a fresh tokens 5 minutes before it expires\n * That should minimise the number of failed requests due to expired token\n * for long-running jobs that reuse the same token for pulling lots of data.\n */\n private const int REFRESH_OFFSET_MIN = 5;\n\n private const string TOKEN_STATE_FETCH = 'fetch';\n private const string TOKEN_STATE_REFRESH = 'refresh';\n private const string TOKEN_RESULT_ATTEMPT = 'attempt';\n private const string TOKEN_RESULT_SUCCESS = 'success';\n private const string TOKEN_RESULT_FAILURE = 'failure';\n\n private ?AccessTokenInterface $accessToken = null;\n private ?string $token = null;\n private ?string $refreshToken = null;\n private ?int $expires = null;\n private ?string $countryCode = null;\n private ?string $timezone = null;\n private ?array $vendorValues = null;\n\n private ?int $refreshTokenExpires = null;\n\n public function __construct(\n private readonly EncryptedTokenManager $encryptedTokenManager,\n private readonly LoggerInterface $logger,\n private readonly PhoneNumberUtil $phoneNumberUtil,\n private readonly Dispatcher $eventDispatcher,\n ) {\n }\n\n public function setVendorValues(array $values): void\n {\n $this->vendorValues = $values;\n }\n\n public function setAccessToken(AccessTokenInterface $accessToken): void\n {\n $this->accessToken = $accessToken;\n // Todo: Also set these other params from this token e.g. refreshToken\n }\n\n public function setToken(?string $token): void\n {\n $this->token = $token;\n }\n\n public function setRefreshToken(?string $refreshToken): void\n {\n $this->refreshToken = $refreshToken;\n }\n\n public function setCountryCode(string $countryCode): void\n {\n $this->countryCode = $countryCode;\n }\n\n public function setTimezone(string $timezone): void\n {\n $this->timezone = $timezone;\n }\n\n public function setExpires(?int $expiry): void\n {\n $this->expires = $expiry;\n }\n\n public function setRefreshTokenExpires(array $values): void\n {\n $this->refreshTokenExpires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getProvider(string $provider): AbstractProvider\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n return new LinkedIn(config('services.linkedin'));\n\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n $socialProvider = new LinkedIn(config('services.linkedin-conference'));\n $socialProvider->withFields([\n 'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',\n ]);\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_SALESFORCE:\n return new Salesforce(config('services.salesforce'));\n\n case SocialAccount::PROVIDER_GOOGLE:\n return new Google(config('services.google'));\n\n case SocialAccount::PROVIDER_SLACK:\n return new Slack(config('services.slack'));\n\n case SocialAccount::PROVIDER_OFFICE:\n $config = config('services.office');\n\n // Convert string scope to array format expected by Azure provider\n if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {\n $config['scopes'] = array_filter(preg_split('/\\s+/', trim($config['scope'])));\n unset($config['scope']);\n }\n\n $socialProvider = new Azure($config);\n $socialProvider->urlAPI = 'https://graph.microsoft.com/v1.0/';\n $socialProvider->API_VERSION = '1.0';\n $socialProvider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_HUBSPOT:\n return new HubSpot(config('services.hubspot'));\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n return new Pipedrive(config('services.pipedrive'));\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n return new Zoom(config('services.zoom-phone'));\n\n case SocialAccount::PROVIDER_OUTREACH:\n return new Outreach(config('services.outreach'));\n\n case SocialAccount::PROVIDER_SALESLOFT:\n return new Salesloft(config('services.salesloft'));\n\n case SocialAccount::PROVIDER_AIRCALL:\n return new Aircall(config('services.aircall'));\n\n case SocialAccount::PROVIDER_DIALPAD:\n return new Dialpad(config('services.dialpad'));\n\n case SocialAccount::PROVIDER_GONG:\n return new BasicAuth(config('services.gong'));\n\n case SocialAccount::PROVIDER_CLOSE:\n return new BasicAuth(config('services.close'));\n\n case SocialAccount::PROVIDER_AVAYA:\n // Avaya is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.avaya'));\n\n case SocialAccount::PROVIDER_TELUS:\n // Telus is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.telus'));\n\n case SocialAccount::PROVIDER_RINGCENTRAL:\n return new RingCentral(config('services.ringcentral'));\n\n case SocialAccount::PROVIDER_BULLHORN:\n return new Bullhorn(config('services.bullhorn'));\n\n case SocialAccount::PROVIDER_TALKDESK:\n return new Talkdesk(config('services.talkdesk'), [\n // Automatically concatenate Basic token to AuthToken requests\n 'optionProvider' => new HttpBasicAuthOptionProvider(),\n ]);\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n /**\n *\n *\n * @throws Exception\n */\n public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n /** @var LinkedInResourceOwner $providerUser */\n return $this->mapLinkedInUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESFORCE:\n /** @var SalesforceResourceOwner $providerUser */\n return $this->mapSalesforceUserData($providerUser);\n\n case SocialAccount::PROVIDER_HUBSPOT:\n /** @var HubSpotResourceOwner $providerUser */\n return $this->mapHubSpotUserData($providerUser);\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n /** @var PipedriveResourceOwner $providerUser */\n return $this->mapPipedriveUserData($providerUser);\n\n case SocialAccount::PROVIDER_GOOGLE:\n /** @var GoogleUser $providerUser */\n return $this->mapGoogleUserData($providerUser);\n\n case SocialAccount::PROVIDER_SLACK:\n /** @var SlackResourceOwner $providerUser */\n return $this->mapSlackUserData($providerUser);\n\n case SocialAccount::PROVIDER_OFFICE:\n /** @var AzureResourceOwner $providerUser */\n return $this->mapOfficeUserData($providerUser);\n\n case SocialAccount::PROVIDER_OUTREACH:\n return $this->mapOutreachUserData($providerUser);\n\n case SocialAccount::PROVIDER_DIALPAD:\n /** @var DialpadResourceOwner $providerUser*/\n return $this->mapDialpadUserData($providerUser);\n\n case SocialAccount::PROVIDER_AIRCALL:\n /** @var AircallResourceOwner $providerUser */\n return $this->mapAircallUserData($providerUser);\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n /** @var ZoomResourceOwner $providerUser */\n return $this->mapZoomPhoneUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESLOFT:\n /** @var SalesloftResourceOwner $providerUser */\n return $this->mapSalesloftUserData($providerUser);\n\n case SocialAccount::PROVIDER_BULLHORN:\n return $this->mapBullhornUserData();\n\n case SocialAccount::PROVIDER_TALKDESK:\n /** @var TalkdeskResourceOwner $providerUser */\n return $this->mapTalkdeskUserData($providerUser);\n\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_TELUS:\n /** @var RingcentralResourceOwner $providerUser */\n return $this->mapRingCentralUserData($providerUser);\n default:\n throw new InvalidEnumException('Unknown provider.');\n }\n }\n\n /**\n * Returns a new random string to use as the state parameter in an\n * authorization flow.\n *\n * @param int $length Length of the random string to be generated.\n *\n * @throws RandomException\n */\n public function getRandomState(int $length = 32): string\n {\n // Converting bytes to hex will always double length. Hence, we can reduce\n // the amount of bytes by half to produce the correct length.\n return bin2hex(random_bytes($length / 2));\n }\n\n private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount\n {\n return SocialAccount::where([\n 'provider' => $provider,\n 'provider_user_id' => $providerUser->getId(),\n ])->first();\n }\n\n /**\n * Based on the provider data, try to match to a sociable entity based on email.\n * If a match is made, create the social account under that entity.\n *\n * @throws AuthenticationException\n */\n public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User\n {\n $account = $this->getAssociation($provider, $providerUser);\n if ($account !== null && $account->hasUser()) {\n return $account->getUser();\n }\n $userData = $this->mapUserData($provider, $providerUser);\n\n // Check if we have an actual user with this email.\n /** @var User|null $user */\n $user = User::where('email', $userData['email'])->first();\n\n // If the user is trying to connect to LinkedIn, don't allow this.\n // Todo: have an interstitial page to perform 2FA to connect.\n if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {\n throw new AuthenticationException(\n 'Sorry, you\\'ll need to login through your Jiminny account to access the Conference.',\n );\n }\n\n return $user;\n }\n\n /**\n * @throws JsonException\n */\n public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount\n {\n /** @var SocialAccount $account */\n $account = $user->socialAccounts()->firstOrNew([\n 'provider' => $provider,\n ]);\n\n $account->fill([\n 'provider_user_id' => $providerUser->getId(),\n 'provider_user_token' => $this->token,\n 'expires' => $this->expires,\n 'state' => SocialAccount::STATE_CONNECTED,\n 'retry_after' => null,\n ]);\n\n // This is an optional parameter, don't overwrite the existing one with null if we don't get it.\n if ($this->refreshToken) {\n $account->fill([\n 'provider_refresh_token' => $this->refreshToken,\n 'refresh_token_expires' => $this->refreshTokenExpires,\n ]);\n }\n\n if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {\n $account->fill([\n 'auth_scope' => is_scalar($this->vendorValues['scope'])\n ? $this->vendorValues['scope']\n : json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),\n ]);\n } else {\n $account->fill([\n 'auth_scope' => null,\n ]);\n\n $this->logger->warning(\n '[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',\n // pulling directly from the token, just to avoid potential masking of the issue\n ['token_values' => $this->accessToken->getValues()],\n );\n }\n\n $account->save();\n\n // Association can be from an updated token so don't re-announce this.\n if (\n $account->wasRecentlyCreated\n && in_array($provider, SocialAccount::CRM_PROVIDERS, true)\n && $provider !== SocialAccount::PROVIDER_HUBSPOT\n && $providerUser->getId() !== null\n ) {\n $crm = $user->team->crm;\n $data = [\n 'crm_configuration_id' => $crm->id,\n 'log_notes' => Profile::LOG_NOTE_ENHANCED,\n ];\n\n $crmProfile = $user->crmProfile()->where([\n 'crm_provider_id' => $providerUser->getId(),\n ])->first();\n\n $user->crmProfile()->updateOrCreate([\n 'crm_provider_id' => $providerUser->getId(),\n ], $data);\n\n // If updated, fire reconnected\n if ($crmProfile !== null) {\n $this->eventDispatcher->dispatch(new CrmAccountReconnected($account));\n }\n }\n\n $this->eventDispatcher->dispatch(new SocialAccountConnected($account));\n\n return $account;\n }\n\n public function integrate(string $provider, User $user, Team $team): void\n {\n if ($provider === SocialAccount::PROVIDER_SLACK) {\n if (! isset($this->vendorValues['ok'])\n || $this->vendorValues['ok'] !== true\n || ! isset($this->vendorValues['token_type'])\n || $this->vendorValues['token_type'] !== 'bot'\n ) {\n // code expects V2 token, which differs slightly from V1\n throw new LogicException('Invalid token received from Slack OAuth v2 API');\n }\n\n $webhook = $this->vendorValues['incoming_webhook'];\n\n $slackTeamId = $this->vendorValues['team']['id'];\n\n $botData = [\n 'channel' => $webhook['channel'],\n 'channel_id' => $webhook['channel_id'],\n 'config_url' => $webhook['configuration_url'],\n 'webhook_url' => $webhook['url'],\n 'bot_user_id' => $this->vendorValues['bot_user_id'],\n 'bot_access_token' => $this->accessToken->getToken(),\n ];\n\n $slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);\n\n if ($slackBot->wasRecentlyCreated) {\n // Send Slack notification.\n $user->notify(new SlackBotAdded());\n }\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);\n\n $this->logger->info('[SocialAccountService] Fetching token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $account->refresh();\n\n if (\n ! $forceRefresh\n && ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))\n ) {\n $this->logger->info('[SocialAccountService] Token retrieved', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);\n\n return $this->encryptedTokenManager->getAccessToken($account);\n }\n\n try {\n $this->logger->info('[SocialAccountService] Token needs refreshing', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n return $this->refreshToken($account, $forceRefresh);\n } catch (IdentityProviderException $exception) {\n $responseBody = $exception->getResponseBody();\n\n if ($responseBody instanceof Response) {\n $responseBody = $responseBody->getBody();\n }\n\n if (is_object($responseBody) && method_exists($responseBody, '__toString')) {\n $responseBody = $responseBody->__toString();\n }\n\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'responseBody' => $responseBody,\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n } catch (SocialAccountTokenInvalidException $exception) {\n $this->logger->error('[SocialAccountService] Cannot obtain token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception::class,\n 'errorMessage' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {\n $this->logger->error('[SocialAccountService] Full refresh required', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n // Something terrible happened their token, they need to reconnect.\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n $this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));\n }\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n }\n }\n\n public function refreshSocialAccountToken(SocialAccount $socialAccount): void\n {\n try {\n $this->getToken($socialAccount);\n } catch (Throwable $e) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $socialAccount->getId(),\n 'provider' => $socialAccount->getProviderName(),\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);\n\n $newToken = null;\n\n Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)\n ->block(8, function () use ($account, $forceRefresh, &$newToken): void {\n try {\n $account->refresh();\n $token = $this->encryptedTokenManager->getAccessToken($account);\n\n if (! $forceRefresh && $this->hasValidToken($account)) {\n $newToken = $token;\n\n return;\n }\n\n if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {\n $this->logger->error('[SocialAccountService] Refresh token not found', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog(\n $account,\n self::TOKEN_STATE_REFRESH,\n self::TOKEN_RESULT_FAILURE,\n );\n\n throw new SocialAccountTokenInvalidException(\n 'Refresh token is not set, re-connection required.',\n );\n }\n\n $this->logger->info('[SocialAccountService] Refreshing token from provider', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),\n 'state' => $account->getState(),\n ]);\n\n $newToken = $this->getProvider($account->provider)\n ->getAccessToken('refresh_token', [\n 'refresh_token' => $token->getRefreshToken(),\n ])\n ;\n\n if ($newToken->getToken() === $token->getToken()) {\n $this->logger->info('[SocialAccountService] Refreshed with an identical token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n }\n } catch (ConnectException | RequestException $exception) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n // This usually occurs due to SSL errors.\n throw new SocialAccountTokenInvalidException(\n 'Token could not be refreshed.',\n $exception->getCode(),\n $exception,\n );\n }\n\n $account->provider_user_token = $newToken->getToken();\n $account->expires = $newToken->getExpires();\n $account->state = SocialAccount::STATE_CONNECTED;\n\n if ($newToken->getRefreshToken()) {\n $account->provider_refresh_token = $newToken->getRefreshToken();\n $values = $newToken->getValues();\n $account->refresh_token_expires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n $account->save();\n });\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);\n\n $this->logger->info('[SocialAccountService] Token refreshed', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'state' => $account->getState(),\n ]);\n\n return $newToken;\n }\n\n /**\n * @return string[]\n */\n private function getAccessScope(string $provider): array\n {\n $scopes = [];\n $providerScopes = config('services.' . $provider . '.scope');\n\n if ($providerScopes) {\n $scopes = preg_split('/\\s+/', $providerScopes);\n }\n\n return $scopes;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getAuthorizationOptions(string $provider): array\n {\n $scopes = ['scope' => $this->getAccessScope($provider)];\n\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n case SocialAccount::PROVIDER_SALESFORCE:\n case SocialAccount::PROVIDER_HUBSPOT:\n case SocialAccount::PROVIDER_OUTREACH:\n case SocialAccount::PROVIDER_SALESLOFT:\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n case SocialAccount::PROVIDER_PIPEDRIVE:\n case SocialAccount::PROVIDER_SLACK:\n case SocialAccount::PROVIDER_AIRCALL:\n case SocialAccount::PROVIDER_BULLHORN:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_TELUS:\n case SocialAccount::PROVIDER_DIALPAD:\n case SocialAccount::PROVIDER_TALKDESK:\n return $scopes;\n\n case SocialAccount::PROVIDER_OFFICE:\n return $scopes + [\n 'access_type' => 'offline',\n ];\n\n case SocialAccount::PROVIDER_GOOGLE:\n return $scopes + [\n 'access_type' => 'offline',\n 'include_granted_scopes' => 'true',\n 'approval_prompt' => null,\n ];\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n private function tokenDoesNotExpire(SocialAccount $account): bool\n {\n return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);\n }\n\n private function hasValidToken(SocialAccount $account): bool\n {\n return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();\n }\n\n private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void\n {\n Datadog::increment('jiminny.access_token', 1, [\n 'provider' => $account->getProviderName(),\n 'state' => $state,\n 'result' => $result,\n ]);\n }\n\n private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),\n ];\n }\n\n private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n try {\n $parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);\n $number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);\n } catch (NumberParseException) {\n $number = null;\n }\n\n // Todo: this should check the `organization_id` matches the parent crm configuration.\n\n return [\n 'country_code' => $this->countryCode,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),\n 'phone' => $number,\n 'crm_provider_id' => $rawUserData['organization_id'],\n 'crm_base_url' => $this->vendorValues['instance_url'],\n ];\n }\n\n /**\n * Todo: this should check the `getHubId` matches the parent crm configuration.\n */\n private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array\n {\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $providerUser->getHubId(),\n 'crm_base_url' => $providerUser->toArray()['hub_domain'],\n ];\n }\n\n /**\n * Todo: this should check the `getCompanyId` matches the parent crm configuration.\n */\n private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $rawUserData['data']['company_id'],\n 'crm_base_url' => 'https://' . $rawUserData['data']['company_domain'] . '.pipedrive.com',\n ];\n }\n\n private function mapGoogleUserData(GoogleUser $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($providerUser->getEmail()),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapSlackUserData(SlackResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getRealName(),\n ];\n }\n\n private function mapOfficeUserData(AzureResourceOwner $providerUser): array\n {\n $email = $providerUser->getUpn() ?? $providerUser->claim('email');\n\n $this->logger->info('[Office] User authenticated', $providerUser->toArray());\n\n $name = $providerUser->claim('name') ??\n $providerUser->getFirstName() . ' ' . $providerUser->getLastName();\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($email),\n 'name' => $name,\n ];\n }\n\n private function mapOutreachUserData(ResourceOwnerInterface $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n $socialProvider = $this->getProvider(SocialAccount::PROVIDER_OUTREACH);\n $url = 'https://api.outreach.io/api/v2/profiles/';\n\n try {\n $request = $socialProvider->getAuthenticatedRequest(\n 'get',\n $url . $rawUserData['meta']['user']['id'],\n $this->accessToken,\n );\n\n $response = $socialProvider->getParsedResponse($request);\n\n $this->logger->info('[Outreach] User authenticated', $response);\n } catch (Exception) {\n //Just ignore\n }\n\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapDialpadUserData(DialpadResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n // They need to be Super Admin to access the Company APIs.\n $this->logger->info('[Dialpad] User authenticated', $rawUserData);\n\n if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Dialpad Super Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapAircallUserData(AircallResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array\n {\n if ($providerUser->toArray()['data']['team_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Team Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapBullhornUserData(): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n\n private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n}","depth":4,"bounds":{"left":0.122340426,"top":0.14684756,"width":0.31083778,"height":0.85315245},"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Services;\n\n/**\n * @todo cleanup after #slack-oauth-v2\n */\n\nuse AdamPaterson\\OAuth2\\Client\\Provider\\SlackResourceOwner;\nuse Chadhutchins\\OAuth2\\Client\\Provider\\Slack;\nuse ChaseConey\\LaravelDatadogHelper\\Datadog;\nuse Daniti\\OAuth2\\Client\\Provider\\Pipedrive;\nuse Daniti\\OAuth2\\Client\\Provider\\PipedriveResourceOwner;\nuse Exception;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpot;\nuse Flipbox\\OAuth2\\Client\\Provider\\HubSpotResourceOwner;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Auth\\AuthenticationException;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Jiminny\\Component\\Encryption\\EncryptedTokenManager;\nuse Jiminny\\Events\\Users\\CrmAccountReconnected;\nuse Jiminny\\Events\\Users\\SocialAccountConnected;\nuse Jiminny\\Events\\Users\\SocialAccountDisconnected;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\InvalidEnumException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Notifications\\SlackBotAdded;\nuse Jiminny\\OAuth2\\Client\\Provider\\Aircall;\nuse Jiminny\\OAuth2\\Client\\Provider\\AircallResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Bullhorn;\nuse Jiminny\\OAuth2\\Client\\Provider\\Dialpad;\nuse Jiminny\\OAuth2\\Client\\Provider\\DialpadResourceOwner;\nuse Jiminny\\OAuth2\\Client\\Provider\\Salesloft;\nuse Jiminny\\OAuth2\\Client\\Provider\\SalesloftResourceOwner;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\Talkdesk;\nuse Jiminny\\Services\\Activity\\Talkdesk\\Provider\\TalkdeskResourceOwner;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\Zoom;\nuse Jiminny\\Services\\Activity\\Zoom\\Provider\\ZoomResourceOwner;\nuse Jiminny\\Services\\OAuth2\\Provider\\BasicAuth;\nuse Jiminny\\Services\\OAuth2\\Provider\\Outreach;\nuse JsonException;\nuse League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider;\nuse League\\OAuth2\\Client\\Provider\\AbstractProvider;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Provider\\Google;\nuse League\\OAuth2\\Client\\Provider\\GoogleUser;\nuse League\\OAuth2\\Client\\Provider\\LinkedIn;\nuse League\\OAuth2\\Client\\Provider\\LinkedInResourceOwner;\nuse League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse League\\OAuth2\\Client\\Token\\AccessTokenInterface;\nuse libphonenumber\\NumberParseException;\nuse libphonenumber\\PhoneNumberFormat;\nuse libphonenumber\\PhoneNumberUtil;\nuse LogicException;\nuse Psr\\Log\\LoggerInterface;\nuse Random\\RandomException;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\Salesforce;\nuse Stevenmaguire\\OAuth2\\Client\\Provider\\SalesforceResourceOwner;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\nuse TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner;\nuse Throwable;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingCentral;\nuse TMannherz\\OAuth2\\Client\\Provider\\RingcentralResourceOwner;\n\nclass SocialAccountService\n{\n /**\n * Get a fresh tokens 5 minutes before it expires\n * That should minimise the number of failed requests due to expired token\n * for long-running jobs that reuse the same token for pulling lots of data.\n */\n private const int REFRESH_OFFSET_MIN = 5;\n\n private const string TOKEN_STATE_FETCH = 'fetch';\n private const string TOKEN_STATE_REFRESH = 'refresh';\n private const string TOKEN_RESULT_ATTEMPT = 'attempt';\n private const string TOKEN_RESULT_SUCCESS = 'success';\n private const string TOKEN_RESULT_FAILURE = 'failure';\n\n private ?AccessTokenInterface $accessToken = null;\n private ?string $token = null;\n private ?string $refreshToken = null;\n private ?int $expires = null;\n private ?string $countryCode = null;\n private ?string $timezone = null;\n private ?array $vendorValues = null;\n\n private ?int $refreshTokenExpires = null;\n\n public function __construct(\n private readonly EncryptedTokenManager $encryptedTokenManager,\n private readonly LoggerInterface $logger,\n private readonly PhoneNumberUtil $phoneNumberUtil,\n private readonly Dispatcher $eventDispatcher,\n ) {\n }\n\n public function setVendorValues(array $values): void\n {\n $this->vendorValues = $values;\n }\n\n public function setAccessToken(AccessTokenInterface $accessToken): void\n {\n $this->accessToken = $accessToken;\n // Todo: Also set these other params from this token e.g. refreshToken\n }\n\n public function setToken(?string $token): void\n {\n $this->token = $token;\n }\n\n public function setRefreshToken(?string $refreshToken): void\n {\n $this->refreshToken = $refreshToken;\n }\n\n public function setCountryCode(string $countryCode): void\n {\n $this->countryCode = $countryCode;\n }\n\n public function setTimezone(string $timezone): void\n {\n $this->timezone = $timezone;\n }\n\n public function setExpires(?int $expiry): void\n {\n $this->expires = $expiry;\n }\n\n public function setRefreshTokenExpires(array $values): void\n {\n $this->refreshTokenExpires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getProvider(string $provider): AbstractProvider\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n return new LinkedIn(config('services.linkedin'));\n\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n $socialProvider = new LinkedIn(config('services.linkedin-conference'));\n $socialProvider->withFields([\n 'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',\n ]);\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_SALESFORCE:\n return new Salesforce(config('services.salesforce'));\n\n case SocialAccount::PROVIDER_GOOGLE:\n return new Google(config('services.google'));\n\n case SocialAccount::PROVIDER_SLACK:\n return new Slack(config('services.slack'));\n\n case SocialAccount::PROVIDER_OFFICE:\n $config = config('services.office');\n\n // Convert string scope to array format expected by Azure provider\n if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {\n $config['scopes'] = array_filter(preg_split('/\\s+/', trim($config['scope'])));\n unset($config['scope']);\n }\n\n $socialProvider = new Azure($config);\n $socialProvider->urlAPI = 'https://graph.microsoft.com/v1.0/';\n $socialProvider->API_VERSION = '1.0';\n $socialProvider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;\n\n return $socialProvider;\n\n case SocialAccount::PROVIDER_HUBSPOT:\n return new HubSpot(config('services.hubspot'));\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n return new Pipedrive(config('services.pipedrive'));\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n return new Zoom(config('services.zoom-phone'));\n\n case SocialAccount::PROVIDER_OUTREACH:\n return new Outreach(config('services.outreach'));\n\n case SocialAccount::PROVIDER_SALESLOFT:\n return new Salesloft(config('services.salesloft'));\n\n case SocialAccount::PROVIDER_AIRCALL:\n return new Aircall(config('services.aircall'));\n\n case SocialAccount::PROVIDER_DIALPAD:\n return new Dialpad(config('services.dialpad'));\n\n case SocialAccount::PROVIDER_GONG:\n return new BasicAuth(config('services.gong'));\n\n case SocialAccount::PROVIDER_CLOSE:\n return new BasicAuth(config('services.close'));\n\n case SocialAccount::PROVIDER_AVAYA:\n // Avaya is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.avaya'));\n\n case SocialAccount::PROVIDER_TELUS:\n // Telus is owned by RingCentral and may operate under the same API\n return new RingCentral(config('services.telus'));\n\n case SocialAccount::PROVIDER_RINGCENTRAL:\n return new RingCentral(config('services.ringcentral'));\n\n case SocialAccount::PROVIDER_BULLHORN:\n return new Bullhorn(config('services.bullhorn'));\n\n case SocialAccount::PROVIDER_TALKDESK:\n return new Talkdesk(config('services.talkdesk'), [\n // Automatically concatenate Basic token to AuthToken requests\n 'optionProvider' => new HttpBasicAuthOptionProvider(),\n ]);\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n /**\n *\n *\n * @throws Exception\n */\n public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array\n {\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n /** @var LinkedInResourceOwner $providerUser */\n return $this->mapLinkedInUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESFORCE:\n /** @var SalesforceResourceOwner $providerUser */\n return $this->mapSalesforceUserData($providerUser);\n\n case SocialAccount::PROVIDER_HUBSPOT:\n /** @var HubSpotResourceOwner $providerUser */\n return $this->mapHubSpotUserData($providerUser);\n\n case SocialAccount::PROVIDER_PIPEDRIVE:\n /** @var PipedriveResourceOwner $providerUser */\n return $this->mapPipedriveUserData($providerUser);\n\n case SocialAccount::PROVIDER_GOOGLE:\n /** @var GoogleUser $providerUser */\n return $this->mapGoogleUserData($providerUser);\n\n case SocialAccount::PROVIDER_SLACK:\n /** @var SlackResourceOwner $providerUser */\n return $this->mapSlackUserData($providerUser);\n\n case SocialAccount::PROVIDER_OFFICE:\n /** @var AzureResourceOwner $providerUser */\n return $this->mapOfficeUserData($providerUser);\n\n case SocialAccount::PROVIDER_OUTREACH:\n return $this->mapOutreachUserData($providerUser);\n\n case SocialAccount::PROVIDER_DIALPAD:\n /** @var DialpadResourceOwner $providerUser*/\n return $this->mapDialpadUserData($providerUser);\n\n case SocialAccount::PROVIDER_AIRCALL:\n /** @var AircallResourceOwner $providerUser */\n return $this->mapAircallUserData($providerUser);\n\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n /** @var ZoomResourceOwner $providerUser */\n return $this->mapZoomPhoneUserData($providerUser);\n\n case SocialAccount::PROVIDER_SALESLOFT:\n /** @var SalesloftResourceOwner $providerUser */\n return $this->mapSalesloftUserData($providerUser);\n\n case SocialAccount::PROVIDER_BULLHORN:\n return $this->mapBullhornUserData();\n\n case SocialAccount::PROVIDER_TALKDESK:\n /** @var TalkdeskResourceOwner $providerUser */\n return $this->mapTalkdeskUserData($providerUser);\n\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_TELUS:\n /** @var RingcentralResourceOwner $providerUser */\n return $this->mapRingCentralUserData($providerUser);\n default:\n throw new InvalidEnumException('Unknown provider.');\n }\n }\n\n /**\n * Returns a new random string to use as the state parameter in an\n * authorization flow.\n *\n * @param int $length Length of the random string to be generated.\n *\n * @throws RandomException\n */\n public function getRandomState(int $length = 32): string\n {\n // Converting bytes to hex will always double length. Hence, we can reduce\n // the amount of bytes by half to produce the correct length.\n return bin2hex(random_bytes($length / 2));\n }\n\n private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount\n {\n return SocialAccount::where([\n 'provider' => $provider,\n 'provider_user_id' => $providerUser->getId(),\n ])->first();\n }\n\n /**\n * Based on the provider data, try to match to a sociable entity based on email.\n * If a match is made, create the social account under that entity.\n *\n * @throws AuthenticationException\n */\n public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User\n {\n $account = $this->getAssociation($provider, $providerUser);\n if ($account !== null && $account->hasUser()) {\n return $account->getUser();\n }\n $userData = $this->mapUserData($provider, $providerUser);\n\n // Check if we have an actual user with this email.\n /** @var User|null $user */\n $user = User::where('email', $userData['email'])->first();\n\n // If the user is trying to connect to LinkedIn, don't allow this.\n // Todo: have an interstitial page to perform 2FA to connect.\n if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {\n throw new AuthenticationException(\n 'Sorry, you\\'ll need to login through your Jiminny account to access the Conference.',\n );\n }\n\n return $user;\n }\n\n /**\n * @throws JsonException\n */\n public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount\n {\n /** @var SocialAccount $account */\n $account = $user->socialAccounts()->firstOrNew([\n 'provider' => $provider,\n ]);\n\n $account->fill([\n 'provider_user_id' => $providerUser->getId(),\n 'provider_user_token' => $this->token,\n 'expires' => $this->expires,\n 'state' => SocialAccount::STATE_CONNECTED,\n 'retry_after' => null,\n ]);\n\n // This is an optional parameter, don't overwrite the existing one with null if we don't get it.\n if ($this->refreshToken) {\n $account->fill([\n 'provider_refresh_token' => $this->refreshToken,\n 'refresh_token_expires' => $this->refreshTokenExpires,\n ]);\n }\n\n if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {\n $account->fill([\n 'auth_scope' => is_scalar($this->vendorValues['scope'])\n ? $this->vendorValues['scope']\n : json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),\n ]);\n } else {\n $account->fill([\n 'auth_scope' => null,\n ]);\n\n $this->logger->warning(\n '[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',\n // pulling directly from the token, just to avoid potential masking of the issue\n ['token_values' => $this->accessToken->getValues()],\n );\n }\n\n $account->save();\n\n // Association can be from an updated token so don't re-announce this.\n if (\n $account->wasRecentlyCreated\n && in_array($provider, SocialAccount::CRM_PROVIDERS, true)\n && $provider !== SocialAccount::PROVIDER_HUBSPOT\n && $providerUser->getId() !== null\n ) {\n $crm = $user->team->crm;\n $data = [\n 'crm_configuration_id' => $crm->id,\n 'log_notes' => Profile::LOG_NOTE_ENHANCED,\n ];\n\n $crmProfile = $user->crmProfile()->where([\n 'crm_provider_id' => $providerUser->getId(),\n ])->first();\n\n $user->crmProfile()->updateOrCreate([\n 'crm_provider_id' => $providerUser->getId(),\n ], $data);\n\n // If updated, fire reconnected\n if ($crmProfile !== null) {\n $this->eventDispatcher->dispatch(new CrmAccountReconnected($account));\n }\n }\n\n $this->eventDispatcher->dispatch(new SocialAccountConnected($account));\n\n return $account;\n }\n\n public function integrate(string $provider, User $user, Team $team): void\n {\n if ($provider === SocialAccount::PROVIDER_SLACK) {\n if (! isset($this->vendorValues['ok'])\n || $this->vendorValues['ok'] !== true\n || ! isset($this->vendorValues['token_type'])\n || $this->vendorValues['token_type'] !== 'bot'\n ) {\n // code expects V2 token, which differs slightly from V1\n throw new LogicException('Invalid token received from Slack OAuth v2 API');\n }\n\n $webhook = $this->vendorValues['incoming_webhook'];\n\n $slackTeamId = $this->vendorValues['team']['id'];\n\n $botData = [\n 'channel' => $webhook['channel'],\n 'channel_id' => $webhook['channel_id'],\n 'config_url' => $webhook['configuration_url'],\n 'webhook_url' => $webhook['url'],\n 'bot_user_id' => $this->vendorValues['bot_user_id'],\n 'bot_access_token' => $this->accessToken->getToken(),\n ];\n\n $slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);\n\n if ($slackBot->wasRecentlyCreated) {\n // Send Slack notification.\n $user->notify(new SlackBotAdded());\n }\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);\n\n $this->logger->info('[SocialAccountService] Fetching token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $account->refresh();\n\n if (\n ! $forceRefresh\n && ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))\n ) {\n $this->logger->info('[SocialAccountService] Token retrieved', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);\n\n return $this->encryptedTokenManager->getAccessToken($account);\n }\n\n try {\n $this->logger->info('[SocialAccountService] Token needs refreshing', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n return $this->refreshToken($account, $forceRefresh);\n } catch (IdentityProviderException $exception) {\n $responseBody = $exception->getResponseBody();\n\n if ($responseBody instanceof Response) {\n $responseBody = $responseBody->getBody();\n }\n\n if (is_object($responseBody) && method_exists($responseBody, '__toString')) {\n $responseBody = $responseBody->__toString();\n }\n\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'responseBody' => $responseBody,\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n } catch (SocialAccountTokenInvalidException $exception) {\n $this->logger->error('[SocialAccountService] Cannot obtain token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception::class,\n 'errorMessage' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {\n $this->logger->error('[SocialAccountService] Full refresh required', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n // Something terrible happened their token, they need to reconnect.\n $account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);\n $this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));\n }\n\n throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);\n }\n }\n\n public function refreshSocialAccountToken(SocialAccount $socialAccount): void\n {\n try {\n $this->getToken($socialAccount);\n } catch (Throwable $e) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $socialAccount->getId(),\n 'provider' => $socialAccount->getProviderName(),\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * @throws SocialAccountTokenInvalidException\n */\n public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken\n {\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);\n\n $newToken = null;\n\n Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)\n ->block(8, function () use ($account, $forceRefresh, &$newToken): void {\n try {\n $account->refresh();\n $token = $this->encryptedTokenManager->getAccessToken($account);\n\n if (! $forceRefresh && $this->hasValidToken($account)) {\n $newToken = $token;\n\n return;\n }\n\n if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {\n $this->logger->error('[SocialAccountService] Refresh token not found', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n\n $this->sendTokenStatsToDatadog(\n $account,\n self::TOKEN_STATE_REFRESH,\n self::TOKEN_RESULT_FAILURE,\n );\n\n throw new SocialAccountTokenInvalidException(\n 'Refresh token is not set, re-connection required.',\n );\n }\n\n $this->logger->info('[SocialAccountService] Refreshing token from provider', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),\n 'state' => $account->getState(),\n ]);\n\n $newToken = $this->getProvider($account->provider)\n ->getAccessToken('refresh_token', [\n 'refresh_token' => $token->getRefreshToken(),\n ])\n ;\n\n if ($newToken->getToken() === $token->getToken()) {\n $this->logger->info('[SocialAccountService] Refreshed with an identical token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n ]);\n }\n } catch (ConnectException | RequestException $exception) {\n $this->logger->error('[SocialAccountService] Failed to refresh token', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'error' => $exception->getMessage(),\n ]);\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);\n\n // This usually occurs due to SSL errors.\n throw new SocialAccountTokenInvalidException(\n 'Token could not be refreshed.',\n $exception->getCode(),\n $exception,\n );\n }\n\n $account->provider_user_token = $newToken->getToken();\n $account->expires = $newToken->getExpires();\n $account->state = SocialAccount::STATE_CONNECTED;\n\n if ($newToken->getRefreshToken()) {\n $account->provider_refresh_token = $newToken->getRefreshToken();\n $values = $newToken->getValues();\n $account->refresh_token_expires = isset($values['refresh_token_expires_in'])\n ? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()\n : null;\n }\n\n $account->save();\n });\n\n $this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);\n\n $this->logger->info('[SocialAccountService] Token refreshed', [\n 'socialAccountId' => $account->id,\n 'provider' => $account->getProviderName(),\n 'state' => $account->getState(),\n ]);\n\n return $newToken;\n }\n\n /**\n * @return string[]\n */\n private function getAccessScope(string $provider): array\n {\n $scopes = [];\n $providerScopes = config('services.' . $provider . '.scope');\n\n if ($providerScopes) {\n $scopes = preg_split('/\\s+/', $providerScopes);\n }\n\n return $scopes;\n }\n\n /**\n * @throws InvalidEnumException\n */\n public function getAuthorizationOptions(string $provider): array\n {\n $scopes = ['scope' => $this->getAccessScope($provider)];\n\n switch ($provider) {\n case SocialAccount::PROVIDER_LINKEDIN:\n case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:\n case SocialAccount::PROVIDER_SALESFORCE:\n case SocialAccount::PROVIDER_HUBSPOT:\n case SocialAccount::PROVIDER_OUTREACH:\n case SocialAccount::PROVIDER_SALESLOFT:\n case SocialAccount::PROVIDER_ZOOM_PHONE:\n case SocialAccount::PROVIDER_PIPEDRIVE:\n case SocialAccount::PROVIDER_SLACK:\n case SocialAccount::PROVIDER_AIRCALL:\n case SocialAccount::PROVIDER_BULLHORN:\n case SocialAccount::PROVIDER_RINGCENTRAL:\n case SocialAccount::PROVIDER_AVAYA:\n case SocialAccount::PROVIDER_TELUS:\n case SocialAccount::PROVIDER_DIALPAD:\n case SocialAccount::PROVIDER_TALKDESK:\n return $scopes;\n\n case SocialAccount::PROVIDER_OFFICE:\n return $scopes + [\n 'access_type' => 'offline',\n ];\n\n case SocialAccount::PROVIDER_GOOGLE:\n return $scopes + [\n 'access_type' => 'offline',\n 'include_granted_scopes' => 'true',\n 'approval_prompt' => null,\n ];\n\n default:\n throw new InvalidEnumException();\n }\n }\n\n private function tokenDoesNotExpire(SocialAccount $account): bool\n {\n return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);\n }\n\n private function hasValidToken(SocialAccount $account): bool\n {\n return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();\n }\n\n private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void\n {\n Datadog::increment('jiminny.access_token', 1, [\n 'provider' => $account->getProviderName(),\n 'state' => $state,\n 'result' => $result,\n ]);\n }\n\n private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),\n ];\n }\n\n private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n try {\n $parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);\n $number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);\n } catch (NumberParseException) {\n $number = null;\n }\n\n // Todo: this should check the `organization_id` matches the parent crm configuration.\n\n return [\n 'country_code' => $this->countryCode,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),\n 'phone' => $number,\n 'crm_provider_id' => $rawUserData['organization_id'],\n 'crm_base_url' => $this->vendorValues['instance_url'],\n ];\n }\n\n /**\n * Todo: this should check the `getHubId` matches the parent crm configuration.\n */\n private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array\n {\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $providerUser->getHubId(),\n 'crm_base_url' => $providerUser->toArray()['hub_domain'],\n ];\n }\n\n /**\n * Todo: this should check the `getCompanyId` matches the parent crm configuration.\n */\n private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'crm_provider_id' => $rawUserData['data']['company_id'],\n 'crm_base_url' => 'https://' . $rawUserData['data']['company_domain'] . '.pipedrive.com',\n ];\n }\n\n private function mapGoogleUserData(GoogleUser $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($providerUser->getEmail()),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapSlackUserData(SlackResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getRealName(),\n ];\n }\n\n private function mapOfficeUserData(AzureResourceOwner $providerUser): array\n {\n $email = $providerUser->getUpn() ?? $providerUser->claim('email');\n\n $this->logger->info('[Office] User authenticated', $providerUser->toArray());\n\n $name = $providerUser->claim('name') ??\n $providerUser->getFirstName() . ' ' . $providerUser->getLastName();\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => strtolower($email),\n 'name' => $name,\n ];\n }\n\n private function mapOutreachUserData(ResourceOwnerInterface $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n $socialProvider = $this->getProvider(SocialAccount::PROVIDER_OUTREACH);\n $url = 'https://api.outreach.io/api/v2/profiles/';\n\n try {\n $request = $socialProvider->getAuthenticatedRequest(\n 'get',\n $url . $rawUserData['meta']['user']['id'],\n $this->accessToken,\n );\n\n $response = $socialProvider->getParsedResponse($request);\n\n $this->logger->info('[Outreach] User authenticated', $response);\n } catch (Exception) {\n //Just ignore\n }\n\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapDialpadUserData(DialpadResourceOwner $providerUser): array\n {\n $rawUserData = $providerUser->toArray();\n\n // They need to be Super Admin to access the Company APIs.\n $this->logger->info('[Dialpad] User authenticated', $rawUserData);\n\n if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Dialpad Super Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapAircallUserData(AircallResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array\n {\n return[\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n /**\n * @throws ActivityProviderException\n */\n private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array\n {\n if ($providerUser->toArray()['data']['team_admin'] === false) {\n throw new ActivityProviderException(\n \"Sorry, you'll need to be a Team Admin to add this integration.\",\n );\n }\n\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n ];\n }\n\n private function mapBullhornUserData(): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n ];\n }\n\n private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n\n private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array\n {\n return [\n 'country_code' => $this->countryCode,\n 'phone' => null,\n 'timezone' => $this->timezone,\n 'email' => $providerUser->getEmail(),\n 'name' => $providerUser->getName(),\n 'id' => $providerUser->getId(),\n ];\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8948022234986695786
|
-8880471945877483717
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
6
8
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services;
/**
* @todo cleanup after #slack-oauth-v2
*/
use AdamPaterson\OAuth2\Client\Provider\SlackResourceOwner;
use Chadhutchins\OAuth2\Client\Provider\Slack;
use ChaseConey\LaravelDatadogHelper\Datadog;
use Daniti\OAuth2\Client\Provider\Pipedrive;
use Daniti\OAuth2\Client\Provider\PipedriveResourceOwner;
use Exception;
use Flipbox\OAuth2\Client\Provider\HubSpot;
use Flipbox\OAuth2\Client\Provider\HubSpotResourceOwner;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Jiminny\Component\Encryption\EncryptedTokenManager;
use Jiminny\Events\Users\CrmAccountReconnected;
use Jiminny\Events\Users\SocialAccountConnected;
use Jiminny\Events\Users\SocialAccountDisconnected;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\InvalidEnumException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Notifications\SlackBotAdded;
use Jiminny\OAuth2\Client\Provider\Aircall;
use Jiminny\OAuth2\Client\Provider\AircallResourceOwner;
use Jiminny\OAuth2\Client\Provider\Bullhorn;
use Jiminny\OAuth2\Client\Provider\Dialpad;
use Jiminny\OAuth2\Client\Provider\DialpadResourceOwner;
use Jiminny\OAuth2\Client\Provider\Salesloft;
use Jiminny\OAuth2\Client\Provider\SalesloftResourceOwner;
use Jiminny\Services\Activity\Talkdesk\Provider\Talkdesk;
use Jiminny\Services\Activity\Talkdesk\Provider\TalkdeskResourceOwner;
use Jiminny\Services\Activity\Zoom\Provider\Zoom;
use Jiminny\Services\Activity\Zoom\Provider\ZoomResourceOwner;
use Jiminny\Services\OAuth2\Provider\BasicAuth;
use Jiminny\Services\OAuth2\Provider\Outreach;
use JsonException;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\GoogleUser;
use League\OAuth2\Client\Provider\LinkedIn;
use League\OAuth2\Client\Provider\LinkedInResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Psr\Log\LoggerInterface;
use Random\RandomException;
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
use Stevenmaguire\OAuth2\Client\Provider\SalesforceResourceOwner;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Provider\AzureResourceOwner;
use Throwable;
use TMannherz\OAuth2\Client\Provider\RingCentral;
use TMannherz\OAuth2\Client\Provider\RingcentralResourceOwner;
class SocialAccountService
{
/**
* Get a fresh tokens 5 minutes before it expires
* That should minimise the number of failed requests due to expired token
* for long-running jobs that reuse the same token for pulling lots of data.
*/
private const int REFRESH_OFFSET_MIN = 5;
private const string TOKEN_STATE_FETCH = 'fetch';
private const string TOKEN_STATE_REFRESH = 'refresh';
private const string TOKEN_RESULT_ATTEMPT = 'attempt';
private const string TOKEN_RESULT_SUCCESS = 'success';
private const string TOKEN_RESULT_FAILURE = 'failure';
private ?AccessTokenInterface $accessToken = null;
private ?string $token = null;
private ?string $refreshToken = null;
private ?int $expires = null;
private ?string $countryCode = null;
private ?string $timezone = null;
private ?array $vendorValues = null;
private ?int $refreshTokenExpires = null;
public function __construct(
private readonly EncryptedTokenManager $encryptedTokenManager,
private readonly LoggerInterface $logger,
private readonly PhoneNumberUtil $phoneNumberUtil,
private readonly Dispatcher $eventDispatcher,
) {
}
public function setVendorValues(array $values): void
{
$this->vendorValues = $values;
}
public function setAccessToken(AccessTokenInterface $accessToken): void
{
$this->accessToken = $accessToken;
// Todo: Also set these other params from this token e.g. refreshToken
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function setRefreshToken(?string $refreshToken): void
{
$this->refreshToken = $refreshToken;
}
public function setCountryCode(string $countryCode): void
{
$this->countryCode = $countryCode;
}
public function setTimezone(string $timezone): void
{
$this->timezone = $timezone;
}
public function setExpires(?int $expiry): void
{
$this->expires = $expiry;
}
public function setRefreshTokenExpires(array $values): void
{
$this->refreshTokenExpires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
/**
* @throws InvalidEnumException
*/
public function getProvider(string $provider): AbstractProvider
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
return new LinkedIn(config('services.linkedin'));
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
$socialProvider = new LinkedIn(config('services.linkedin-conference'));
$socialProvider->withFields([
'id', 'localizedFirstName', 'localizedLastName', 'profilePicture(displayImage~:playableStreams)',
]);
return $socialProvider;
case SocialAccount::PROVIDER_SALESFORCE:
return new Salesforce(config('services.salesforce'));
case SocialAccount::PROVIDER_GOOGLE:
return new Google(config('services.google'));
case SocialAccount::PROVIDER_SLACK:
return new Slack(config('services.slack'));
case SocialAccount::PROVIDER_OFFICE:
$config = config('services.office');
// Convert string scope to array format expected by Azure provider
if (isset($config['scope']) && is_string($config['scope']) && ! empty(trim($config['scope']))) {
$config['scopes'] = array_filter(preg_split('/\s+/', trim($config['scope'])));
unset($config['scope']);
}
$socialProvider = new Azure($config);
$socialProvider->urlAPI = '[URL_WITH_CREDENTIALS] Exception
*/
public function mapUserData(string $provider, ResourceOwnerInterface $providerUser): array
{
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
/** @var LinkedInResourceOwner $providerUser */
return $this->mapLinkedInUserData($providerUser);
case SocialAccount::PROVIDER_SALESFORCE:
/** @var SalesforceResourceOwner $providerUser */
return $this->mapSalesforceUserData($providerUser);
case SocialAccount::PROVIDER_HUBSPOT:
/** @var HubSpotResourceOwner $providerUser */
return $this->mapHubSpotUserData($providerUser);
case SocialAccount::PROVIDER_PIPEDRIVE:
/** @var PipedriveResourceOwner $providerUser */
return $this->mapPipedriveUserData($providerUser);
case SocialAccount::PROVIDER_GOOGLE:
/** @var GoogleUser $providerUser */
return $this->mapGoogleUserData($providerUser);
case SocialAccount::PROVIDER_SLACK:
/** @var SlackResourceOwner $providerUser */
return $this->mapSlackUserData($providerUser);
case SocialAccount::PROVIDER_OFFICE:
/** @var AzureResourceOwner $providerUser */
return $this->mapOfficeUserData($providerUser);
case SocialAccount::PROVIDER_OUTREACH:
return $this->mapOutreachUserData($providerUser);
case SocialAccount::PROVIDER_DIALPAD:
/** @var DialpadResourceOwner $providerUser*/
return $this->mapDialpadUserData($providerUser);
case SocialAccount::PROVIDER_AIRCALL:
/** @var AircallResourceOwner $providerUser */
return $this->mapAircallUserData($providerUser);
case SocialAccount::PROVIDER_ZOOM_PHONE:
/** @var ZoomResourceOwner $providerUser */
return $this->mapZoomPhoneUserData($providerUser);
case SocialAccount::PROVIDER_SALESLOFT:
/** @var SalesloftResourceOwner $providerUser */
return $this->mapSalesloftUserData($providerUser);
case SocialAccount::PROVIDER_BULLHORN:
return $this->mapBullhornUserData();
case SocialAccount::PROVIDER_TALKDESK:
/** @var TalkdeskResourceOwner $providerUser */
return $this->mapTalkdeskUserData($providerUser);
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_TELUS:
/** @var RingcentralResourceOwner $providerUser */
return $this->mapRingCentralUserData($providerUser);
default:
throw new InvalidEnumException('Unknown provider.');
}
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
*
* @throws RandomException
*/
public function getRandomState(int $length = 32): string
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return bin2hex(random_bytes($length / 2));
}
private function getAssociation(string $provider, ResourceOwnerInterface $providerUser): ?SocialAccount
{
return SocialAccount::where([
'provider' => $provider,
'provider_user_id' => $providerUser->getId(),
])->first();
}
/**
* Based on the provider data, try to match to a sociable entity based on email.
* If a match is made, create the social account under that entity.
*
* @throws AuthenticationException
*/
public function getSociable(string $provider, ResourceOwnerInterface $providerUser): ?User
{
$account = $this->getAssociation($provider, $providerUser);
if ($account !== null && $account->hasUser()) {
return $account->getUser();
}
$userData = $this->mapUserData($provider, $providerUser);
// Check if we have an actual user with this email.
/** @var User|null $user */
$user = User::where('email', $userData['email'])->first();
// If the user is trying to connect to LinkedIn, don't allow this.
// Todo: have an interstitial page to perform 2FA to connect.
if ($provider === SocialAccount::PROVIDER_LINKEDIN_CONFERENCE) {
throw new AuthenticationException(
'Sorry, you\'ll need to login through your Jiminny account to access the Conference.',
);
}
return $user;
}
/**
* @throws JsonException
*/
public function associate(string $provider, ResourceOwnerInterface $providerUser, User $user): SocialAccount
{
/** @var SocialAccount $account */
$account = $user->socialAccounts()->firstOrNew([
'provider' => $provider,
]);
$account->fill([
'provider_user_id' => $providerUser->getId(),
'provider_user_token' => $this->token,
'expires' => $this->expires,
'state' => SocialAccount::STATE_CONNECTED,
'retry_after' => null,
]);
// This is an optional parameter, don't overwrite the existing one with null if we don't get it.
if ($this->refreshToken) {
$account->fill([
'provider_refresh_token' => $this->refreshToken,
'refresh_token_expires' => $this->refreshTokenExpires,
]);
}
if (is_array($this->vendorValues) && array_key_exists('scope', $this->vendorValues) && ! empty($this->vendorValues['scope'])) {
$account->fill([
'auth_scope' => is_scalar($this->vendorValues['scope'])
? $this->vendorValues['scope']
: json_encode($this->vendorValues['scope'], JSON_THROW_ON_ERROR),
]);
} else {
$account->fill([
'auth_scope' => null,
]);
$this->logger->warning(
'[OAuth permissions] OAuth callback is not providing information about scopes or it is in different format than expected',
// pulling directly from the token, just to avoid potential masking of the issue
['token_values' => $this->accessToken->getValues()],
);
}
$account->save();
// Association can be from an updated token so don't re-announce this.
if (
$account->wasRecentlyCreated
&& in_array($provider, SocialAccount::CRM_PROVIDERS, true)
&& $provider !== SocialAccount::PROVIDER_HUBSPOT
&& $providerUser->getId() !== null
) {
$crm = $user->team->crm;
$data = [
'crm_configuration_id' => $crm->id,
'log_notes' => Profile::LOG_NOTE_ENHANCED,
];
$crmProfile = $user->crmProfile()->where([
'crm_provider_id' => $providerUser->getId(),
])->first();
$user->crmProfile()->updateOrCreate([
'crm_provider_id' => $providerUser->getId(),
], $data);
// If updated, fire reconnected
if ($crmProfile !== null) {
$this->eventDispatcher->dispatch(new CrmAccountReconnected($account));
}
}
$this->eventDispatcher->dispatch(new SocialAccountConnected($account));
return $account;
}
public function integrate(string $provider, User $user, Team $team): void
{
if ($provider === SocialAccount::PROVIDER_SLACK) {
if (! isset($this->vendorValues['ok'])
|| $this->vendorValues['ok'] !== true
|| ! isset($this->vendorValues['token_type'])
|| $this->vendorValues['token_type'] !== 'bot'
) {
// code expects V2 token, which differs slightly from V1
throw new LogicException('Invalid token received from Slack OAuth v2 API');
}
$webhook = $this->vendorValues['incoming_webhook'];
$slackTeamId = $this->vendorValues['team']['id'];
$botData = [
'channel' => $webhook['channel'],
'channel_id' => $webhook['channel_id'],
'config_url' => $webhook['configuration_url'],
'webhook_url' => $webhook['url'],
'bot_user_id' => $this->vendorValues['bot_user_id'],
'bot_access_token' => $this->accessToken->getToken(),
];
$slackBot = $team->slackBot()->updateOrCreate(['slack_team_id' => $slackTeamId], $botData);
if ($slackBot->wasRecentlyCreated) {
// Send Slack notification.
$user->notify(new SlackBotAdded());
}
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function getToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_ATTEMPT);
$this->logger->info('[SocialAccountService] Fetching token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$account->refresh();
if (
! $forceRefresh
&& ($this->tokenDoesNotExpire($account) || $this->hasValidToken($account))
) {
$this->logger->info('[SocialAccountService] Token retrieved', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_FETCH, self::TOKEN_RESULT_SUCCESS);
return $this->encryptedTokenManager->getAccessToken($account);
}
try {
$this->logger->info('[SocialAccountService] Token needs refreshing', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
return $this->refreshToken($account, $forceRefresh);
} catch (IdentityProviderException $exception) {
$responseBody = $exception->getResponseBody();
if ($responseBody instanceof Response) {
$responseBody = $responseBody->getBody();
}
if (is_object($responseBody) && method_exists($responseBody, '__toString')) {
$responseBody = $responseBody->__toString();
}
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'responseBody' => $responseBody,
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
} catch (SocialAccountTokenInvalidException $exception) {
$this->logger->error('[SocialAccountService] Cannot obtain token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception::class,
'errorMessage' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
if ($account->state !== SocialAccount::STATE_FULL_REFRESH_REQUIRED) {
$this->logger->error('[SocialAccountService] Full refresh required', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
// Something terrible happened their token, they need to reconnect.
$account->update(['state' => SocialAccount::STATE_FULL_REFRESH_REQUIRED]);
$this->eventDispatcher->dispatch(new SocialAccountDisconnected($account));
}
throw new SocialAccountTokenInvalidException('Flow refresh required.', 1, $exception);
}
}
public function refreshSocialAccountToken(SocialAccount $socialAccount): void
{
try {
$this->getToken($socialAccount);
} catch (Throwable $e) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $socialAccount->getId(),
'provider' => $socialAccount->getProviderName(),
'reason' => $e->getMessage(),
]);
}
}
/**
* @throws SocialAccountTokenInvalidException
*/
public function refreshToken(SocialAccount $account, bool $forceRefresh = false): AccessToken
{
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_ATTEMPT);
$newToken = null;
Cache::lock(sprintf('oauth-refreshtoken-%s', $account->id), 10)
->block(8, function () use ($account, $forceRefresh, &$newToken): void {
try {
$account->refresh();
$token = $this->encryptedTokenManager->getAccessToken($account);
if (! $forceRefresh && $this->hasValidToken($account)) {
$newToken = $token;
return;
}
if (! $this->tokenDoesNotExpire($account) && ! $token->getRefreshToken()) {
$this->logger->error('[SocialAccountService] Refresh token not found', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
$this->sendTokenStatsToDatadog(
$account,
self::TOKEN_STATE_REFRESH,
self::TOKEN_RESULT_FAILURE,
);
throw new SocialAccountTokenInvalidException(
'Refresh token is not set, re-connection required.',
);
}
$this->logger->info('[SocialAccountService] Refreshing token from provider', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'refreshToken' => hash('sha256', $account->getProviderRefreshToken()),
'state' => $account->getState(),
]);
$newToken = $this->getProvider($account->provider)
->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
])
;
if ($newToken->getToken() === $token->getToken()) {
$this->logger->info('[SocialAccountService] Refreshed with an identical token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
]);
}
} catch (ConnectException | RequestException $exception) {
$this->logger->error('[SocialAccountService] Failed to refresh token', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'error' => $exception->getMessage(),
]);
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_FAILURE);
// This usually occurs due to SSL errors.
throw new SocialAccountTokenInvalidException(
'Token could not be refreshed.',
$exception->getCode(),
$exception,
);
}
$account->provider_user_token = $newToken->getToken();
$account->expires = $newToken->getExpires();
$account->state = SocialAccount::STATE_CONNECTED;
if ($newToken->getRefreshToken()) {
$account->provider_refresh_token = $newToken->getRefreshToken();
$values = $newToken->getValues();
$account->refresh_token_expires = isset($values['refresh_token_expires_in'])
? now()->addSeconds($values['refresh_token_expires_in'])->getTimestamp()
: null;
}
$account->save();
});
$this->sendTokenStatsToDatadog($account, self::TOKEN_STATE_REFRESH, self::TOKEN_RESULT_SUCCESS);
$this->logger->info('[SocialAccountService] Token refreshed', [
'socialAccountId' => $account->id,
'provider' => $account->getProviderName(),
'state' => $account->getState(),
]);
return $newToken;
}
/**
* @return string[]
*/
private function getAccessScope(string $provider): array
{
$scopes = [];
$providerScopes = config('services.' . $provider . '.scope');
if ($providerScopes) {
$scopes = preg_split('/\s+/', $providerScopes);
}
return $scopes;
}
/**
* @throws InvalidEnumException
*/
public function getAuthorizationOptions(string $provider): array
{
$scopes = ['scope' => $this->getAccessScope($provider)];
switch ($provider) {
case SocialAccount::PROVIDER_LINKEDIN:
case SocialAccount::PROVIDER_LINKEDIN_CONFERENCE:
case SocialAccount::PROVIDER_SALESFORCE:
case SocialAccount::PROVIDER_HUBSPOT:
case SocialAccount::PROVIDER_OUTREACH:
case SocialAccount::PROVIDER_SALESLOFT:
case SocialAccount::PROVIDER_ZOOM_PHONE:
case SocialAccount::PROVIDER_PIPEDRIVE:
case SocialAccount::PROVIDER_SLACK:
case SocialAccount::PROVIDER_AIRCALL:
case SocialAccount::PROVIDER_BULLHORN:
case SocialAccount::PROVIDER_RINGCENTRAL:
case SocialAccount::PROVIDER_AVAYA:
case SocialAccount::PROVIDER_TELUS:
case SocialAccount::PROVIDER_DIALPAD:
case SocialAccount::PROVIDER_TALKDESK:
return $scopes;
case SocialAccount::PROVIDER_OFFICE:
return $scopes + [
'access_type' => 'offline',
];
case SocialAccount::PROVIDER_GOOGLE:
return $scopes + [
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'approval_prompt' => null,
];
default:
throw new InvalidEnumException();
}
}
private function tokenDoesNotExpire(SocialAccount $account): bool
{
return in_array($account->provider, SocialAccount::PROVIDERS_WITHOUT_EXPIRY, true);
}
private function hasValidToken(SocialAccount $account): bool
{
return $account->expires > now()->addMinutes(self::REFRESH_OFFSET_MIN)->getTimestamp();
}
private function sendTokenStatsToDatadog(SocialAccount $account, string $state, string $result): void
{
Datadog::increment('jiminny.access_token', 1, [
'provider' => $account->getProviderName(),
'state' => $state,
'result' => $result,
]);
}
private function mapLinkedInUserData(LinkedInResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => sprintf('%s %s', $providerUser->getFirstName(), $providerUser->getLastName()),
];
}
private function mapSalesforceUserData(SalesforceResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
try {
$parsedNumber = $this->phoneNumberUtil->parse($rawUserData['mobile_phone'], $this->countryCode);
$number = $this->phoneNumberUtil->format($parsedNumber, PhoneNumberFormat::E164);
} catch (NumberParseException) {
$number = null;
}
// Todo: this should check the `organization_id` matches the parent crm configuration.
return [
'country_code' => $this->countryCode,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getFirstName() . ' ' . $providerUser->getLastName(),
'phone' => $number,
'crm_provider_id' => $rawUserData['organization_id'],
'crm_base_url' => $this->vendorValues['instance_url'],
];
}
/**
* Todo: this should check the `getHubId` matches the parent crm configuration.
*/
private function mapHubSpotUserData(HubSpotResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $providerUser->getHubId(),
'crm_base_url' => $providerUser->toArray()['hub_domain'],
];
}
/**
* Todo: this should check the `getCompanyId` matches the parent crm configuration.
*/
private function mapPipedriveUserData(PipedriveResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'crm_provider_id' => $rawUserData['data']['company_id'],
'crm_base_url' => '[URL_WITH_CREDENTIALS] ActivityProviderException
*/
private function mapDialpadUserData(DialpadResourceOwner $providerUser): array
{
$rawUserData = $providerUser->toArray();
// They need to be Super Admin to access the Company APIs.
$this->logger->info('[Dialpad] User authenticated', $rawUserData);
if (isset($rawUserData['is_super_admin']) && $rawUserData['is_super_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Dialpad Super Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapAircallUserData(AircallResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapZoomPhoneUserData(ZoomResourceOwner $providerUser): array
{
return[
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
/**
* @throws ActivityProviderException
*/
private function mapSalesloftUserData(SalesloftResourceOwner $providerUser): array
{
if ($providerUser->toArray()['data']['team_admin'] === false) {
throw new ActivityProviderException(
"Sorry, you'll need to be a Team Admin to add this integration.",
);
}
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
];
}
private function mapBullhornUserData(): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
];
}
private function mapTalkdeskUserData(TalkdeskResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
private function mapRingCentralUserData(RingcentralResourceOwner $providerUser): array
{
return [
'country_code' => $this->countryCode,
'phone' => null,
'timezone' => $this->timezone,
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'id' => $providerUser->getId(),
];
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
34717
|
1300
|
7
|
2026-05-13T11:34:56.999443+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-13/1778 /Users/lukas/.screenpipe/data/data/2026-05-13/1778672096999_m2.jpg...
|
PhpStorm
|
faVsco.js – ExtensionController.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
namespace Jiminny\Http\Controllers\Auth;
use Exception;
use Google\Service\Oauth2\Userinfo;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Contracts\InitialFrontendStateInterface;
use Jiminny\Component\Sidekick\SidekickService;
use Jiminny\Events\Auth\ChromeExtensionAuthenticated;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\HttpForbiddenException;
use Jiminny\Exceptions\HttpUnauthorizedException;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Guards\Sso;
use Jiminny\Http\Controllers\API\BaseController as Controller;
use Jiminny\Http\Responses\Api\Response;
use Jiminny\Http\Serializers\JsonSerializer;
use Jiminny\Jiminny;
use Jiminny\Models\Device;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Services\MeetingGenerator\Validators\OfficeTokenValidator;
use Jiminny\Services\SocialAccountService;
use Jiminny\Utils\StringUtil;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use TheNetworg\OAuth2\Client\Provider\Azure;
class ExtensionController extends Controller
{
/**
* Create a new controller instance.
*/
public function __construct(
Response $response,
private readonly SocialAccountService $socialAccountService,
private readonly OfficeTokenValidator $officeTokenValidator,
private readonly UserRepository $userRepository
) {
parent::__construct($response);
}
public function authenticate()
{
$this->request->validate([
'deviceType' => 'in:' . implode(',', Device::$enumTypes),
'deviceId' => 'uuid:devices',
'deviceVersion' => 'max:40',
]);
$this->response
->getManager()
->setSerializer(new JsonSerializer());
try {
$response = [
'message' => null,
];
$deviceType = $this->request->input('deviceType', Device::TYPE_CHROME);
if (str_starts_with($deviceType, Device::TYPE_OUTLOOK_ADDIN)) {
$device = $this->authenticateOutlook($deviceType);
} else {
$device = $this->authenticateChrome($deviceType);
}
$user = $device->getUser();
$response += [
'success' => true,
'userId' => $user->getUuid(), // BC
'state' => Jiminny::call(InitialFrontendStateInterface::class . '@forUser', [$user]),
'token' => $user->createToken($user->email)->accessToken,
'deviceId' => $device->getUuid(),
];
if ($deviceType === Device::TYPE_CHROME) {
event(new ChromeExtensionAuthenticated($device));
if (! $this->isSidekickEnabled($user)) {
return $this->response->errorUnauthorized('Sidekick is disabled, contact your admin');
}
}
return $this->response->withArray($response);
} catch (IdentityProviderException $e) {
Log::error('[' . __METHOD__ . ']' . $e->getMessage(), [
'responseBody' => $e->getResponseBody(),
'user' => $this->request->getUser(),
]);
return $this->response->errorUnauthorized($e->getMessage());
} catch (HttpUnauthorizedException $e) {
return $this->response->errorUnauthorized($e->getMessage());
} catch (\InvalidArgumentException $e) {
return $this->response->errorWrongArgs($e->getMessage());
} catch (HttpForbiddenException $e) {
return $this->response->errorForbidden($e->getMessage());
}
}
/**
* @throws IdentityProviderException
* @throws HttpUnauthorizedException
* @throws ActivityProviderException
* @throws Exception
*/
private function validateViaCalendar(User $user): void
{
$provider = $this->socialAccountService->getProvider($user->team->calendar_provider);
switch ($user->team->calendar_provider) {
case Team::CALENDAR_PROVIDER_GOOGLE:
// We are passed an Access Token from Google. Use this to retrieve the email address for this profile.
$token = new AccessToken(['access_token' => $this->request->getPassword()]);
/** @var Userinfo $ownerDetails */
$ownerDetails = $provider->getResourceOwner($token);
if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($ownerDetails->getEmail())) {
Log::error('[validateViaCalendar] Google Email mismatch', [
'userEmail' => $user->email,
'preferredUsername' => $ownerDetails->getEmail(),
'userEmailClean' => StringUtil::cleanEmail($user->email),
'preferredUsernameClean' => StringUtil::cleanEmail($ownerDetails->getEmail()),
]);
$this->accountNotMatch();
}
break;
case Team::CALENDAR_PROVIDER_OFFICE:
// We are passed an Access Token from Azure AD. Use this to retrieve the email address from the claims.
try {
/** @var Azure $provider */
$claims = $provider->validateAccessToken($this->request->getPassword());
if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($claims['preferred_username'])) {
Log::error('[validateViaCalendar] Office Email mismatch', [
'userEmail' => $user->email,
'preferredUsername' => $claims['preferred_username'],
'userEmailClean' => StringUtil::cleanEmail($user->email),
'preferredUsernameClean' => StringUtil::cleanEmail($claims['preferred_username']),
]);
$this->accountNotMatch();
}
} catch (\RuntimeException $exception) {
Log::info('[Sidekick] Authorization failed', [
'error' => get_class($exception),
'message' => $exception->getMessage(),
]);
throw new \InvalidArgumentException('The authorization token is invalid. Please try again.
Reason: ' . $exception->getMessage());
}
break;
}
}
private function validateViaJiminnyToken(): void
{
$email = $this->request->getUser();
$token = $this->request->getPassword();
// Cut the jmny prefix at beginning
$token = substr($token, 4);
$sso = new Sso();
$cacheKey = $sso->getJiminnyTokenCacheKey($email, $token);
if (Cache::pull($cacheKey) === null) {
Log::error('[validateViaJiminnyToken] Cannot pull cache key', [
'userEmail' => $email,
]);
$this->accountNotMatch();
}
}
private function accountNotMatch(): void
{
throw new HttpUnauthorizedException('Sorry, that account does not match. ' .
'Please ensure you sign in with your work account.');
}
private function accountNotFound(): void
{
throw new HttpUnauthorizedException('Sorry, we couldn\'t find an account with that email address. ' .
'Please ensure you sign in with your work account.');
}
/**
* Authenticate Chrome Extension
*
* @throws ActivityProviderException
* @throws HttpUnauthorizedException
* @throws IdentityProviderException
*/
private function authenticateChrome(string $deviceType): Device
{
if (empty($this->request->getUser()) || empty($this->request->getPassword())) {
throw new \InvalidArgumentException('No authorization header was sent.');
}
$user = $this->userRepository->findByEmail($this->request->getUser());
if ($user === null) {
$this->accountNotFound();
}
$team = $user->getTeam();
if (Str::startsWith($this->request->getPassword(), ['jmny'])) {
$this->validateViaJiminnyToken();
} else {
$this->validateViaCalendar($user);
if ($team && $team->getTenant() instanceof \Slides\Saml2\Models\Tenant) {
throw new HttpForbiddenException('Required SSO login.');
}
}
$deviceVersion = $this->request->headers->get(
'X-Jiminny-Device-Version',
$this->request->input('deviceVersion')
);
return $user->devices()->updateOrCreate([
'type' => $deviceType,
'fingerprint' => str_limit($this->request->fingerprint(), 255, ''),
], [
'version' => $deviceVersion,
]);
}
private function authenticateOutlook(string $deviceType): Device
{
$officeToken = $this->request->bearerToken();
if (empty($officeToken)) {
throw new InvalidArgumentException('The authorization token is required.');
}
// Validate user token passed from Outlook
try {
// Todo: Confirm we cannot use the existing Azure Provider validator with this token.
$verifiedClaims = $this->officeTokenValidator->validateOfficeIdentityToken($officeToken);
$userEmail = $verifiedClaims['upn'] ?? $verifiedClaims['preferred_username'] ?? $verifiedClaims['email'];
$user = $this->userRepository->findByEmail($userEmail);
if ($user === null || ! $this->officeTokenValidator->validateUserFromOfficeToken($verifiedClaims, $user)) {
$this->accountNotFound();
}
return $user->devices()->updateOrCreate([
'type' => $deviceType,
'fingerprint' => str_limit($verifiedClaims['sub'], 255, ''),
], [
'version' => $this->request->input('deviceVersion'),
]);
} catch (\Throwable $exception) {
Log::error('[Outlook] Authorization failed', [
'error' => get_class($exception),
'message' => $exception->getMessage(),
]);
throw new HttpUnauthorizedException('The authorization token is invalid. Please try again.');
}
}
private function isSidekickEnabled(?User $user): bool
{
if (! $user) {
return false;
}
if (
$user->getTeam()->hasFeature(FeatureEnum::SIDEKICK_SETTINGS) &&
$user->hasPermission(PermissionEnum::SIDEKICK_ACCESS)
) {
return app(SidekickService::class)->isSidekickEnabledForUser($user);
}
return false;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20891-improve-sms-text-relays, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.08843085,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20891-improve-sms-text-relays","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Http\\Controllers\\Auth;\n\nuse Exception;\nuse Google\\Service\\Oauth2\\Userinfo;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Contracts\\InitialFrontendStateInterface;\nuse Jiminny\\Component\\Sidekick\\SidekickService;\nuse Jiminny\\Events\\Auth\\ChromeExtensionAuthenticated;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\HttpForbiddenException;\nuse Jiminny\\Exceptions\\HttpUnauthorizedException;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Guards\\Sso;\nuse Jiminny\\Http\\Controllers\\API\\BaseController as Controller;\nuse Jiminny\\Http\\Responses\\Api\\Response;\nuse Jiminny\\Http\\Serializers\\JsonSerializer;\nuse Jiminny\\Jiminny;\nuse Jiminny\\Models\\Device;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Services\\MeetingGenerator\\Validators\\OfficeTokenValidator;\nuse Jiminny\\Services\\SocialAccountService;\nuse Jiminny\\Utils\\StringUtil;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\n\nclass ExtensionController extends Controller\n{\n /**\n * Create a new controller instance.\n */\n public function __construct(\n Response $response,\n private readonly SocialAccountService $socialAccountService,\n private readonly OfficeTokenValidator $officeTokenValidator,\n private readonly UserRepository $userRepository\n ) {\n parent::__construct($response);\n }\n\n public function authenticate()\n {\n $this->request->validate([\n 'deviceType' => 'in:' . implode(',', Device::$enumTypes),\n 'deviceId' => 'uuid:devices',\n 'deviceVersion' => 'max:40',\n ]);\n\n $this->response\n ->getManager()\n ->setSerializer(new JsonSerializer());\n\n try {\n $response = [\n 'message' => null,\n ];\n $deviceType = $this->request->input('deviceType', Device::TYPE_CHROME);\n\n if (str_starts_with($deviceType, Device::TYPE_OUTLOOK_ADDIN)) {\n $device = $this->authenticateOutlook($deviceType);\n } else {\n $device = $this->authenticateChrome($deviceType);\n }\n\n $user = $device->getUser();\n $response += [\n 'success' => true,\n 'userId' => $user->getUuid(), // BC\n 'state' => Jiminny::call(InitialFrontendStateInterface::class . '@forUser', [$user]),\n 'token' => $user->createToken($user->email)->accessToken,\n 'deviceId' => $device->getUuid(),\n ];\n\n if ($deviceType === Device::TYPE_CHROME) {\n event(new ChromeExtensionAuthenticated($device));\n\n if (! $this->isSidekickEnabled($user)) {\n return $this->response->errorUnauthorized('Sidekick is disabled, contact your admin');\n }\n }\n\n return $this->response->withArray($response);\n } catch (IdentityProviderException $e) {\n Log::error('[' . __METHOD__ . ']' . $e->getMessage(), [\n 'responseBody' => $e->getResponseBody(),\n 'user' => $this->request->getUser(),\n ]);\n\n return $this->response->errorUnauthorized($e->getMessage());\n } catch (HttpUnauthorizedException $e) {\n return $this->response->errorUnauthorized($e->getMessage());\n } catch (\\InvalidArgumentException $e) {\n return $this->response->errorWrongArgs($e->getMessage());\n } catch (HttpForbiddenException $e) {\n return $this->response->errorForbidden($e->getMessage());\n }\n }\n\n /**\n * @throws IdentityProviderException\n * @throws HttpUnauthorizedException\n * @throws ActivityProviderException\n * @throws Exception\n */\n private function validateViaCalendar(User $user): void\n {\n $provider = $this->socialAccountService->getProvider($user->team->calendar_provider);\n\n switch ($user->team->calendar_provider) {\n case Team::CALENDAR_PROVIDER_GOOGLE:\n\n // We are passed an Access Token from Google. Use this to retrieve the email address for this profile.\n $token = new AccessToken(['access_token' => $this->request->getPassword()]);\n\n /** @var Userinfo $ownerDetails */\n $ownerDetails = $provider->getResourceOwner($token);\n\n if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($ownerDetails->getEmail())) {\n Log::error('[validateViaCalendar] Google Email mismatch', [\n 'userEmail' => $user->email,\n 'preferredUsername' => $ownerDetails->getEmail(),\n 'userEmailClean' => StringUtil::cleanEmail($user->email),\n 'preferredUsernameClean' => StringUtil::cleanEmail($ownerDetails->getEmail()),\n ]);\n\n $this->accountNotMatch();\n }\n\n break;\n\n case Team::CALENDAR_PROVIDER_OFFICE:\n\n // We are passed an Access Token from Azure AD. Use this to retrieve the email address from the claims.\n try {\n /** @var Azure $provider */\n $claims = $provider->validateAccessToken($this->request->getPassword());\n\n if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($claims['preferred_username'])) {\n Log::error('[validateViaCalendar] Office Email mismatch', [\n 'userEmail' => $user->email,\n 'preferredUsername' => $claims['preferred_username'],\n 'userEmailClean' => StringUtil::cleanEmail($user->email),\n 'preferredUsernameClean' => StringUtil::cleanEmail($claims['preferred_username']),\n ]);\n\n $this->accountNotMatch();\n }\n } catch (\\RuntimeException $exception) {\n Log::info('[Sidekick] Authorization failed', [\n 'error' => get_class($exception),\n 'message' => $exception->getMessage(),\n ]);\n\n throw new \\InvalidArgumentException('The authorization token is invalid. Please try again.\n Reason: ' . $exception->getMessage());\n }\n\n break;\n }\n }\n\n private function validateViaJiminnyToken(): void\n {\n $email = $this->request->getUser();\n $token = $this->request->getPassword();\n\n // Cut the jmny prefix at beginning\n $token = substr($token, 4);\n\n $sso = new Sso();\n $cacheKey = $sso->getJiminnyTokenCacheKey($email, $token);\n\n if (Cache::pull($cacheKey) === null) {\n Log::error('[validateViaJiminnyToken] Cannot pull cache key', [\n 'userEmail' => $email,\n ]);\n\n $this->accountNotMatch();\n }\n }\n\n private function accountNotMatch(): void\n {\n throw new HttpUnauthorizedException('Sorry, that account does not match. ' .\n 'Please ensure you sign in with your work account.');\n }\n\n private function accountNotFound(): void\n {\n throw new HttpUnauthorizedException('Sorry, we couldn\\'t find an account with that email address. ' .\n 'Please ensure you sign in with your work account.');\n }\n\n /**\n * Authenticate Chrome Extension\n *\n * @throws ActivityProviderException\n * @throws HttpUnauthorizedException\n * @throws IdentityProviderException\n */\n private function authenticateChrome(string $deviceType): Device\n {\n if (empty($this->request->getUser()) || empty($this->request->getPassword())) {\n throw new \\InvalidArgumentException('No authorization header was sent.');\n }\n\n $user = $this->userRepository->findByEmail($this->request->getUser());\n\n if ($user === null) {\n $this->accountNotFound();\n }\n\n $team = $user->getTeam();\n\n if (Str::startsWith($this->request->getPassword(), ['jmny'])) {\n $this->validateViaJiminnyToken();\n } else {\n $this->validateViaCalendar($user);\n if ($team && $team->getTenant() instanceof \\Slides\\Saml2\\Models\\Tenant) {\n throw new HttpForbiddenException('Required SSO login.');\n }\n }\n\n $deviceVersion = $this->request->headers->get(\n 'X-Jiminny-Device-Version',\n $this->request->input('deviceVersion')\n );\n\n return $user->devices()->updateOrCreate([\n 'type' => $deviceType,\n 'fingerprint' => str_limit($this->request->fingerprint(), 255, ''),\n ], [\n 'version' => $deviceVersion,\n ]);\n }\n\n private function authenticateOutlook(string $deviceType): Device\n {\n $officeToken = $this->request->bearerToken();\n if (empty($officeToken)) {\n throw new InvalidArgumentException('The authorization token is required.');\n }\n\n // Validate user token passed from Outlook\n try {\n // Todo: Confirm we cannot use the existing Azure Provider validator with this token.\n $verifiedClaims = $this->officeTokenValidator->validateOfficeIdentityToken($officeToken);\n\n $userEmail = $verifiedClaims['upn'] ?? $verifiedClaims['preferred_username'] ?? $verifiedClaims['email'];\n $user = $this->userRepository->findByEmail($userEmail);\n\n if ($user === null || ! $this->officeTokenValidator->validateUserFromOfficeToken($verifiedClaims, $user)) {\n $this->accountNotFound();\n }\n\n return $user->devices()->updateOrCreate([\n 'type' => $deviceType,\n 'fingerprint' => str_limit($verifiedClaims['sub'], 255, ''),\n ], [\n 'version' => $this->request->input('deviceVersion'),\n ]);\n } catch (\\Throwable $exception) {\n Log::error('[Outlook] Authorization failed', [\n 'error' => get_class($exception),\n 'message' => $exception->getMessage(),\n ]);\n\n throw new HttpUnauthorizedException('The authorization token is invalid. Please try again.');\n }\n }\n\n private function isSidekickEnabled(?User $user): bool\n {\n if (! $user) {\n return false;\n }\n\n if (\n $user->getTeam()->hasFeature(FeatureEnum::SIDEKICK_SETTINGS) &&\n $user->hasPermission(PermissionEnum::SIDEKICK_ACCESS)\n ) {\n return app(SidekickService::class)->isSidekickEnabledForUser($user);\n }\n\n return false;\n }\n}","depth":4,"bounds":{"left":0.122340426,"top":0.14684756,"width":0.29321808,"height":0.85315245},"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Http\\Controllers\\Auth;\n\nuse Exception;\nuse Google\\Service\\Oauth2\\Userinfo;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Contracts\\InitialFrontendStateInterface;\nuse Jiminny\\Component\\Sidekick\\SidekickService;\nuse Jiminny\\Events\\Auth\\ChromeExtensionAuthenticated;\nuse Jiminny\\Exceptions\\ActivityProviderException;\nuse Jiminny\\Exceptions\\HttpForbiddenException;\nuse Jiminny\\Exceptions\\HttpUnauthorizedException;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Guards\\Sso;\nuse Jiminny\\Http\\Controllers\\API\\BaseController as Controller;\nuse Jiminny\\Http\\Responses\\Api\\Response;\nuse Jiminny\\Http\\Serializers\\JsonSerializer;\nuse Jiminny\\Jiminny;\nuse Jiminny\\Models\\Device;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\UserRepository;\nuse Jiminny\\Services\\MeetingGenerator\\Validators\\OfficeTokenValidator;\nuse Jiminny\\Services\\SocialAccountService;\nuse Jiminny\\Utils\\StringUtil;\nuse League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException;\nuse League\\OAuth2\\Client\\Token\\AccessToken;\nuse TheNetworg\\OAuth2\\Client\\Provider\\Azure;\n\nclass ExtensionController extends Controller\n{\n /**\n * Create a new controller instance.\n */\n public function __construct(\n Response $response,\n private readonly SocialAccountService $socialAccountService,\n private readonly OfficeTokenValidator $officeTokenValidator,\n private readonly UserRepository $userRepository\n ) {\n parent::__construct($response);\n }\n\n public function authenticate()\n {\n $this->request->validate([\n 'deviceType' => 'in:' . implode(',', Device::$enumTypes),\n 'deviceId' => 'uuid:devices',\n 'deviceVersion' => 'max:40',\n ]);\n\n $this->response\n ->getManager()\n ->setSerializer(new JsonSerializer());\n\n try {\n $response = [\n 'message' => null,\n ];\n $deviceType = $this->request->input('deviceType', Device::TYPE_CHROME);\n\n if (str_starts_with($deviceType, Device::TYPE_OUTLOOK_ADDIN)) {\n $device = $this->authenticateOutlook($deviceType);\n } else {\n $device = $this->authenticateChrome($deviceType);\n }\n\n $user = $device->getUser();\n $response += [\n 'success' => true,\n 'userId' => $user->getUuid(), // BC\n 'state' => Jiminny::call(InitialFrontendStateInterface::class . '@forUser', [$user]),\n 'token' => $user->createToken($user->email)->accessToken,\n 'deviceId' => $device->getUuid(),\n ];\n\n if ($deviceType === Device::TYPE_CHROME) {\n event(new ChromeExtensionAuthenticated($device));\n\n if (! $this->isSidekickEnabled($user)) {\n return $this->response->errorUnauthorized('Sidekick is disabled, contact your admin');\n }\n }\n\n return $this->response->withArray($response);\n } catch (IdentityProviderException $e) {\n Log::error('[' . __METHOD__ . ']' . $e->getMessage(), [\n 'responseBody' => $e->getResponseBody(),\n 'user' => $this->request->getUser(),\n ]);\n\n return $this->response->errorUnauthorized($e->getMessage());\n } catch (HttpUnauthorizedException $e) {\n return $this->response->errorUnauthorized($e->getMessage());\n } catch (\\InvalidArgumentException $e) {\n return $this->response->errorWrongArgs($e->getMessage());\n } catch (HttpForbiddenException $e) {\n return $this->response->errorForbidden($e->getMessage());\n }\n }\n\n /**\n * @throws IdentityProviderException\n * @throws HttpUnauthorizedException\n * @throws ActivityProviderException\n * @throws Exception\n */\n private function validateViaCalendar(User $user): void\n {\n $provider = $this->socialAccountService->getProvider($user->team->calendar_provider);\n\n switch ($user->team->calendar_provider) {\n case Team::CALENDAR_PROVIDER_GOOGLE:\n\n // We are passed an Access Token from Google. Use this to retrieve the email address for this profile.\n $token = new AccessToken(['access_token' => $this->request->getPassword()]);\n\n /** @var Userinfo $ownerDetails */\n $ownerDetails = $provider->getResourceOwner($token);\n\n if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($ownerDetails->getEmail())) {\n Log::error('[validateViaCalendar] Google Email mismatch', [\n 'userEmail' => $user->email,\n 'preferredUsername' => $ownerDetails->getEmail(),\n 'userEmailClean' => StringUtil::cleanEmail($user->email),\n 'preferredUsernameClean' => StringUtil::cleanEmail($ownerDetails->getEmail()),\n ]);\n\n $this->accountNotMatch();\n }\n\n break;\n\n case Team::CALENDAR_PROVIDER_OFFICE:\n\n // We are passed an Access Token from Azure AD. Use this to retrieve the email address from the claims.\n try {\n /** @var Azure $provider */\n $claims = $provider->validateAccessToken($this->request->getPassword());\n\n if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($claims['preferred_username'])) {\n Log::error('[validateViaCalendar] Office Email mismatch', [\n 'userEmail' => $user->email,\n 'preferredUsername' => $claims['preferred_username'],\n 'userEmailClean' => StringUtil::cleanEmail($user->email),\n 'preferredUsernameClean' => StringUtil::cleanEmail($claims['preferred_username']),\n ]);\n\n $this->accountNotMatch();\n }\n } catch (\\RuntimeException $exception) {\n Log::info('[Sidekick] Authorization failed', [\n 'error' => get_class($exception),\n 'message' => $exception->getMessage(),\n ]);\n\n throw new \\InvalidArgumentException('The authorization token is invalid. Please try again.\n Reason: ' . $exception->getMessage());\n }\n\n break;\n }\n }\n\n private function validateViaJiminnyToken(): void\n {\n $email = $this->request->getUser();\n $token = $this->request->getPassword();\n\n // Cut the jmny prefix at beginning\n $token = substr($token, 4);\n\n $sso = new Sso();\n $cacheKey = $sso->getJiminnyTokenCacheKey($email, $token);\n\n if (Cache::pull($cacheKey) === null) {\n Log::error('[validateViaJiminnyToken] Cannot pull cache key', [\n 'userEmail' => $email,\n ]);\n\n $this->accountNotMatch();\n }\n }\n\n private function accountNotMatch(): void\n {\n throw new HttpUnauthorizedException('Sorry, that account does not match. ' .\n 'Please ensure you sign in with your work account.');\n }\n\n private function accountNotFound(): void\n {\n throw new HttpUnauthorizedException('Sorry, we couldn\\'t find an account with that email address. ' .\n 'Please ensure you sign in with your work account.');\n }\n\n /**\n * Authenticate Chrome Extension\n *\n * @throws ActivityProviderException\n * @throws HttpUnauthorizedException\n * @throws IdentityProviderException\n */\n private function authenticateChrome(string $deviceType): Device\n {\n if (empty($this->request->getUser()) || empty($this->request->getPassword())) {\n throw new \\InvalidArgumentException('No authorization header was sent.');\n }\n\n $user = $this->userRepository->findByEmail($this->request->getUser());\n\n if ($user === null) {\n $this->accountNotFound();\n }\n\n $team = $user->getTeam();\n\n if (Str::startsWith($this->request->getPassword(), ['jmny'])) {\n $this->validateViaJiminnyToken();\n } else {\n $this->validateViaCalendar($user);\n if ($team && $team->getTenant() instanceof \\Slides\\Saml2\\Models\\Tenant) {\n throw new HttpForbiddenException('Required SSO login.');\n }\n }\n\n $deviceVersion = $this->request->headers->get(\n 'X-Jiminny-Device-Version',\n $this->request->input('deviceVersion')\n );\n\n return $user->devices()->updateOrCreate([\n 'type' => $deviceType,\n 'fingerprint' => str_limit($this->request->fingerprint(), 255, ''),\n ], [\n 'version' => $deviceVersion,\n ]);\n }\n\n private function authenticateOutlook(string $deviceType): Device\n {\n $officeToken = $this->request->bearerToken();\n if (empty($officeToken)) {\n throw new InvalidArgumentException('The authorization token is required.');\n }\n\n // Validate user token passed from Outlook\n try {\n // Todo: Confirm we cannot use the existing Azure Provider validator with this token.\n $verifiedClaims = $this->officeTokenValidator->validateOfficeIdentityToken($officeToken);\n\n $userEmail = $verifiedClaims['upn'] ?? $verifiedClaims['preferred_username'] ?? $verifiedClaims['email'];\n $user = $this->userRepository->findByEmail($userEmail);\n\n if ($user === null || ! $this->officeTokenValidator->validateUserFromOfficeToken($verifiedClaims, $user)) {\n $this->accountNotFound();\n }\n\n return $user->devices()->updateOrCreate([\n 'type' => $deviceType,\n 'fingerprint' => str_limit($verifiedClaims['sub'], 255, ''),\n ], [\n 'version' => $this->request->input('deviceVersion'),\n ]);\n } catch (\\Throwable $exception) {\n Log::error('[Outlook] Authorization failed', [\n 'error' => get_class($exception),\n 'message' => $exception->getMessage(),\n ]);\n\n throw new HttpUnauthorizedException('The authorization token is invalid. Please try again.');\n }\n }\n\n private function isSidekickEnabled(?User $user): bool\n {\n if (! $user) {\n return false;\n }\n\n if (\n $user->getTeam()->hasFeature(FeatureEnum::SIDEKICK_SETTINGS) &&\n $user->hasPermission(PermissionEnum::SIDEKICK_ACCESS)\n ) {\n return app(SidekickService::class)->isSidekickEnabledForUser($user);\n }\n\n return false;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.40957448,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.41821808,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.42918882,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.43783244,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.44647607,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4574468,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.46841756,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.4950133,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.50598407,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.7084442,"top":0.09896249,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.67785907,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.69015956,"top":0.123703115,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"40","depth":4,"bounds":{"left":0.6994681,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"65","depth":4,"bounds":{"left":0.7117686,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7237367,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.73105055,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01'\n# and id IN (32415, 32416);\nand id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7214871042976799626
|
1065678670630630989
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20891-improve-sms-text Project: faVsco.js, menu
JY-20891-improve-sms-text-relays, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
namespace Jiminny\Http\Controllers\Auth;
use Exception;
use Google\Service\Oauth2\Userinfo;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Contracts\InitialFrontendStateInterface;
use Jiminny\Component\Sidekick\SidekickService;
use Jiminny\Events\Auth\ChromeExtensionAuthenticated;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Exceptions\HttpForbiddenException;
use Jiminny\Exceptions\HttpUnauthorizedException;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Guards\Sso;
use Jiminny\Http\Controllers\API\BaseController as Controller;
use Jiminny\Http\Responses\Api\Response;
use Jiminny\Http\Serializers\JsonSerializer;
use Jiminny\Jiminny;
use Jiminny\Models\Device;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\UserRepository;
use Jiminny\Services\MeetingGenerator\Validators\OfficeTokenValidator;
use Jiminny\Services\SocialAccountService;
use Jiminny\Utils\StringUtil;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use TheNetworg\OAuth2\Client\Provider\Azure;
class ExtensionController extends Controller
{
/**
* Create a new controller instance.
*/
public function __construct(
Response $response,
private readonly SocialAccountService $socialAccountService,
private readonly OfficeTokenValidator $officeTokenValidator,
private readonly UserRepository $userRepository
) {
parent::__construct($response);
}
public function authenticate()
{
$this->request->validate([
'deviceType' => 'in:' . implode(',', Device::$enumTypes),
'deviceId' => 'uuid:devices',
'deviceVersion' => 'max:40',
]);
$this->response
->getManager()
->setSerializer(new JsonSerializer());
try {
$response = [
'message' => null,
];
$deviceType = $this->request->input('deviceType', Device::TYPE_CHROME);
if (str_starts_with($deviceType, Device::TYPE_OUTLOOK_ADDIN)) {
$device = $this->authenticateOutlook($deviceType);
} else {
$device = $this->authenticateChrome($deviceType);
}
$user = $device->getUser();
$response += [
'success' => true,
'userId' => $user->getUuid(), // BC
'state' => Jiminny::call(InitialFrontendStateInterface::class . '@forUser', [$user]),
'token' => $user->createToken($user->email)->accessToken,
'deviceId' => $device->getUuid(),
];
if ($deviceType === Device::TYPE_CHROME) {
event(new ChromeExtensionAuthenticated($device));
if (! $this->isSidekickEnabled($user)) {
return $this->response->errorUnauthorized('Sidekick is disabled, contact your admin');
}
}
return $this->response->withArray($response);
} catch (IdentityProviderException $e) {
Log::error('[' . __METHOD__ . ']' . $e->getMessage(), [
'responseBody' => $e->getResponseBody(),
'user' => $this->request->getUser(),
]);
return $this->response->errorUnauthorized($e->getMessage());
} catch (HttpUnauthorizedException $e) {
return $this->response->errorUnauthorized($e->getMessage());
} catch (\InvalidArgumentException $e) {
return $this->response->errorWrongArgs($e->getMessage());
} catch (HttpForbiddenException $e) {
return $this->response->errorForbidden($e->getMessage());
}
}
/**
* @throws IdentityProviderException
* @throws HttpUnauthorizedException
* @throws ActivityProviderException
* @throws Exception
*/
private function validateViaCalendar(User $user): void
{
$provider = $this->socialAccountService->getProvider($user->team->calendar_provider);
switch ($user->team->calendar_provider) {
case Team::CALENDAR_PROVIDER_GOOGLE:
// We are passed an Access Token from Google. Use this to retrieve the email address for this profile.
$token = new AccessToken(['access_token' => $this->request->getPassword()]);
/** @var Userinfo $ownerDetails */
$ownerDetails = $provider->getResourceOwner($token);
if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($ownerDetails->getEmail())) {
Log::error('[validateViaCalendar] Google Email mismatch', [
'userEmail' => $user->email,
'preferredUsername' => $ownerDetails->getEmail(),
'userEmailClean' => StringUtil::cleanEmail($user->email),
'preferredUsernameClean' => StringUtil::cleanEmail($ownerDetails->getEmail()),
]);
$this->accountNotMatch();
}
break;
case Team::CALENDAR_PROVIDER_OFFICE:
// We are passed an Access Token from Azure AD. Use this to retrieve the email address from the claims.
try {
/** @var Azure $provider */
$claims = $provider->validateAccessToken($this->request->getPassword());
if (StringUtil::cleanEmail($user->email) !== StringUtil::cleanEmail($claims['preferred_username'])) {
Log::error('[validateViaCalendar] Office Email mismatch', [
'userEmail' => $user->email,
'preferredUsername' => $claims['preferred_username'],
'userEmailClean' => StringUtil::cleanEmail($user->email),
'preferredUsernameClean' => StringUtil::cleanEmail($claims['preferred_username']),
]);
$this->accountNotMatch();
}
} catch (\RuntimeException $exception) {
Log::info('[Sidekick] Authorization failed', [
'error' => get_class($exception),
'message' => $exception->getMessage(),
]);
throw new \InvalidArgumentException('The authorization token is invalid. Please try again.
Reason: ' . $exception->getMessage());
}
break;
}
}
private function validateViaJiminnyToken(): void
{
$email = $this->request->getUser();
$token = $this->request->getPassword();
// Cut the jmny prefix at beginning
$token = substr($token, 4);
$sso = new Sso();
$cacheKey = $sso->getJiminnyTokenCacheKey($email, $token);
if (Cache::pull($cacheKey) === null) {
Log::error('[validateViaJiminnyToken] Cannot pull cache key', [
'userEmail' => $email,
]);
$this->accountNotMatch();
}
}
private function accountNotMatch(): void
{
throw new HttpUnauthorizedException('Sorry, that account does not match. ' .
'Please ensure you sign in with your work account.');
}
private function accountNotFound(): void
{
throw new HttpUnauthorizedException('Sorry, we couldn\'t find an account with that email address. ' .
'Please ensure you sign in with your work account.');
}
/**
* Authenticate Chrome Extension
*
* @throws ActivityProviderException
* @throws HttpUnauthorizedException
* @throws IdentityProviderException
*/
private function authenticateChrome(string $deviceType): Device
{
if (empty($this->request->getUser()) || empty($this->request->getPassword())) {
throw new \InvalidArgumentException('No authorization header was sent.');
}
$user = $this->userRepository->findByEmail($this->request->getUser());
if ($user === null) {
$this->accountNotFound();
}
$team = $user->getTeam();
if (Str::startsWith($this->request->getPassword(), ['jmny'])) {
$this->validateViaJiminnyToken();
} else {
$this->validateViaCalendar($user);
if ($team && $team->getTenant() instanceof \Slides\Saml2\Models\Tenant) {
throw new HttpForbiddenException('Required SSO login.');
}
}
$deviceVersion = $this->request->headers->get(
'X-Jiminny-Device-Version',
$this->request->input('deviceVersion')
);
return $user->devices()->updateOrCreate([
'type' => $deviceType,
'fingerprint' => str_limit($this->request->fingerprint(), 255, ''),
], [
'version' => $deviceVersion,
]);
}
private function authenticateOutlook(string $deviceType): Device
{
$officeToken = $this->request->bearerToken();
if (empty($officeToken)) {
throw new InvalidArgumentException('The authorization token is required.');
}
// Validate user token passed from Outlook
try {
// Todo: Confirm we cannot use the existing Azure Provider validator with this token.
$verifiedClaims = $this->officeTokenValidator->validateOfficeIdentityToken($officeToken);
$userEmail = $verifiedClaims['upn'] ?? $verifiedClaims['preferred_username'] ?? $verifiedClaims['email'];
$user = $this->userRepository->findByEmail($userEmail);
if ($user === null || ! $this->officeTokenValidator->validateUserFromOfficeToken($verifiedClaims, $user)) {
$this->accountNotFound();
}
return $user->devices()->updateOrCreate([
'type' => $deviceType,
'fingerprint' => str_limit($verifiedClaims['sub'], 255, ''),
], [
'version' => $this->request->input('deviceVersion'),
]);
} catch (\Throwable $exception) {
Log::error('[Outlook] Authorization failed', [
'error' => get_class($exception),
'message' => $exception->getMessage(),
]);
throw new HttpUnauthorizedException('The authorization token is invalid. Please try again.');
}
}
private function isSidekickEnabled(?User $user): bool
{
if (! $user) {
return false;
}
if (
$user->getTeam()->hasFeature(FeatureEnum::SIDEKICK_SETTINGS) &&
$user->hasPermission(PermissionEnum::SIDEKICK_ACCESS)
) {
return app(SidekickService::class)->isSidekickEnabledForUser($user);
}
return false;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
40
1
40
65
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01'
# and id IN (32415, 32416);
and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
34716
|
NULL
|
NULL
|
NULL
|