Google Drive API upload file with custom property, properties missing from response - google-api

I am trying to save a google drive file with custom properties, but its not working and due to the very poor documentation of the Google API, i am struggeling with this. Here is my code so far:
$g = new FileCtrl();
$fileMeta = new Google_Service_Drive_DriveFile();
$fileMeta->name = $file['name'];
$fileMeta->parents = [$g->googleDriveFolderId];
$fileMeta->appProperties = (object)['lead_id'=>$file['lid'], 'sales_package_id'=>$file['pid'], 'user_id'=>$user->uid];
//$fileMeta->size = $file['size'];
$fileData = array(
'data' => $fileContent,
'mimeType' => $file['media_type'],
'uploadType' => $file['multipart'],
);
//create file in google drive
$res = $g->client->files->create($fileMeta, $fileData);
It is not returning an error and the event is saved, but without the custom properties!?

You are probably looking for the properties in the returned file resource.
The reason they aren't there is that Drive only returns a small number of the file properties (name, mime type, id). If you want to see the full file resource you need to include fields=* in the request. So a correct request would look something like
POST https://content.googleapis.com/drive/v3/files?fields=*
I don't know the PHP library, so you'll need to figure that bit out. It will be something like
'fields' => '*',

I just tested this.
Request:
{
"name": "Linda Test",
"mimeType": "application/vnd.google-apps.document",
"appProperties": {
"TestingId": "1"
}
}
Response:
{
"kind": "drive#file",
"id": "1mhP2EW4Kbl81F5AuJ4zJ2IPoeI56i_Vd5K-dfGJRj6Y",
"name": "Linda Test",
"mimeType": "application/vnd.google-apps.document"
}
Do a file.get to check the file metadata.
{
"kind": "drive#file",
"id": "1mhP2EW4Kbl81F5AuJ4zJ2IPoeI56i_Vd5K-dfGJRj6Y",
"name": "Linda Test",
"mimeType": "application/vnd.google-apps.document",
"starred": false,
"trashed": false,
"explicitlyTrashed": false,
"parents": [
"0AJpJkOVaKccEUk9PVA"
],
"appProperties": {
"TestingId": "1"
},
...
}
I suggest you check your uploaded file using the File.get method after its returned to be sure that it was added. To my knowledge there is now way to see these added fields via the Google drive website interface. If after ruining a file.get you still find that it wasn't uploaded i suggest you log this as a bug with the Google APIs PHP client library team. This works with raw rest requests it could be an issue with the library.

Related

Can't download reference attachment from MS graph API

I'm using graph API mentioned below -
"client.api(/users/${data_body.payload.originEmail}/messages/${data_body.payload.emailId}/attachments/${data_body.payload.attachmentId}/$value).getStream()"
it works fine for me if attachment type is "fileattachment" but this api is not working in case of "referenceattachment"
also I went through the documentation it says that "Attempting to get the $value of a reference attachment returns HTTP 405."
and it does not return contentBytes
enter image description here
site to refer - https://learn.microsoft.com/en-us/graph/api/attachment-get?view=graph-rest-1.0&tabs=http
1: https://i.stack.imgur.com/fGrft.png
does anyone have any solution to get content data of reference attachment. if yes it would be great help !! Thanks in advance
GET /drive/items/{item-ID}?select=id,#microsoft.graph.downloadUrl
response =>
click to open
Here you can see downloadURL is missing in response
The graph v1.0 endpoint doesn't have any support for reference attachments (other then showing you that one existing on an email). You need to switch to the beta endpoint which will provide the sourceUrl of the attachment in question eg
https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/referenceattachment
eg
https://graph.microsoft.com/beta/me/mailfolders/inbox/messages/..AA=/attachments/AAM..
would give you something like
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#users('..')/mailFolders('inbox')/messages('..')/attachments/$entity",
"#odata.type": "#microsoft.graph.referenceAttachment",
"id": "..",
"lastModifiedDateTime": "2022-04-11T23:53:54Z",
"name": "User1.text",
"contentType": "application/octet-stream",
"size": 565,
"isInline": false,
"sourceUrl": "https://..-my.sharepoint.com/personal/.._com/Documents/Attachments/User1.text",
"providerType": "oneDriveBusiness",
"thumbnailUrl": null,
"previewUrl": null,
"permission": "other",
"isFolder": false
}
You then need to take the sourceURL and download that via the applicable API for the reference attachment. eg in this example its Sharepoint so you can use the SharePoint API to download the file.

how can I compose a bot to iterate trough a xml json object?

I am using the composer to publish a bot to fetch data from an azure storage table.
In short, the bot composer needs to construct a bot to iterate through an XML deserialized JSON object returned by the azure storage rest API.
In my code generated by the composer, the bot does a "set property" step immediately following the successful return of the REST API (storage table query). Given the deserialized object returned by the storage REST API, how should the "set property" statement be constructed so the bot can print our the individual data field,
Another way to phrase the question: how can I use the composer to construct the bot to iterate through a returned deserialized object (coded in XML JSON format)?
Where can I find a document that can shed some light on this matter?
Is there any place I can find a good example? Can it be done via composer?
Thanks in advance.
Yes, it can be done. If the API returns XML, make sure you configure your api call to ask for content type application/xml.
Then you can use use the xPath built in function. Make note that it will return an array if results in more than value matches the expression, in which you can use the foreach function to iterate over it with. I needed to run the nightly build of Composer (with bot-builder 4.12.0) to get it to work for me. See here for some more info:
https://github.com/microsoft/botbuilder-js/pull/3093
Here's an example that worked for me:
"actions": [
{
"$kind": "Microsoft.SendActivity",
"$designer": {
"id": "rGv7XC"
},
"activity": "${SendActivity_rGv7XC()}"
},
{
"$kind": "Microsoft.HttpRequest",
"$designer": {
"id": "TDA1wO"
},
"method": "GET",
"url": "http://www.geoplugin.net/xml.gp?ip=157.54.54.128",
"resultProperty": "dialog.api_response",
"contentType": "application/xml"
},
{
"$kind": "Microsoft.SetProperty",
"$designer": {
"id": "ipNhfY"
},
"property": "dialog.timezone",
"value": "=xPath(dialog.api_response.content,'/geoPlugin/geoplugin_timezone/text()')"
},
{
"$kind": "Microsoft.SendActivity",
"$designer": {
"id": "DxohEx"
},
"activity": "${SendActivity_DxohEx()}"
}
]
You can (if needed/you wish) use the json and jPath built in functions to convert xml to json and then query with. Something like:
${json(user.testXml)} and then
${jPath(user.testJson , "automobiles")}

How to download an image/media using telegram API

I want to start by saying that this question is not for telegram bot API. I am trying to fetch images from a channel using telegram core API. The image is in the media property of the message object
"_": "message",
"pFlags": {
"post": true
},
"flags": 17920,
"post": true,
"id": 11210,
"to_id": {
"_": "peerChannel",
"channel_id": 1171605754
},
"date": 1550556770,
"message": "",
"media": {
"_": "messageMediaPhoto",
"pFlags": {},
"flags": 1,
"photo": {
"_": "photo",
"pFlags": {},
"flags": 0,
"id": "6294134956242348146",
"access_hash": "11226369941418527484",
"date": 1550556770,
I am using the upload.getFile API to fetch the file. Example is
upload.getFile({
location: {
_: 'inputFileLocation',
id: '6294134956242348146',
access_hash: '11226369941418527484'
},
limit: 1000,
offset: 0
})
But the problem is it throws the error RpcError: CODE#400 LIMIT_INVALID. From looking at the https://core.telegram.org/api/files it looks like limit value is invalid. I tried giving limit as
1024000 (1Kb)
20480000 (20Kb)
204800000 (200kb)
But it always return the same error.
For anyone who is also frustrated with the docs. Using, reading and trying out different stuff will ultimately work for you. If possible someone can take up the task of documenting the wonderful open source software.
Coming to the answer, the location object shouldn't contain id or access hash like other APIs rather it has its own parameters as defined in telegram schema.
There is a media property to a message which has a sizes object. This will contains 3 or more size options (thumbnail, preview, websize and so on). Choose the one that you will need and use the volume_id, local_id and secret properties. The working code will look something like this.
upload.getFile({
location: {
_: 'inputFileLocation', (This parameter will change for other files)
volume_id: volumeId,
local_id: localId,
secret: secret
},
limit: 1024 * 1024,
offset: 0
}, {
isFileTransfer: true,
createClient: true
})
The following points should be noted.
Limit should be in bytes (not bits)
Offset will be 0. But if its big file use this and limit to download parts of the file and join them.
Additional parameters such as isFileTransfer and createClient also exists. I haven't fully understood why its needed. If I have time I'll update it later.
Try using a library that's built on top the original telegram library. I'm using Airgram, a JS/TS library which is a well maintained Repo.

Amazon Alexa Device Discovery for Smart Home API with Lambda Failing

I have setup an Alexa Smart Home Skill, all settings done, oauth2 processed done and skill is enabled on my Amazon Echo device. Lambda function is setup and linked to the skill. When I "Discover Devices" I can see the payload hit my Lambda function in the log. I am literally returning via the context.succeed() method the following JSON with a test appliance. However Echo tells me that it fails to find any devices.
{
"header": {
"messageId": "42e0bf9c-18e2-424f-bb11-f8a12df1a79e",
"name": "DiscoverAppliancesResponse",
"namespace": "Alexa.ConnectedHome.Discovery",
"payloadVersion": "2"
},
"payload": {
"discoveredAppliances": [
{
"actions": [
"incrementPercentage",
"decrementPercentage",
"setPercentage",
"turnOn",
"turnOff"
],
"applianceId": "0d6884ab-030e-8ff4-ffffaa15c06e0453",
"friendlyDescription": "Study Light connected to Loxone Kit",
"friendlyName": "Study Light",
"isReachable": true,
"manufacturerName": "Loxone",
"modelName": "Spot"
}
]
}
}
Does the above payload look correct?
According to https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/smart-home-skill-api-reference#discovery-messages the version attribute is required. Your response seems to be missing that attribute.
In my (very short) experience with this, even the smallest mistake in the response would generate a silent error like the one you are experiencing.
I had the same problem. If you are creating discovery for "Entertainment Device", make sure you have wrapped the output in 'event' key for context.succeed
var payload = {
endpoints:
[
{
"endpointId": "My-id",
"manufacturerName": "Manufacturer",
"friendlyName": "Living room TV",
"description": "65in LED TV from Demo AV Company",
"displayCategories": [ ],
"cookie": {
"data": "e.g. ip address",
},
"capabilities":
[
{
"interface": "Alexa.Speaker",
"version": "1.0",
"type": "AlexaInterface"
},
]
}
]
};
var header = request.directive.header;
header.name = "Discover.Response";
context.succeed({ event: {
header: header, payload: payload
} });
Although, in the sample code, this is never mentioned and an incorrect example is given (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/steps-to-create-a-smart-home-skill). However, the response body provided includes the "event" key.
Recreating lambda function helped me fix the issue. I also set "Enable trigger" check button while creating, though I'm not sure if that matters. After that my device provided by skill was found successfully.
Edit: Answer was wrong. Only useful information was this
This context.fail syntax is actually deprecated. Look up the Lambda context object properties, it should look more like "callback(null, resultObj)" now.
Did you include the return statement in your function?
return {
"header": header,
"payload": payload
}
It was missing in the example and after adding it, I was able to 'discover' my device.

google-api-javascript-client : How to get contents of file using Drive API?

First off, if there is a question/answer that solves my problem already then I sincerely apologize for creating a new one. However, I have been searching for 3 days now, and have not found an answer...
My problem is, I cannot for the life of me figure out how to pull the contents of a file(any file). From reading the docs I've discovered that my returned file resource object is supposed to have a property named "downloadUrl", and from this I should be able to access the file contents.
None of the file resource objects that are returned to me(via gapi.client.request) have this field/property. Below is the function I am using to get a file.
Can someone please help point me in the right direction? I have to have this demo done by Monday and I've been stuck on this for 2 days....
Here is the code for my get function :
Client.getFileContent = function getFileContent() {
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.request({
path : '/drive/v2/files/1QmaofXyVqnw6ODXHE5KWlUTcWbA9KkLyb-lBdh_FLUs',
method : 'GET',
params : {
projection: "FULL"
}
});
request.execute(function(response) {
console.log(response);
});
});
};
The file resource object that is returned to me does not have the downloadUrl property.
As requested, here is the response object I get back for a text file. Note, I replaced some of the ids with "fileid" for posting here.
"kind": "drive#file",
"id": "fileID",
"etag": "\"-tJAWr_lbRQU2o8gZ0X7BCBIlVk/MTM0MjYyODQ1MTQ2Nw\"",
"selfLink": "https://www.googleapis.com/drive/v2/files/fileID",
"alternateLink": "https://docs.google.com/document/d/fileID/edit",
"embedLink": "https://docs.google.com/document/d/fileID/preview",
"thumbnailLink": "https://docs.google.com/feeds/vt?gd=true&id=fileID&v=1&s=AMedNnoAAAAAUAfLhbYIDsNIn40k7DfRYBsrquijmCii&sz=s220",
"permissionsLink": "https://www.googleapis.com/drive/v2/files/fileID/permissions",
"title": "Copied filed.txt",
"mimeType": "application/vnd.google-apps.document",
"labels": {
"starred": false,
"hidden": false,
"trashed": false,
"restricted": false,
"viewed": true
},
"createdDate": "2012-07-18T16:20:51.132Z",
"modifiedDate": "2012-07-18T16:20:51.467Z",
"modifiedByMeDate": "2012-07-18T16:20:51.467Z",
"lastViewedByMeDate": "2012-07-18T16:20:51.467Z",
"parents": [
{
"kind": "drive#parentReference",
"id": "0AAAYYkwdgVqHUk9PVA",
"selfLink": "https://www.googleapis.com/drive/v2/files/fileID/parents/0AAAYYkwdgVqHUk9PVA",
"parentLink": "https://www.googleapis.com/drive/v2/files/0AAAYYkwdgVqHUk9PVA",
"isRoot": true
}
],
"exportLinks": {
"application/vnd.oasis.opendocument.text": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=odt",
"application/msword": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=doc",
"text/html": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=html",
"application/rtf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=rtf",
"text/plain": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=txt",
"application/pdf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=pdf"
},
"userPermission": {
"kind": "drive#permission",
"etag": "\"-tJAWr_lbRQU2o8gZ0X7BCBIlVk/9STkNeCmz61YXorH3hoJimnEgfM\"",
"id": "current",
"role": "owner",
"type": "user"
},
"quotaBytesUsed": "0",
"ownerNames": [
"Joshua.morine"
],
"lastModifyingUserName": "Joshua.morine",
"editable": true,
"writersCanShare": true
}
For native Google documents (Google Spreadsheet, Presentation etc...) we don;t provide a downloadUrl as these can't really be downloaded as files in their native format. Instead you'll have to use one of the URLs in the list of exportLinks which provides URLs to download the Google Documents in a few different export formats.
In your case, a Google Documents the following can be used:
"exportLinks": {
"application/vnd.oasis.opendocument.text": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=odt",
"application/msword": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=doc",
"text/html": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=html",
"application/rtf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=rtf",
"text/plain": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=txt",
"application/pdf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=pdf"
}
The meta-data function you are looking for is actually:
request = gapi.client.drive.files.get({
'fileId': fileId
});
This one produces a result with the downloadUrl that you're referring to. Then it's easy to grab the file using any HTTP request.

Resources