How to send big files from URL to Telegram bot? - php

I have some big size files (in MP4 and Zip formats) and I want to send them to my chat by Telegram bot, I used the code below:
file_get_contents('https://api.telegram.org/bot[[app:token]]/sendDocument?chat_id=24523586&document='.$fileAddress);
But it just can send files with small sizes, less than 50MB! But I know there is no file size limitation for documents which are sending by file_id. You can see this page
Now how can I make file_id for my files? My files are uploaded on my server and I am using PHP.

Telegram bot API can only send files less than 20 MB by url param, you should lookup Sending Files section.
If you want to send 20-50 MB files, you should download and re-upload to Telegram bot API server.
You can refer this simple code
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.telegram.org/bot131210513:AXXXXXX/sendDocument?caption=Hello+World&chat_id=24523586',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: multipart/form-data'
],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'document' => curl_file_create('/etc/hosts', 'plain/text', 'Hosts-file.txt')
]
]);
$data = curl_exec($curl);
curl_close($curl);

2021 Update: Telegram now provides a self hostable Telegram Bot API which can upload 1.5GB.
You can install pwrtelegram on your server. Then simply switch the API URL and you will be able to upload up to 1.5 GB of files with your bot. That is the only possible way. Check out the link for more information.
Also, you cannot pass in any random file_id, as Telegram will not send it. You can only pass in a file_id which has been uploaded by your bot previously. To bypass the limit, use the method, above. It works very well.

Firstly you should send your file(s) to your bot and then get the fileID.
After that you can just use the fileID to send your files and this way the load will be on Telegram's server not yours. Of course you can send the files from your own server to but this method will cause speed reduction for your bot.
Note that when you send a file to your bot and get the fileID, from that moment the file can be sent immediately without needing to store the files on your own server.
You don't need to make a fileID.
All you need is sending the file to the bot and let the bot find out
the fileID and save it somewhere for future transfers.

Related

How to create a Slack message containing an uploaded image?

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());

Streaming video from server to mobile using base64

We are building an application that deals with images and videos and the privacy requirement is high , where users are not allowed to gain access to the images and videos at all time (privacy option) ,
therefore we went with the option of having a php api that clients request the file and the api returns a base64 encoded response that the client decode and display ,that is for image side ,as for video we are having a trouble finding the right logic .
does VideoView in android helps me achieve this ?
does the api needs to send the video in chunks instead of one large base64 ?
is base64 even right for this requirement ,noting that user should not have direct access to the file at all times .
php api function :
function viewFile($data) {
$file = file_get_contents($data['file_path']);
$mime = mime_content_type($data['file_path']);
return ['status' => 200, 'file' => ['mime' => $mime, 'base64' => base64_encode($file)]];
}
Security with base64? That does not exist. I made a text (in Portuguese) that might help you. Read.
I do not recommend using a very large base64. The server will have a lot of load, the download will be slow, etc.
The ideal is to divide it into smaller pieces. For this you can use bento4 e o ExoPlayer.
For images, I recommend using Cipher. More information for Android and More information for PHP
I made this code to encrypt images. It is already quite old, but I think I can help you enteder this issue.
https://github.com/valdeirpsr/estudo-openssl/blob/master/library/OpensslEncrypt/OpensslEncrypt.php

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.

How to download word document from API using Laravel

I am pretty new to using Guzzle with Laravel. I currently just use it for communication between my front-end and a seperate REST api.
I'm trying to download a file from my api but I'm not sure how to go about it. I could just specify the path to the file and directly download it but I also want to be able to stream or view it in my browser so a user can just view a word document instead of just downloading it.
Currently I'm sending a GET request from front end project (with backend to do api calls) to the api project:
$resp = $client->request('GET', env('API_BASE_URL').'/project/'.$id. '/download-report', [ 'headers' => [ 'Authorization' => 'Bearer '. session()->get('api_token') ] ]);
and in my api backend I return the file with the ->download() function.
return response()->download($report->getPath());
Can someone explain what would be the best way to approach this situation?
Solutions for both issues would be awesome, just downloading it, or actually viewing the contents of the word document.
Thanks in advance!
First of all, it's better to serve files with the web server (and leave PHP for "smarter" work). The idea behind it is to generate a "secure" link, that hides the real file and has an expiration timeout.
There are a few ways to do that (depends on your server: nginx, Apache or something else). A good example for nginx, with which you can just generate such link in your API, and send it to the end user through your frontend.
If you prefer to do in PHP for some reasons, just download the file to a temporary file and send it using response()->download() with corresponding headers (Content-Type) in your frontend.
$tmpFile = tempnam(sys_get_temp_dir(), 'reports_');
$resp = $client->request('GET', '...', [
// ... your options ...
'sink' => $tmpFile,
]);
response()->download(
$tmpFile,
null,
[
'Content-Type' => $resp->getHeader('Content-Type')[0]
]
)->deleteFileAfterSend(true);

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.

Categories