helpscout / helpscout-api-php

PHP Wrapper for the Help Scout API
MIT License
98 stars 62 forks source link

Could patchConversation() be public? Options for deleting a thread? #239

Closed helgatheviking closed 4 years ago

helgatheviking commented 4 years ago

Could patchConversation() be public or is there another way to patch/delete threads in a conversation?

The flow for my project is that I receive a form submission from the marketplace that sells my product. It is auto-forwarded by gsuite to my HelpScout email. I'm receiving a webhook when this conversation is created and I'd like the replace the initial thread (which is a wall of text as it includes a website's "system status") with two threads... one Note with the "system status" and one with their question... plus some custom fields and a tag.

So far I've been able to parse the hook correctly and create 2 additional threads, but ideally I'd like to delete the original and just leave my 2 sparkly clean threads in the conversation.

https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/update/

Suggests that you can patch a thread with a remove or replace operation. But in the PHP API I'm stuck since patchConversation() is a private method. I can't call RestClient->patchResource() directly either since I've yet to figure out how to access/return the restClient property.

JonLaliberte commented 4 years ago

Yeah, HelpScout's formatting for these marketplace emails is really ugly (not exactly HelpScout's fault, but it'd be nice if they worked to make them look better nonetheless).

In the meantime though, I think we'll do the same as you, so I'd be interested in this being made public (we could just use a custom repo to make it public, but seems to make sense to allow it in general).

helgatheviking commented 4 years ago

I think it would be really difficult for HS to handle the formatting for all the disparate marketplaces out there. But I'm 85% of the way there to using the webhook to parse a message cleanly. I could leave the original or change it's text to a null string (b/c you can change a thread's content), but I'm curious if it can be deleted.

I just tested making patchConversation() public.. and running the following:

$patch = Patch::replace( 'threads', $newThreads );
$client->conversations()->patchConversation( $conversationId, $patch );

and got the following error:

string(48) "HelpScout\Api\Exception\ValidationErrorException"

object(HelpScout\Api\Http\Hal\VndError)#1676 (4) {
  ["message":"HelpScout\Api\Http\Hal\VndError":private]=>
  string(11) "Bad request"
  ["logRef":"HelpScout\Api\Http\Hal\VndError":private]=>
  string(45) "0e992c01-798e-4da4-b26f-f356f21f9caa#32555373"
  ["path":"HelpScout\Api\Http\Hal\VndError":private]=>
  NULL
  ["errors":"HelpScout\Api\Http\Hal\VndError":private]=>
  array(1) {
    [0]=>
    object(HelpScout\Api\Http\Hal\VndError)#1678 (4) {
      ["message":"HelpScout\Api\Http\Hal\VndError":private]=>
      string(104) "Expected one of these: '/assignTo', '/draft', '/mailboxId', '/primaryCustomer.id', '/status', '/subject'"
      ["logRef":"HelpScout\Api\Http\Hal\VndError":private]=>
      NULL
      ["path":"HelpScout\Api\Http\Hal\VndError":private]=>
      string(4) "path"
      ["errors":"HelpScout\Api\Http\Hal\VndError":private]=>
      array(0) {
      }
    }
  }
}

Going to see if I can try patching a thread resource next, but like I said, I'm a little stuck getting the restClient

helgatheviking commented 4 years ago

Tried adding a delete() method for the ThreadsEndpoint but that's not supported at all:

string(36) "GuzzleHttp\Exception\ClientException" string(274) "Client error: DELETE https://api.helpscout.net/v2/conversations/1168141260/threads/3327974905 resulted in a 400 Bad Request response: {"logRef":"0e992c01-798e-4da4-b26f-f356f21f9caa#32582520","message":"This endpoint does not support HTTP method DELETE, (truncated...) "

I think my best option here is to just replace the original thread with some small unobtrustive text, like "parsed on this date"

JonLaliberte commented 4 years ago

Have you tested deleting the original message with a few marketplaces to be sure they are able to properly track the replies as when you do this? Normally it's in the message's subject/metadata, so it should be fine - but just something to consider.

I could leave the original or change it's text to a null string (b/c you can change a thread's content),

Ah, I had misunderstood, I thought this didn't work either (haven't tested anything we've discussed yet!). I think this solution would be good for us - I am curious how the receiving end will deal with it though.

helgatheviking commented 4 years ago

Not exactly sure what you mean by that? For me, I just get an email and that's the end of it. Nothing I do relays a status back to the original marketplace.

If it helps you at all... here's where I've been tinkering away at processing a new conversation webhook: https://github.com/kathyisawesome/woo3pd-helpscout/blob/master/includes/class-woo3pd-helpscout-webhook-handler.php#L122

It's a WordPress plugin so I can host it on my site. I've got custom fields, customer info, tags, etc... all parsing out of an "email" via domDocument and some regex.

Two final pieces of the puzzle are going to be 1. logging errors. and 2. determining what happens when you create a customer with an email attached to someone who already exists as a customer.

At the moment, it's not functional as it's parsing a single webhook that I captured the json for testing purposes. When those are resolved I can turn it "on" so that it is parsing real webhooks.

JonLaliberte commented 4 years ago

Ah, sorry - I was thinking of the customer communications we get from Amazon/Ebay - they come though with a lot of HTML and they are difficult to decipher. That's the emails we'll be cleaning up soon :)

helgatheviking commented 4 years ago

You may be able to get somewhere with domDocument if the emails have any IDs in the markup. That helped me a lot. But had to rely on some regex for a few things.

bkuhl commented 4 years ago

Hey @helgatheviking,

I'm sorry for the delay in response here! patchConversation() isn't public because there's only a handful of attributes editable via that endpoint and each of those have their own dedicated method (such as assign/unassign).

Updating the thread text looks like it'll be the best path forward and does require the use of an additional endpoint ($client->threads()->updateText($convoId, $threadId, $newText)).

helgatheviking commented 4 years ago

Thanks Ben. Yes, I determined that's the only path available for this.

@JonLaliberte I did a lot of rewriting last week but it's up and functioning! https://github.com/kathyisawesome/woo3pd-helpscout Works either via a HelpScout webhook or Inbound parse relay via SendGrid.

JonLaliberte commented 4 years ago

@helgatheviking Nice, thanks for sharing! I'm jealous of your parsing options. I checked some Amazon/Ebay email HTML and woof, it's going to have to be all regex and crossed fingers ;)

helgatheviking commented 4 years ago

Don't know if this is the case for you, but one tip that I struggled with at first is the emails had to be auto-forwarded by a Gmail filter. Otherwise Gmail got in there and DESTROYED the markup... which would've left me in a similar boat. But yeah, very grateful my marketplace has a few IDs in there. Good luck!