How to get larger thumbnails for Facebook page link posts? - ruby-on-rails

I've been successfully fetching only photos posted at my Facebook page via Opengraph api and now I want to display some links shared at the page through the similar method that I've been using to fetch photos.
The problem is that type=link posts don't contain object_id, which can be used to fetch a bigger thumbnail for photos like https://https://graph.facebook.com/<%= post['object_id'] %>/picture. What a type=link post returns is as follows.
Response
"id": "127100524044142_757791214308400",
"from": { ... },
"to": { ... },
"message": "...",
"message_tags": { ... },
"picture": "https://fbexternal-a.akamaihd.net/safe_image.php?d=AQA5ofIEKR1dK6_T&w=158&h=158&url=http\u00253A\u00252F\u00252Fyeondoo.kr\u00252Fassets\u00252Fstaffs-88e474e70d16794e898d5f4bb200f710.jpg",
"link": "...",
"name": "...",
"caption": "...",
"description": "...",
"icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif",
"privacy": {
"value": ""
},
"type": "link",
"status_type": "shared_story",
"created_time": "2015-01-25T06:08:11+0000",
"updated_time": "2015-01-25T07:54:28+0000",
"likes": { ...
],
"paging": { ... }
},
"comments": { ...
],
"paging": { ... }
}
I could get the url for "small" thumbnails via picture property, but this is too small to display on the website. Is there any solution to get a larger thumbnail for Facebook page, if that matters although I don't think it would, link posts via Opengraph API?

I happen to find a field which is not specified as default. It is full_picture and it returns the url for the "larger" thumbnail.
/posts?fields=full_picture
"full_picture": "https://fbexternal-a.akamaihd.net/safe_image.php?d=AQBHe3GKoga49ZHw&url=http%3A%2F%2Fyeondoo.kr%2Fassets%2Fstaffs-88e474e70d16794e898d5f4bb200f710.jpg",
"id": "127100524044142_757791214308400",
"created_time": "2015-01-25T06:08:11+0000"

Related

Is there a way to distingush inline picture and picture attachment via Gmail API

I fetched two emails from Gmail via their APIs, one contains an inline picture, the other contains an picture attachment. See their HTTP response below.
By comparing these two sections, I am not able to tell which picture is attached and which is inline. "Content-Disposition" shows that both are attachments, though one of them is actually an inline photo.
Is there a way to identify inline pictures with the response from Gmail API?
// inline
{
"partId": "2",
"mimeType": "image/heic",
"filename": "image_50410497.JPG",
"headers": [
{
"name": "Content-Type",
"value": "image/heic; name=\"image_50410497.JPG\""
},
{
"name": "Content-Disposition",
"value": "attachment; filename=\"image_50410497.JPG\""
},
{
"name": "Content-Transfer-Encoding",
"value": "base64"
},
{
"name": "X-Attachment-Id",
"value": "18334b929992fd46a211"
},
{
"name": "Content-ID",
"value": "\u003c18334b929992fd46a211\u003e"
}
],
"body": {
"attachmentId": "ANGjdJ8FshN6fd_2OoZEttwPYHk_8q1mVOJevilskBM-6yOZZ6aMMSMblU3Vo5pw-V1_SeDzxkVx0zOg5R-9fGkaSGvGzd6Wi9yVBe4dAn03HDCghyUWFC2jyodeWYmttzzaXyCNRUVPdVxmO7l8yTaeEsQ4Ep1Ze7Nc3bnLNozWHeKZQHQLqGyfLKDdEI1GKjT8X6OuyEY6EWMo8djE30c-BvYjuY95vmomjkjzfoIqTFfpUlMMktNUfvC1SZMHL0arymXmTTM6uVg5N0U2TngVfbKNx0x8hI0bhccB-AiIhwrSqCxM_CZkyXrGRcY",
"size": 2607632
}
},
// attached
{
"partId": "1",
"mimeType": "image/jpeg",
"filename": "unnamed.jpeg",
"headers": [
{
"name": "Content-Type",
"value": "image/jpeg; name=\"unnamed.jpeg\""
},
{
"name": "Content-Disposition",
"value": "attachment; filename=\"unnamed.jpeg\""
},
{
"name": "Content-Transfer-Encoding",
"value": "base64"
},
{
"name": "Content-ID",
"value": "\u003cf_l83jtl4x0\u003e"
},
{
"name": "X-Attachment-Id",
"value": "f_l83jtl4x0"
}
],
"body": {
"attachmentId": "ANGjdJ_6KFGMzvKW6XFwD4BaSjCDSQGWPEMpL97DE1Lx31cKi2cSzSTOMDIdTEV8wyvnLiB8iqg5_1CVlDOOofl4NiEll2IwrxDuE-IdDXP9PmryOXbMp0pFgIQ961UQWQk8yhObqPcx8xWnqQaPWI3pwirH6hhoe3JtswoLXQ1NDs7FjJZ2iivLZHoTvMlh-i4VQIK6JVaEdIcQBejI6WruTi7DuC_ZpRwewfReZ2JsPKtncVCFwOkb0Ov1vElLS7Y1BTATiRzurXQw1A4lYOn5-XDKqXk90p_HxEQO5zEsvdz2MigVSa803-mIvK8RFTyOOuA4iVWEzad0I3mEFVE6bxTfFQ_YnAYm1FLKImnMEkJf5MuyZofZleyu8fjTGGqzvWmjikDGLvAzdM2O",
"size": 1553427
}
}
UPDATE:
Max mentioned 'Content-ID', I can confirm it works for some emails I have, here is an example:
// header of the attachment part
{
"name": "Content-ID",
"value": "\u003cii_l83jb7dh0\u003e"
}
// decoded HTML body
<img src="cid:ii_l83jb7dh0" alt="20190906-2P2A3622.jpeg" width="361" height="542"><br>
Sometimes the only thing that distinguishes them is whether the Content-ID is referenced in the HTML body of the message. More precisely, by any reasonable definition, that image is an attachment, but it may also be referenced as a cid: url in an <img> tag in an HTML mime part. The header information alone cannot tell you that.

Enumerate DriveItem resources of a specific Drive given SharePoint URL and using Graph API

I have a SharePoint URL of the form https://organizationname.sharepoint.com/sites/....
I want to use the Graph API to get a list of all resources in this drive. Reading the API documentation it appears that I require the drive-id of this drive in order to perform this request.
/drives/{drive-id}/root/children
Also, according to the answer to a similar stackoverflow question it appears there are no APIs to convert SharePoint URL to OneDrive driveId. Is there a possible workaround? Is there any way to programmatically get a list of resources from a SharePoint URL?
If your SharePoint URL is https://organizationname.sharepoint.com/sites/yourSiteName, then you can issue a request like this via the Graph API (scope Sites.Read.All might be required):
client.api("/sites/organizationname.sharepoint.com:/sites/yourSiteName:/drives").get();
That request will return something like this:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives",
"value": [
{
"createdDateTime": "2021-07-24T23:35:00Z",
"description": "",
"id": "b!A1234567-ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210",
"lastModifiedDateTime": "2021-08-12T16:39:23Z",
"name": "Dokumente",
"webUrl": "https://organizationname.sharepoint.com/sites/yourSIteName/folderName",
"driveType": "documentLibrary",
"createdBy": {
"user": {
"displayName": "abc"
}
},
"lastModifiedBy": {
"user": {
"email": "bla#organizationame.onmicrosoft.com",
"id": "12345678-4321-4321-4321-012345678901",
"displayName": "zz"
}
},
"owner": {
"group": {
"email": "x#y.onmicrosoft.com",
"id": "09876543-1234-1234-1234-012345678901",
"displayName": "Owner of something"
}
},
"quota": {
"deleted": 345678,
"remaining": 27487788453406,
"state": "normal",
"total": 27487790694400,
"used": 96120
}
}
]
}
The id under description is the drive-id. With that you can get /root/children like so:
client.api("/sites/yourorganizationname.sharepoint.com/drives/b!A1234567-ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210/root/children").get();
While there is no single API or algorithm that allows you to programmatically get a list of resources from a SharePoint URL, you can achieve the same with two Graph API requests.

personal onedrive is returning same id for drive and user?

When reviewing some example OneDrive Items using Graph Explorer, it appears that the user.id and the parentReference.driveId are identical. Is MSFT re-using one Id to identify both the user and drive object?
I have been testing my app against a number of OneDrive Business accounts and I do not believe I have seen this scenario. I would like to understand if this is something specific to OneDrive Personal and/or what implications it might have...
I am not sure this will cause any issues, but my understanding was that all "IDs" were generally unique.
Here's a redacted snippet of JSON returned from Graph Explorer to illustrate what I am seeing:
{
"#microsoft.graph.downloadUrl": "https://xxx.yyy",
"createdDateTime": "2018-12-04T19:02:41.173Z",
"cTag": "aYzpDQjBCMTc0REJFRUY2RTU4ITMxNzEuMjI1",
"eTag": "aQ0IwQjE3NERCRUVGNkU1OCEzMTcxLjk",
"id": "<MY_USER_ID>!3171",
"lastModifiedDateTime": "2018-12-04T19:10:36.83Z",
"name": "blah-2018.docx",
"size": 250538,
"webUrl": "https://1drv.ms/...",
"createdBy": {
"application": {
"displayName": "MSOffice15",
"id": "480728c5"
},
"device": {
"id": "188000899fbcaf"
},
"user": {
"displayName": "My Name",
"id": "<MY_USER_ID>"
}
},
"lastModifiedBy": {
"application": {
"displayName": "MSOffice15",
"id": "480728c5"
},
"device": {
"id": "188000899fbcaf"
},
"user": {
"displayName": "My Name",
"id": "<MY_USER_ID>"
}
},
"parentReference": {
"driveId": "<MY_USER_ID>",
"driveType": "personal",
"id": "<MY_USER_ID>!109",
"path": "/drive/root:"
},
"file": {
"mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"hashes": {
"sha1Hash": "F0370F54348ED81F421EB036868AEBE5253AF58A"
}
},
"fileSystemInfo": {
"createdDateTime": "2018-12-04T19:02:41.173Z",
"lastModifiedDateTime": "2018-12-04T19:02:38.633Z"
}
},
Note that MY_USER_ID is all uppercase in the prefix of the driveItem.Id. It is all lowercase as my driveId and my userId.
OneDrive Personal isn't reusing the same id, it's using the User's Id as a prefix for Drive and DriveItem ids:
{User Id}!{OneDrive ID}
Since there is a 1:1 relationship between an MSA and it's Drive, there isn't much call for a more complex mechanism. OneDrive for Business, on the other hand, is hosted in SharePoint and, as such, use's SharePoint's identifiers.
`

How fetch "webParts" from site pages

I am trying to fetch Pages from Sharepoint sites using graph API.
But when we make GET request with
https://graph.microsoft.com/beta/sites/{site-id}/pages/{page-id}
the response consists of webParts which only have type and data.
Inside data we have an id(which same as type) and an instanceId that is unique for every webPart.
Sample webPart:
{
"type": "d1d91016-032f-456d-98a4-721247c305e8",
"data": {
"id": "d1d91016-032f-456d-98a4-721247c305e8",
"instanceId": "c54a74ef-86c1-44aa-9ba4-802e6841e3a7"
}
My goal is to fetch webPages with complete details and then backup them to a local drive in any format.
The documentation of graph API shows that the responce would consist of complete details for the webPart, but it is not so.
Documentation link: https://learn.microsoft.com/en-us/graph/api/sitepage-get?view=graph-rest-beta&tabs=http
Sample request URL:
https://graph.microsoft.com/beta/sites/m365x214355.sharepoint.com,c1e5444e-12d8-43d3-96b1-f2f66559ef58,b181bdf0-9680-4988-81f7-a24aee4afd6a/pages
Webpart repsonse:
"webParts": [
{
"type": "rte",
"data": {
"innerHTML": "<p>Take a look at the team behind delivering amazing fashion events for Contoso.</p><p>Find out how the team uses the latest technology to plan amazing fashion shows and gather customer feedback for future events.</p><p>Meet the people behind Contoso's events, learn how to plan your own event, and find the necessary resources to run highly successful fashion shows, premiers, and extravaganzas!</p>"
}
},
{
"type": "d1d91016-032f-456d-98a4-721247c305e8",
"data": {
"id": "d1d91016-032f-456d-98a4-721247c305e8",
"instanceId": "c54a74ef-86c1-44aa-9ba4-802e6841e3a7"
}
},
{
"type": "b7dd04e1-19ce-4b24-9132-b60a1c2b910d",
"data": {
"id": "b7dd04e1-19ce-4b24-9132-b60a1c2b910d",
"instanceId": "75ccfeba-ad6c-416d-a859-4a6b114e156e"
}
},
{
"type": "b7dd04e1-19ce-4b24-9132-b60a1c2b910d",
"data": {
"id": "b7dd04e1-19ce-4b24-9132-b60a1c2b910d",
"instanceId": "f04e02fb-45e6-4e74-9f46-0c8d90e7fb8d"
}
},
{
"type": "275c0095-a77e-4f6d-a2a0-6a7626911518",
"data": {
"id": "275c0095-a77e-4f6d-a2a0-6a7626911518",
"instanceId": "c1a222b0-624e-4e30-b544-d2a67e8e1112"
}
}
Expected Response format:
"webParts": [
{
"type": "rte",
"data": {
"innerHTML": "<p>Here are the team's upcoming events:</p>"
}
},
{
"type": "d1d91016-032f-456d-98a4-721247c305e8",
"data": {
"title": "Events",
"description": "Display upcoming events",
"serverProcessedContent": {
"htmlStrings": {},
"searchablePlainTexts": {
"title": ""
},
"imageSources": {},
"links": {
"baseUrl": "https://www.contoso.com/sites/Engineering"
},
"componentDependencies": {
"layoutComponentId": "8ac0c53c-e8d0-4e3e-87d0-7449eb0d4027"
}
},
"dataVersion": "1.0",
"properties": {
"selectedListId": "032e08ab-89b0-4d8f-bc10-73094233615c",
"selectedCategory": "",
"dateRangeOption": 0,
"startDate": "",
"endDate": "",
"isOnSeeAllPage": false,
"layoutId": "FilmStrip",
"dataProviderId": "Event",
"webId": "0764c419-1ecc-4126-ba32-0c25ae0fffe8",
"siteId": "6b4ffc7a-cfc2-4a76-903a-1cc3686dee23"
}
}
}
]
I want webParts in the format as per documentation.
If the instanceId is unique then there might be some reference table to match these instanceIds and fetch the detailed webParts structure.

Uploading items to a personal OneDrive shared folder

OneDrive user A shares a folder with OneDrive user B, and B can access that folder by using the share id.
For example using the graph explorer
GET https://graph.microsoft.com/v1.0/shares/{shareId}
yields
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#shares/$entity",
"id": "{shareId}",
"name": "ASharedFolder",
"owner": { ... }
}
Now, B wants to upload a new file to ASharedFolder.
Reading the OneDrive docs for upload I have tried
PUT https://graph.microsoft.com/v1.0/shares/{shareId}/driveItem/children:/SomeFile.txt:/content
Content-Type text/plain
some text goes here
as well as
PUT https://graph.microsoft.com/v1.0/shares/{shareId}/items/{sharedItemId}:/SomeFile.txt:/content
Content-Type text/plain
some text goes here
but both yield "BadRequest", "Unsupported segment type..."
Edit: I have now played out this scenario in the OneDrive Web UI using two different browsers for OneDrive users A and B, so I know that it is possible (without first adding the shared folder to B's own root), but I need some help figuring out the right request for the OneDrive REST API.
Does anyone know?
I checked the possibility of uploading files to a shared folder on OneDrive belonging to another user. I did not have any problems to achieve it using GraphExplorer.
Here is what I did:
I got a list of shared files and folders:
GET /me/drive/sharedWithMe
Returned (some of the data has been omitted):
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)",
"value": [
{
"#odata.type": "#microsoft.graph.driveItem",
"id": "<itemId>",
"name": "Folder name",
"parentReference": {
"driveId": "<myUserId>",
"driveType": "personal"
},
"remoteItem": {
"id": "<remoteItemId>",
"name": "Folder name",
"createdBy":
"user": {
"displayName": "Other user name",
"id": "<otherUserId>"
}
},
"folder": {
"childCount": 0
},
"parentReference": {
"driveId": "<otherUserId>",
"driveType": "personal"
},
"shared": {
"owner": {
"user": {
"displayName": "Other user name",
"id": "<otherUserId>"
}
}
}
}
}
]
}
Then I preformed PUT request with the following data:
PUT /drives/{otherUserId}/items/{remoteItemId}:/test.txt:/content
Content-Type: text/plain
The contents of the file goes here.
Response: Success - Status Code 201
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives('<otherUserId>')/items/$entity",
"id": "<itemId>",
"name": "test.txt",
"size": 35,
"createdBy": {
"application": {
"displayName": "Graph explorer"
},
"user": {
"displayName": "My user name",
"id": "<myUserId>"
}
},
"parentReference": {
"driveId": "<otherUserId>",
"driveType": "personal",
"id": "<parentReferenceId>",
"name": "Folder name",
"path": "/drives/<otherUserId>/items/<parentReferenceId>"
},
"file": {
"mimeType": "text/plain"
}
}
Then, on the subsequent GET /me/drive/sharedWithMe request, the value of the childCount of the folder has been increased to 1.
NOTE:
The \shares endpoint only allows GET requests to access a shared DriveItem or a collection of shared items. It does not allow to create new items.

Resources