crisp-im / node-crisp-api

:zap: Crisp API Node Wrapper
https://docs.crisp.chat/guides/rest-api/
MIT License
99 stars 39 forks source link

How to use Bucket for uploading image via API #43

Closed ehsan-mohammadi closed 2 years ago

ehsan-mohammadi commented 2 years ago

Hello again! I want to upload an image with Bucket. In this way, I used crispClient.bucket.generateBucketURL(data). But it returns me 403 - not_allowed error. I tried this code:

var data = {
    namespace: "upload",
    from: "plugin",
    identifier: crispConfig.plugin.identifier,
    id: "bal2",
    file: {
      name: input.file.name,
      type: input.file.type
    }
};

crispClient.bucket.generateBucketURL(data)

I used my plugin identifier and key for this code. Also, can you help me how can I upload a photo after generating the bucket URL?

Thanks a lot

valeriansaliou commented 2 years ago

Hello!

ehsan-mohammadi commented 2 years ago

@valeriansaliou Yes, I added Bucket scope to my plugin in the Marketplace. Also, I double-checked my plugin identifier and finally, re-created the identifier and key in the Marketplace. Maybe, everything is fine and I haven't any idea about the problem. If I want to upload a photo from plugin, should I put the plugin-identifier that I got from Marketplace, in the message body?

var data = {
    namespace: "upload",
    from: "plugin",
    identifier: crispConfig.plugin.identifier, // The identifier that I got from Crisp Marketplace
    ...
}
valeriansaliou commented 2 years ago

Did you publish your plugin? That’s probably the issue, I believe this can’t work if you don’t first publish your plugin to obtain a permanent identifier for the plugin (this is an UUID, not the plugin URN).

ehsan-mohammadi commented 2 years ago

@valeriansaliou Yes, I published it as a private plugin and use production token.

valeriansaliou commented 2 years ago

Here's an example code from one of our plugin (w/ the Golang library):

  _, err := httpEndpointManager.crisp.client.Bucket.GenerateBucketURL(crispAPI.BucketURLRequest{
    Namespace  : "upload",
    From       : "plugin",
    Identifier : httpEndpointManager.crisp.pluginID, // your plugin_id (an UUID, not an URN)
    ID         : correlationID, // an internal ID that you generate to match the signed URL generated event coming back on the RTM API

    File       : crispAPI.BucketURLRequestFile {
      Name : fileName, // eg. "Photo.jpg"
      Type : fileType, // eg. "image/jpeg"
    },
  })
ehsan-mohammadi commented 2 years ago

@valeriansaliou Many thanks for helping me! I did a mistake because I used production-identifier instead of UUID. Now, in the RTM bucket:url:upload:generated event, I get this message:

{
  identifier: 'my identifier',
  type: 'upload',
  from: 'plugin',
  url: {
    signed: 'signed URL'
    resource: 'resource URL'
  },
  policy: { size_limit: 12000000 },
  id: 'bal2'
}

But if I enter signed-url in the browser, it gives me this message:

Oops! This file is not reachable. It may have expired as it was too old, or was removed by our systems because it could be harmful.

How can I reach the photo that I upload it?

valeriansaliou commented 2 years ago

Great!

You need first to upload it using url.signed by doing an HTTP PUT w/ your file content, with the exact same name and MIME type as requested (as this is verified upon upload, it needs to match).

Then, once the file is uploaded by your HTTP client (can be a Web browser or your server), your file will be available at url.resource.

Note that we run a cache layer on our edges that could cache the 404 Not Found if you try to open url.resource before the file gets uploaded with url.signed. So upload it first, and then you can read the file anytime.

Also note that any image uploaded will be downsized, we do not keep originals.

ehsan-mohammadi commented 2 years ago

@valeriansaliou Many thanks for helping me and quick response! That solved my problem. Also, thanks to the Crisp team!

ehsan-mohammadi commented 2 years ago

@valeriansaliou Can you help me with the standard format of the file content that should be uploaded in the url.signed? For example, I send messages with this structure:

var message = {
    origin: 'chat',
    type: 'text',
    from: 'operator',
    content: 'Some content'
};

Should I send my file in a format like this? What's the right format of my file content (like base64) I want to upload it with the <input type="file">.

valeriansaliou commented 2 years ago

You need to PUT to the signed URL.

Send send the unsigned URL resource as content.url in the message, with type file. The content body should also contain name and type as per our docs.

ehsan-mohammadi commented 2 years ago

@valeriansaliou Is this correct?

var file: {
    type: 'image/jpeg',
    name: 'sample.jpeg',
    url: 'Unsigned resource URL',
};

Then I do a PUT request to the signed URL. But, where should I put the file binary (or base64 or other formats) content?

valeriansaliou commented 2 years ago

Yes, LGTM.

ehsan-mohammadi commented 2 years ago

@valeriansaliou So, where should I set the file binary? These are just settings (type, name, and URL).

ehsan-mohammadi commented 2 years ago

Can you give me an example?

valeriansaliou commented 2 years ago

The file should be uploaded to the signed URL you get, using a standard HTTP file upload via HTTP PUT.

ehsan-mohammadi commented 2 years ago

@valeriansaliou Oh, sorry for my bad mistake. Thanks a lot for helping me.

Manouchehri commented 1 year ago

Somewhat related question, is there a way for us to provide our own signed URL for Crisp to use for uploading?

e.g. I have https://untrusted.files.ai.moda/api/v1.0.0-alpha/url/generate that generates a presigned upload URL.

baptistejamin commented 1 year ago

You could just upload your file on your signed and use the bucket URL in the Crisp message, no need to use the bucket API, as its only used to upload files on Crisp.

Manouchehri commented 1 year ago

Hmm, isn't that only useful for operator -> user? I want user attachments -> operator to use a different endpoint.

image