How to create a Slack message containing an uploaded image? - php

I'd like to create a message in the #general channel of my Slackspace from within a PHP script. The message should contain text and an image which was created locally on-the-fly.
I've already created an App, generated an bearer token and have managed to create an text-only message also as an image-upload.
But i didn't know how to create both in one message, as the procedure above creates two messages, one with text and another one with the image.

There are two different approaches on how to post a Slack message with an image.
A. Upload image directly with message
You can upload an image directly to Slack and share it in a channel. Within that request you can also add a comment that will appear as message above the images. This is the easiest approach, however you comment is limited to one string.
API method: files.upload with these arguments:
channels: ID of one or multiple channel for the image to appear in
initial_comment: Your message
B. Post message with image block / attachment
Alternatively you can add an image to your normal message either as image block or secondary attachment. This only works with a public URL to your image file, so you first need to upload your image to an image hoster (which can be your Slack workspace) to get the public URL.
In our example we will use Slack as image hoster, but you can use any image hoster (e.g. Imgur) even your own webserver, as long as you get a public URL for your image file.
Step 1 - Upload image to Slack
API method: files.upload with no special arguments, but make sure to get the file ID from the response. Don't include the channels argument or the image will be posted visible into those channel.
Step 2 - Create public URL
Next you have to mark the uploaded file as public. Only then will it be accessible through its public_url property
API method: files.sharedPublicURL with the file ID as argument.
Next you need to construct the direct image link from the link to website / permalink_public property of the file.
The website link you get from permalink_public has the format:
https://slack-files.com/{team_id}-{file_id}-{pub_secret}
The direct link to the image has the format:
https://files.slack.com/files-pri/{team_id}-{file_id}/{filename}?pub_secret={pub_secret}
So you just need to extract the pub_secret from permalink_public and you should be able to construct the direct link to the image. The other parameters you can get from your file object.
Step 3 - Send message
Finally compose your message with the image URL either as Image Block or in a secondary attachment and submit it using a method of your choice.
API method: chat.PostMessage or any other method for sending message incl. incoming webhooks.
Answer to OP
If you need to stick with webhooks as it appears from your comments and have no access to the Slack API I would suggest uploading the image to an image hoster (e.g. Imgur) and then use approach B.
See also
Slack bot send an image
Can I upload an image as attachment with Slack API?
How to use the permalink_public URL of an uploaded image to include it in a message?

After much tinkering I found that while I could not use the API to create a message and upload an image simultaneously, I can first upload an image and then, with the timestamp returned, use update message to add text to the original message with the image upload.
This is the flow:
1- Use files_upload method to upload an image to my channel (using the channel name)
response = client.files_upload(
channels=my_channel_name,
file=image_path,
initial_comment='My initial comment'
)
2- Get the response from the files_upload and extract the channel id and timestamp of the message.
channel_id = response['file']['groups'][0]
ts = response['file']['shares']['private'][channel_id][0]['ts']
3- Use chat update to add text or rich content to the message with the uploaded image:
response = client.chat_update(
channel=channel_id,
text="My Message",
ts=ts,
blocks=blocks_list
)

For those who might still need this.. this gist helped me. Its a quick and easier way using GuzzleHttp.
use GuzzleHttp\Client;
/**
* Notes:
*
* Tested with guzzlehttp/guzzle version 7.3
* See https://api.slack.com/methods/files.upload for details on how to generate a token
*
*/
$fileName = '';
$filePath = '';
$slacktoken = ''; // See https://api.slack.com/tokens; The token will need file.read and file.write permissions
$client = new Client();
$apiUrl = 'https://slack.com/api/files.upload';
$client = new Client();
$request = $client->post( $apiUrl, [
'headers' => ['Authorization' => 'auth_trusted_header'],
'multipart' => [
[
'name' => 'token',
'contents' => $slacktoken,
],
[
'name' => 'file',
'contents' => fopen($filePath, 'r'),
'filename' => $fileName
],
[
'name' => 'channels',
'contents' => '#general'
],
[
'name' => 'initial_comment',
'contents' => 'File Uploaded'
]
]
]);
var_dump($request->getBody()->getContents());

Related

Graph API: Send mail with attachment by drive item ID?

I'd like to send mail via the Graph API and attach a file by its drive item ID.
At the moment I can successfully send email via the Graph API and attach a file that is on my local server.
However the file originates on OneDrive so the current situation is I have to download the file to my server then re-upload it via the sendMail endpoint as an attachment and then delete it from my server.
This seems like an unneeded step if it's possible to just provide the file ID and let office 365 resolve it all locally.
$mailBody = ...
'attachments' => [
[
'#odata.type' => '#microsoft.graph.fileAttachment',
'Name' => 'file.docx',
'ContentBytes' => $localFile
// 'DriveID' => 'possibly this instead of Content Bytes?'
]
]
...
$response = $this->getGraph()->createRequest("POST", "/users/{primary-user}/sendMail")
->attachBody($mailBody)
->execute();
You can attach a file by its drive item ID, it is called referenceAttachment but not the fileAttachment in your code. The v1.0 edition has very limited support for referenceAttachment. And by that I mean, there isn't much you can do with them beyond acknowledging one exists.
Reference from egorbunov's answer: Send reference attachment to email via Graph API
Create the message draft using POST request to https://graph.microsoft.com/beta/me/messages with payload:
{
"subject": "TestMessage",
"toRecipients": [
{
"emailAddress":{
"address":"egor-mailbox#ya.ru"
}
}
],
"body": {
"contentType": "html",
"content": "<b>Hello!</b>"
}
},
As a response you will get the whole message structure with id set to something like
AQMkADAwATMwMAItMTJkYi03YjFjLTAwAi0wMAoARgAAA_hRKmxc6QpJks9QJkO5R50HAP6mz4np5UJHkvaxWZjGproAAAIBDwAAAP6mz4np5UJHkvaxWZjGproAAAAUZT2jAAAA.
Lets refer to it as {messageID}. NOTE: as you can see I have passed
html-typed body. This is needed because (at least in GraphAPI
Explorer) graph api returns error in case you are trying to add
reference attachment to message with non-html body content-type.
After that you can create an attachment using POST request to https://graph.microsoft.com/beta/me/messages/{messageID}/attachments
{
"#odata.type": "#microsoft.graph.referenceAttachment",
"name": "AttachmentName",
"sourceUrl": "https://1drv.ms/u/s!ASDLKASDLASHDLASKDLJAXCXZ_DASD",
"providerType": "oneDriveConsumer",
"isFolder": false
}
After step 2 you will see created message in your mailbox Drafts folder. To send it use
https://graph.microsoft.com/beta/me/messages/{messageID}/send (=(
turns out it does not work too)
An alternative solution, not add attachment but add the file link in the mail body directly(Let the recipient to download it as needed).

Unable to upload video Tumblr Error - Bad Request (You may only upload one video per post.)

Instead of video if I'll upload photo with same code its working fine.
$post_data = array('type' => 'video', 'caption' => 'hello video','data' => $video_path);
$createPost = $tumblr->createPost($unique_id,$post_data);
I'm getting this error while uploading:
Tumblr\API\RequestException: [400]: Bad Request (You may only upload one video per post.)
There was an issue in the official Tumblr API v2 PHP Client. I had created a pull request here.
Either take a pull or update your local code to fix your code.

S3 ,verify a signed URL in PHP, Deconstruct signed URL

I am using s3 direct uploads along with a database to store the URLS of the files (along with other data like who uploaded etc).
To allow direct upload to s3, I'm creating a presigned URL like :
$s3 = App::make('aws')->createClient('s3', [
'credentials' => [
'key' => 'AAAAAAAAAAAAAAA',
'secret' => 'YYYYYYYYYYYYYYYYYYYY',
]
]);
$command = $s3->getCommand('PutObject', [
'#use_accelerate_endpoint'=>true,
'Bucket' => 'remdev-experimental',
'Key' => "newest newest.txt",
'Metadata' => array(
'foo' => "test",
)
]);
return response()->json(((string)$s3->createPresignedRequest($command, '+1 minutes')->getUri()));
Now, after the file from the client has finished uploading , I want my server to know about it. So I will require the client to send me a request , notifying about the fact that he has finished uploading. For this, I think the simplest(and also secure) way is to just allow the client to send back the signed URL that he just sent back.
Is there a way to parse the URL ?
I am interested in getting the object key , and more importantly , I want to verify that the URL has not been tampered with (meaning, the signature in the URL should match the rest of the contents). How can I do this in php sdk ?
The signed URL is the file's URL with the signature information in the query data. So a signed request for bucket: remdev-experimental file: abc.txt looks like https://s3.amazonaws.com/remdev-experimental/abc.txt?X-Amz-Date=date&X-Amz-Expires=60&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=signature&X-Amz-Credential=SOMEID/20160703/us-east-1/s3/aws4_request&X-Amz-SignedHeaders=Host&x-amz-security-token=some-long-token so all you need to do is get the URL's Path (/remdev-experimental/abc.txt and take everything after the 2nd slash.
Also you should be aware that you can have S3 redirect the browser to a URL using success_action_redirect in an HTTP post policy
Lastly you can have S3 trigger a notification to your server (via SQS, SNS, or Lambda) whenever a file is uploaded.

How to get Twilio Recording file in PHP

I am using Twilio application. I want to get the path of my recording. I am using this code:
$client = new Services_Twilio($sid, $token, $version);
$calls = $client->account->calls->getIterator(0, 50, array(
));
$url = $call->subresource_uris->recordings;
in the variable $url /2010-04-01/Accounts/<acount id>/Calls/callerid/Recordings.json
But when i paste this url "https://api.twilio.com/2010-04-01/Accounts/<acount id>/Calls/callerid/Recordings.json" it gives me alert popup to enter user name and password.
Basically i want this file to save on my system
Twilio evangelist here.
The URL you are using is requesting a list of Recording resources from Twililo, not the actual audio files. Each resource contains a property called Url that represents that actual audio recording file.
If you want to download the audio, you will need to loop through that list of recordings and make a new HTTP GET request to the Url specified in the Url property.
Hope that helps.

Is it possible to post a photo to Facebook by a link, not upload?

Is this possible to create a photo on user/page's timeline not by uploading said photo, but by providing a URL to an already uploaded image? My code so far is this:
$response = $fb->api ("/$page_id/photos", 'post', array (
'name' => $_description,
'source' => $_image_path
));
This results in OAuthException #324 "Requires upload file". Also, I'd like to photo to be immediately posted on the page's timeline - will it happen, or do I need to make a separate call for that?
You can switch parameter source for url, and give it a publicly reachable HTTP URL as value.
But be aware, this only works for photos not on Facebook already – feeding it the URL of a photo on Facebook will result in an error message saying that posting photos from their CDN is not possible.

Categories