How to get a file using fetch in 'Code by Zapier' - zapier

I was requesting an API that delivers pdf. This also need authorization.
var fileUlr = 'https://api.safetyculture.io/audits/1234/exports/5678.pdf';
var getFile = fetch( fileUlr, { method: 'GET', headers: { 'Authorization': 'Bearer 2034weoiroew' } } )
.then( function( fileBinary ) {
return fileBinary;
});
I am getting the file in binary format. How to convert this to original pdf? Then I need to programmatically upload the file to dropbox/google drive. Can you help me?

Related

Trying to upload media to the Meta Whatsapp API but running into errors

Context: I need to send media templates in which I need to send local files. Thus I need to upload the files to the WhatsApp API to get the Media Id, which I can then use to send the message templates.
The issue: I am running into errors while sending the post request to the server through DART. However the same call is working when sent through postman. I have tried sending the data both as a JSON and as form-data, but both are returning errors. I am attaching the code below, as well as the errors I am facing. Any help is really appreciated.
Getting the file path
upload() async{
if(await Permission.storage.isGranted){
FilePickerResult? choice = await FilePicker.platform.pickFiles(allowMultiple: false);
String? path = choice?.files.single.path;
if(path != null){
uploadJson(path);
// uploadFormData(path);
}
}else{
Permission.storage.request();
}
}
Uploading JSON
uploadJson(String path) async{
File imgfile = File(path);
Uint8List imgbytes = await imgfile.readAsBytes();
String bs4str = base64.encode(imgbytes);
print(bs4str);
var headers = {
'Authorization': variables.authorizationToken,
"Content-Type": 'application/json',
};
var body = jsonEncode({
'file': '$bs4str;type=image/jpeg',
'messaging_product':'whatsapp'
});
Response response = await post(Uri.parse('${variables.baseURL}${variables.phoneNumberId}/media'), headers: headers, body: body);
print(response.body);
}
Uploading as Form-data
uploadFormData(String path) async {
var headers = {
'Authorization': 'Bearer EAAGtvNhUHUIBANf5KvyxnZCUKcRn3jTJgPZBR2AbbVhZBZBO7GjoDCnS26FQT6Nr6qdRV993ZCJEbGwiqZCdQ7TZBJX8S6KXQdOTgmSf9ue7GCEN1IL3yqfAUEIN1bw0nyvptHeZBFCsdfwpxZAcS1ZCbCdmqArZC81orVbYRkzJy1h7ChOAygmrchfFtJAapykZAadruFqOWwcVvtudMezse94zENBNVZA0k7pAZD',
};
var request = MultipartRequest('POST', Uri.parse('https://graph.facebook.com/v14.0/106822672107550/media'));
request.fields.addAll({
'messaging_product': 'whatsapp'
});
request.files.add(await MultipartFile.fromPath('file', path));
request.headers.addAll(headers);
Response response = await Response.fromStream(await request.send());
print(response.body);
}
Error for JSON:
flutter: {"error":{"message":"An unknown error has occurred.","type":"OAuthException","code":1,"fbtrace_id":"AE72st2KT8wJFQ_wYvrcJY6"}}
Error for Form-Data:
flutter: {"error":{"message":"(#100) Param file must be a file with one of the following types: audio\/aac, audio\/mp4, audio\/mpeg, audio\/amr, audio\/ogg, audio\/opus, application\/vnd.ms-powerpoint, application\/msword, application\/vnd.openxmlformats-officedocument.wordprocessingml.document, application\/vnd.openxmlformats-officedocument.presentationml.presentation, application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application\/pdf, text\/plain, application\/vnd.ms-excel, image\/jpeg, image\/png, image\/webp, video\/mp4, video\/3gpp. Received file of type 'application\/octet-stream'.","type":"OAuthException","code":100,"fbtrace_id":"AfsxKl38CW7hUF_ixMzNha9"}}
The problem was with the Mime-type of the file. The Multi-Part file class needed the mime-type of the file to be declared while uploading the file, or the file was automatically being uploaded as an octlet-stream. The code to the working request is posted below.
var request = http.MultipartRequest('POST', Uri.parse('https://graph.facebook.com/v14.0/${variables.phoneNumberId}/media'));
request.headers.addAll({
'Authorization': variables.authorizationToken,
'Content-Type': 'multipart/form-data'
});
request.fields.addAll({
'messaging_product': 'whatsapp',
'type': 'application/pdf'
});
// The MIME type of the image or file
const mimeType = 'application/pdf';
// Open the image file
var file = File(path);
// Create a MultipartFile from the File object
final multipartFile = await http.MultipartFile.fromPath(
'file',
file.path,
contentType: MediaType.parse(mimeType),
);
// Create a request body containing the multipart file
request.files.add(multipartFile);
// Send the request
final response = await request.send();
// Check the response status code
if (response.statusCode == 200) {
String body = await response.stream.bytesToString();
var json = jsonDecode(body);
print(json['id']);
} else {
print(response.reasonPhrase);
}

zapier performResume step not being waited for / run

I'm following the docs in zapier regarding the callbackUrl https://platform.zapier.com/cli_docs/docs#zgeneratecallbackurl however cannot seem to get the performResume step to be run. The zap I'm creating based on this integration also does not seem to wait for the callbackUrl to be hit.
const createScreenshot = (z, bundle) => {
const callbackUrl = z.generateCallbackUrl();
const promise = z.request({
url: 'https://myapi.com/v1/render',
method: 'POST',
params: {},
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: {
...bundle.inputData,
webhook_url: callbackUrl
},
removeMissingValuesFrom: {},
});
z.console.log("Returning from perform / createScreenshot");
return promise.then((response) => ({ ...response.data, waiting_for: "performResume" }));
const onScreenshotFinished = (z, bundle) => {
z.console.log("In performResume / onScreenshotFinished", bundle.cleanedRequest);
const responseBody = bundle.cleanedRequest;
let screenshotUrl;
if (responseBody.event === "render.succeeded") {
z.console.log("render was processed successfully", responseBody);
screenshotUrl = responseBody.result.renderUrl;
return { screenshotUrl, ...responseBody };
}
z.console.log("render was not processed", responseBody);
throw z.errors.Error("Screenshot was not successful");
}
module.exports = {
operation: {
perform: createScreenshot,
performResume: onScreenshotFinished,
...
}
}
We talked through this question (and its solution) on GitHub (zapier/zapier-platform#398), but to summarize for SO readers:
When setting up a resumable Zap, the editor uses the sample to populate the data in the callback. No actual waiting happens during the setup process. Once the zap is live, it works like normal.
So, to implement:
perform should return sample data that matches the data the "resume" webhook sends
performSubscribe can read that data and operate normally
See the GH issue for more info.

Onedrive Upload API uploads corrupt file or Image

I am using Onedrive Rest API to Upload a file into my Onedrive Account. Below is the mentioned Microsoft documentation link to the Upload file.
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession?view=odsp-graph-online
Whenever I used the above API the file gets uploaded into my account but the file gets corrupted.
Below mentioned is my request object.
{
method: "PUT",
url: Upload Url,
processData: false,
headers: {
"Authorization": <access_token>
"Content-Disposition": 'form-data; name="metadata"',
"Content-Type": "application/json; charset=UTF-8",
"Content-Transfer-Encoding": "8bit"
},
formData: {
file: {
value: fs.createReadStream("Smile.png"),
options:
{
filename: "Smile.png,
contentType: null
}
}
}
}
The file gets uploaded in the proper folder but it's corrupted and I am unable to view it in my Onedrive Account.
Can someone please help me with this.
The problem lies in how you pass the data in the body. I had the same issue and solved by passing directly the image buffer (in your case fs.createReadStream("Smile.png") as a body (without any curly brackets {})
My code:
const config = {
headers: { Authorization: `Bearer ${token}`,
}
};
const bodyParameters = imageBuffer;
await axios.put("https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{item-id}:/{filename}:/content",bodyParameters,config)

Is there a way to upload media to the Twitter API using the URL of the media resource?

I've created an app that allows users to upload their images to a Google Cloud Storage bucket - which is then used in social media sharing previews.
The image is uploaded directly to the bucket from the user's browser - using the Firebase API.
What I also want to do is - when an image is saved - to automatically post that image on my app's twitter feed.
The way I've done this is to use a Cloud Function trigger on Cloud Storage - which downloads the image and then uploads via the Twitter API.
There's essentially an unnecessary double handling of traffic here is there a way to just give the Twitter API the public location of the file and have it source the file directly?
Here's my code for the current solution:
class Defferred {
constructor() {
const that = this;
this.prom = new Promise((resolve, reject) => {
that.resolve = resolve;
that.reject = reject;
});
}
}
exports.onNewImage = functions.storage.object().onFinalize((object) => {
const prom = new Defferred();
bucket.file(object.name).download((err, file, response) => {
if (err) {
return prom.reject(err);
} else {
twitterClient.post('media/upload', {
media: file
}, (err, media, response) => {
if (!err) {
let status = {
status: "Somebody created this at https://geoplanets.io #geometry #geometricart",
media_ids: media.media_id_string
}
twitterClient.post('statuses/update', status, (error, tweet, response) => {
if (!error) {
return prom.resolve(response);
} else {
return prom.reject(error);
}
});
} else {
return prom.reject(err);;
}
});
}
});
return prom.prom;
});
Is there an alternative way of doing this that doesn't involve downloading the file? - A good answer would highlight the relevant parts of the API documentation that highlight how I would go about working this out myself.
The Twitter node api doesn't have a way to simply pass an URL for media upload. The example they give shows what you're doing now - sending the full content with the request.
The node client is just a wrapper around the REST API, and if you read its docs, you'll see that you have to provide the file content directly to the POST.
Yes!
We can upload media using URL of file by making the downstream of a file.
First we need to make Axios request to have a buffer of it then we can pass it with file type using
twitter-api-v2
use it in this package or REST API
const client = new TwitterApi({
appKey: CONSUMER_KEY,
appSecret: CONSUMER_SECRET,
accessToken: oauth_token,
accessSecret: oauth_token_secret,
});
const url = 'URL OF THE FILE';
const downStream = await axios({
method: 'GET',
responseType: 'arraybuffer',
url: url,
}).catch(function (error) {
res.send({error:error});
});
const mediaId = await client.v1.uploadMedia(downStream.data,{ mimeType: 'png'});
const newTweet = await client.v1.tweet('Hello link tweet!', { media_ids: mediaId });
sample Image

Encoding issue with Axios

I am fetching a web page with axios, but the content-type of the response is ISO-8859-1, and the result given by axios seems like it parses it as UTF-8 and the result has corrupt characters.
I tried to convert the result encoding but nothing works, and I think it does not because of this
For example in the got library I can set encoding to null and overcome the problem, but I would like to ask you what can I do with axios to disable the auto-encoding or change it?
My approach was this:
Make the request with responseType and responseEncoding set as below
const response = await axios.request({
method: 'GET',
url: 'https://www.example.com',
responseType: 'arraybuffer',
responseEncoding: 'binary'
});
Decode reponse.data to the desired format
let html = iso88592.decode(response.data.toString('binary'));
Note: In my case, I needed to decode it using this package.
Without using interceptor or another package, I got the response on a buffer with:
notifications = await axios.request({
method: 'GET',
url: Link,
responseType: 'arraybuffer',
reponseEncoding: 'binary'
});
And next converting it with:
let html = notifications.data.toString('latin1');
In this github issue Matt Zabriskie recommends using an axios response interceptor, which I think is the cleanest option.
axios.interceptors.response.use(response => {
let ctype = response.headers["content-type"];
if (ctype.includes("charset=ISO-8859-1")) {
response.data = iconv.decode(response.data, 'ISO-8859-1');
}
return response;
})
const notifications = await axios.request({
method: 'GET',
url: 'https://...your link',
responseType: 'arraybuffer',
reponseEncoding: 'binary'
});
const decoder = new TextDecoder('ISO-8859-1');
let html = decoder.decode(notifications.data)

Resources