How to get proposed time using Microsoft Graph API? - outlook

When the other person declined the meeting and proposed a new time. In Outlook, you can see the proposed time.
Now I am trying to use Microsoft Graph API to get that proposed time.
For example, the original meeting date is 2018-03-08, and the other person declined and proposed a new date 2018-03-12.
I tried
GET /beta/me/messages/{messageId}=?$expand=microsoft.graph.eventMessage/event
However, I cannot find the proposed time from the result returned. How can I get it? Thanks
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#users('576552d5-3bc0-42a6-a53d-bfceb405db23')/messages/$entity",
"#odata.type": "#microsoft.graph.eventMessage",
"#odata.etag": "W/\"DAAAABYAAACpTc/InBsuTYwTUBb+VIb4AADoRAyI\"",
"id": "AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk-iwQZRbXMgkfKtmYhBwCpTc-InBsuTYwTUBb_VIb4AAAAAAEMAACpTc-InBsuTYwTUBb_VIb4AADnwc8mAAA=",
"createdDateTime": "2018-03-06T22:29:10Z",
"lastModifiedDateTime": "2018-03-06T22:29:11Z",
"changeKey": "DAAAABYAAACpTc/InBsuTYwTUBb+VIb4AADoRAyI",
"categories": [],
"receivedDateTime": "2018-03-06T22:29:11Z",
"sentDateTime": "2018-03-06T22:29:05Z",
"hasAttachments": false,
"internetMessageId": "<MWHPR15MB18399806CC97C61817C9A2B18BD90#MWHPR15MB1839.namprd15.prod.outlook.com>",
"subject": "New Time Proposed: Test",
"bodyPreview": "",
"importance": "normal",
"parentFolderId": "AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgAuAAAAAACUbnk-iwQZRbXMgkfKtmYhAQCpTc-InBsuTYwTUBb_VIb4AAAAAAEMAAA=",
"conversationId": "AAQkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgAQAOnuCMgoRLdGs-1scw6i7EU=",
"conversationIndex": "AdO1mnWL6e4IyChEt0az/WxzDqLsRQAABO5D",
"isDeliveryReceiptRequested": null,
"isReadReceiptRequested": false,
"isRead": false,
"isDraft": false,
"webLink": "https://outlook.office365.com/owa/?ItemID=AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk%2FiwQZRbXMgkfKtmYhBwCpTc%2FInBsuTYwTUBb%2BVIb4AAAAAAEMAACpTc%2FInBsuTYwTUBb%2BVIb4AADnwc8mAAA%3D&exvsurl=1&viewmodel=ReadMessageItem",
"inferenceClassification": "focused",
"unsubscribeData": [],
"unsubscribeEnabled": false,
"meetingMessageType": "meetingDeclined",
"type": "singleInstance",
"isOutOfDate": false,
"isAllDay": false,
"isDelegated": false,
"body": {
"contentType": "html",
"content": "Hi"
},
"sender": {
"emailAddress": {
"name": "Rose",
"address": "rose#example.com"
}
},
"from": {
"emailAddress": {
"name": "Rose",
"address": "rose#example.com"
}
},
"toRecipients": [
{
"emailAddress": {
"name": "Jack",
"address": "jack#example.com"
}
}
],
"ccRecipients": [],
"bccRecipients": [],
"replyTo": [],
"mentionsPreview": null,
"flag": {
"flagStatus": "notFlagged"
},
"startDateTime": {
"dateTime": "2018-03-08T04:00:00.0000000",
"timeZone": "UTC"
},
"endDateTime": {
"dateTime": "2018-03-08T05:00:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "Test",
"locationType": "default",
"uniqueIdType": "unknown"
},
"recurrence": null,
"event#odata.context": "https://graph.microsoft.com/beta/$metadata#users('576552d5-3bc0-42a6-a53d-bfceb405db23')/messages('AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk-iwQZRbXMgkfKtmYhBwCpTc-InBsuTYwTUBb_VIb4AAAAAAEMAACpTc-InBsuTYwTUBb_VIb4AADnwc8mAAA%3D')/microsoft.graph.eventMessage/event/$entity",
"event": {
"#odata.etag": "W/\"qU3PyJwbLk2ME1AW/lSG+AAA6EQMeA==\"",
"id": "AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk-iwQZRbXMgkfKtmYhBwCpTc-InBsuTYwTUBb_VIb4AAAAAAENAACpTc-InBsuTYwTUBb_VIb4AADnwkmiAAA=",
"createdDateTime": "2018-03-06T22:28:32.3852279Z",
"lastModifiedDateTime": "2018-03-06T22:29:11.4604154Z",
"changeKey": "qU3PyJwbLk2ME1AW/lSG+AAA6EQMeA==",
"categories": [],
"originalStartTimeZone": "Pacific Standard Time",
"originalEndTimeZone": "Pacific Standard Time",
"iCalUId": "040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000310000007643616C2D5569640100000033324633333433392D433744452D344338362D393046452D44424639314131363444323900",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Test",
"bodyPreview": "Test",
"importance": "normal",
"sensitivity": "normal",
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "busy",
"type": "singleInstance",
"webLink": "https://outlook.office365.com/owa/?itemid=AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk%2FiwQZRbXMgkfKtmYhBwCpTc%2FInBsuTYwTUBb%2BVIb4AAAAAAENAACpTc%2FInBsuTYwTUBb%2BVIb4AADnwkmiAAA%3D&exvsurl=1&path=/calendar/item",
"onlineMeetingUrl": null,
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"body": {
"contentType": "html",
"content": "Hi"
},
"start": {
"dateTime": "2018-03-08T04:00:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2018-03-08T05:00:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "Test",
"locationType": "default",
"uniqueId": "Test",
"uniqueIdType": "private"
},
"locations": [
{
"displayName": "Test",
"locationType": "default",
"uniqueId": "Test",
"uniqueIdType": "private"
}
],
"recurrence": null,
"attendees": [
{
"type": "required",
"status": {
"response": "declined",
"time": "2018-03-06T22:29:05Z"
},
"emailAddress": {
"name": "Rose",
"address": "rose#example.com"
}
}
],
"organizer": {
"emailAddress": {
"name": "Jack",
"address": "jack#example.com"
}
}
}
}

The API doesn't expose this information directly. The related entities just don't have the fields defined to show this information. However, the data is obviously there, you just need to know how to get to it. The answer lies in extended properties.
Basically since Graph doesn't expose these values, we need to dig into the MAPI properties that store this data. After a little digging through the Exchange server protocol docs I found PidLidAppointmentProposedStartWhole and PidLidAppointmentProposedEndWhole. We just need to translate those MAPI property definitions into the Graph extended property syntax.
From the doc, those are both in the PSETID_Appointment namespace, which uses the GUID {00062002-0000-0000-C000-000000000046}. PidLidAppointmentProposedStartWhole uses id 0x8250, and PidLidAppointmentProposedEndWhole uses id 0x8251. So those should translate to:
PidLidAppointmentProposedStartWhole: 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8250'
PidLidAppointmentProposedEndWhole: 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8251'
If we use those in an $expand clause as per Get singleValueLegacyExtendedProperty, we get something like:
GET /me/mailfolders/inbox/messages?$expand=singleValueExtendedProperties($filter=id eq 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8250' or id eq 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8251')
And the response looks something like this (other properties omitted):
{
"subject": "New Time Proposed: Let's meet",
"singleValueExtendedProperties": [
{
"id": "SystemTime {00062002-0000-0000-c000-000000000046} Id 0x8250",
"value": "2018-03-20T20:00:00Z"
},
{
"id": "SystemTime {00062002-0000-0000-c000-000000000046} Id 0x8251",
"value": "2018-03-20T21:00:00Z"
}
]
}

Related

process json using jq in bash script

Below is my json which I need to process using jq in bash script. I need to get the "Id" column value. Since in this json there are 3 records, record with maximum value id would be returned. So after processing of below json I should get 170.
I am newbie and have very limited exposure to bash.
{
"count": 3,
"value": [
{
"properties": {},
"tags": [], "validationResults": [],
"plans": [
{
"planId": "49699e0f-b893-4633-bc05-754b8a562d07"
}
], "triggerInfo": {},
"id": 170,
"buildNumber": "20181011.8", "status": "completed", "result": "succeeded", "queueTime": "2018-10-11T15:56:24.9611153Z", "startTime": "2018-10-11T15:56:28.3668144Z", "finishTime": "2018-10-11T15:57:20.5163422Z",
"url": "https://indiatelecom.visualstudio.com/d354caa2-2e88-414a-829b-25df3aceaaaf/_apis/build/Builds/170",
"buildNumberRevision": 8, "uri": "vstfs:///Build/Build/170",
"sourceBranch": "refs/heads/master", "sourceVersion": "4303c19f8fda79e35fcb598219d5dca6bb274c2d",
"priority": "normal", "reason": "manual", "lastChangedDate": "2018-10-11T15:57:20.797Z", "parameters": "{\"system.debug\":\"false\"}",
"orchestrationPlan": {
"planId": "49699e0f-b893-4633-bc05-754b8a562d07"
}, "keepForever": false, "retainedByRelease": false, "triggeredByBuild": null
},
{ "properties": {}, "tags": [], "validationResults": [],
"plans": [ { "planId": "15026a2f-c725-4e52-974b-61e01a940661"
} ],
"triggerInfo": {},
"id": 160,
"buildNumber": "20181009.20", "status": "completed", "result": "succeeded", "queueTime": "2018-10-09T16:47:42.2954075Z", "startTime": "2018-10-09T16:47:43.8034575Z",
"finishTime": "2018-10-09T16:48:35.8340469Z", "url": "https://indiatelecom.visualstudio.com/d354caa2-2e88-414a-829b-25df3aceaaaf/_apis/build/Builds/160",
"buildNumberRevision": 20, "uri": "vstfs:///Build/Build/160",
"sourceBranch": "refs/heads/master", "sourceVersion": "19a55c7482083785265b86015150521b40230c11",
"priority": "normal", "reason": "manual",
"lastChangedDate": "2018-10-09T16:48:36.057Z", "parameters": "{\"system.debug\":\"false\"}",
"orchestrationPlan": {
"planId": "15026a2f-c725-4e52-974b-61e01a940661"
},
"keepForever": false, "retainedByRelease": false,
"triggeredByBuild": null },
{
"properties": {}, "tags": [],
"validationResults": [], "plans": [
{
"planId": "e45d9da8-4d95-42b7-aa23-478e1c1c49f5"
}
],
"triggerInfo": {},
"id": 147,
"buildNumber": "20181009.7", "status": "completed",
"result": "succeeded", "queueTime": "2018-10-09T15:15:47.0248009Z",
"startTime": "2018-10-09T15:15:50.8899892Z", "finishTime": "2018-10-09T15:16:47.7866356Z",
"url": "https://indiatelecom.visualstudio.com/d354caa2-2e88-414a-829b-25df3aceaaaf/_apis/build/Builds/147",
"buildNumberRevision": 7, "uri": "vstfs:///Build/Build/147",
"sourceBranch": "refs/heads/master", "sourceVersion": "70fccb138a2f2a9dfe18290c468959102f504067",
"priority": "normal", "reason": "manual",
"lastChangedDate": "2018-10-09T15:16:48.16Z",
"parameters": "{\"system.debug\":\"false\"}", "orchestrationPlan": {
"planId": "e45d9da8-4d95-42b7-aa23-478e1c1c49f5"
}, "keepForever": false, "retainedByRelease": false,
"triggeredByBuild": null }
] }
The id's are stored in an array under the key value. .value[].id lists the ids, if you put them into an array, you can call max on it:
jq '[.value[].id] | max' < file.json

Can I sync calendar events with the Microsoft Graph API?

I'm working with the Microsoft Graph api to try and sync calendar events from Outlook. I was looking at this article concerning the Outlook api, which suggested I add the header odata.track-changes to my request and I would receive a deltaToken, which I could use on a later request to fetch only those events which had been updated or created since the last sync.
I have been successful fetching events, but I'm not getting a deltaToken back :/
Is this only supported in the Outlook api? Graph's response has Preference-Applied: odata.track-changes, so it's acknowledging my header. Here's my sample request:
GET /v1.0/me/calendar/calendarView
?startDateTime=2016-09-01T00:00:00.0000000
&endDateTime=2099-01-01T00:00:00.0000000
HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer XXX
Prefer: odata.track-changes
Prefer: odata.maxpagesize=3 //for testing
Cache-Control: no-cache
And my sample response:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('')/calendar/calendarView",
"value": [
{
"#odata.etag": "",
"id": "",
"createdDateTime": "2016-08-04T14:00:25.8552351Z",
"lastModifiedDateTime": "2016-08-25T14:43:54.9950828Z",
"changeKey": "",
"categories": [
"Orange category"
],
"originalStartTimeZone": "Eastern Standard Time",
"originalEndTimeZone": "Eastern Standard Time",
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"iCalUId": "",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Closing on House",
"body": {
"contentType": "html",
"content": ""
},
"bodyPreview": "",
"importance": "normal",
"sensitivity": "normal",
"start": {
"dateTime": "2016-09-08T19:30:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-09-08T21:30:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "245 E Main St",
"address": {
"street": "245 E Main St",
"city": "Somewhere",
"state": "NY",
"countryOrRegion": "United States",
"postalCode": ""
}
},
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"recurrence": null,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "busy",
"type": "singleInstance",
"attendees": [],
"organizer": {
"emailAddress": {
"name": "",
"address": ""
}
},
"webLink": "https://outlook.office365.com/owa/?ItemID="
},
{
"#odata.etag": "",
"id": "",
"createdDateTime": "2016-08-19T18:02:39.0607411Z",
"lastModifiedDateTime": "2016-08-19T18:04:10.548447Z",
"changeKey": "",
"categories": [
"Green category"
],
"originalStartTimeZone": "UTC",
"originalEndTimeZone": "UTC",
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"iCalUId": "",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Moving (off work)",
"body": {
"contentType": "html",
"content": ""
},
"bodyPreview": "",
"importance": "normal",
"sensitivity": "normal",
"start": {
"dateTime": "2016-09-10T00:00:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-09-13T00:00:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "",
"address": {}
},
"isAllDay": true,
"isCancelled": false,
"isOrganizer": true,
"recurrence": null,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "oof",
"type": "singleInstance",
"attendees": [],
"organizer": {
"emailAddress": {
"name": "",
"address": ""
}
},
"webLink": "https://outlook.office365.com/owa/?ItemID="
},
{
"#odata.etag": "",
"id": "",
"createdDateTime": "2016-09-13T19:05:20.8438647Z",
"lastModifiedDateTime": "2016-09-13T19:05:22.1899702Z",
"changeKey": "",
"categories": [],
"originalStartTimeZone": "America/New_York",
"originalEndTimeZone": "America/New_York",
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"iCalUId": "",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Coffee Break",
"body": {
"contentType": "html",
"content": ""
},
"bodyPreview": "",
"importance": "normal",
"sensitivity": "normal",
"start": {
"dateTime": "2016-09-15T20:15:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-09-15T21:15:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "",
"address": {}
},
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"recurrence": null,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "busy",
"type": "singleInstance",
"attendees": [],
"organizer": {
"emailAddress": {
"name": "",
"address": ""
}
},
"webLink": "https://outlook.office365.com/owa/?ItemID="
}
]
}
I redacted anything I thought could be mildly sensitive. Ultimately, my Laravel app is trying to sync events starting 4 months back, and go forever into the future.
If there's a more efficient/better way to do it, I'm open to suggestions. If it matters, these results were generated with Postman. Any help or clarity on this is appreciated.
I ended up using the odata filter like so:
https://graph.microsoft.com/beta/me/calendar/calendarView?startDateTime=2016-05-01T00:00:00Z&endDateTime=2099-01-01T00:00:00Z&$filter=type eq 'singleInstance' and lastModifiedDateTime eq '2016-09-20T07:30:00+00:00'
This will fetch all calendar events scheduled between 2016-05-01T00:00:00Z (May 1st, 2016, midnight, UTC and 2099-01-01T00:00:00Z (January 1st, 2099, midnight, UTC) where the event type is singleInstance (not a recurring event) and the lastModifiedDateTime is after the last sync (in this example, 2016-09-20T07:30:00+00:00).
A few pitfalls with this:
Obviously, this is not url encoded. You would need to do that.
Make sure the + in the lastModifiedDateTime example is properly encoded to %2B, otherwise the Graph API will treat it as a space and reject it.
If you don't filter out recurring events, you will get each recurring event from now until 2099. This is the nature of fetching a list of calendarViews as opposed to events.
If I could do this again, I would probably go back and just do the full calendar sync, which Graph supports (I believe). I just didn't want to sync the whole calendar, only a date range, but it seems that was a doomed endeavor.
But despite the lack of recurring events, it works.
UPDATE
I ended up scrapping this implementation mostly because of the continuing pitfalls I've encountered with maintaining data sync integrity, lack of recurring events, and etc. Instead, I pull calendar events in real time, and maintain a cache. Just some advice in case anyone else ends up in my situation.

Fetch all user ids under domain

How do I fetch all user Ids under our company domain using Google API?
I want to get list of all users under our domain.
Then I want to get a list of all emails for each user.
I think you are referring to Retrieve all users in a domain:
To retrieve all users in the same domain, use the following GET request and include the authorization described in Authorize requests. For readability, this example uses line returns:
GET https://www.googleapis.com/admin/directory/v1/users
?domain=primary domain name&pageToken=token for next results page
&maxResults=max number of results per page
&orderBy=email, givenName, or familyName
&sortOrder=ascending or descending
&query=email, givenName, or familyName:the query's value*
By default, the system returns a list of 100 users in the alphabetical order of the user's email address:
GET https://www.googleapis.com/admin/directory/v1/users?domain=example.com&maxResults=2
A successful response returns an HTTP 200 status code. Along with the status code, the response returns 2 user accounts in the example.com domain (maxResults=2):
{
"kind": "directory#users",
"users": [
{
"kind": "directory#user",
"id": "the unique user id",
"primaryEmail": "liz#example.com",
"name": {
"givenName": "Liz",
"familyName": "Smith",
"fullName": "Liz Smith"
},
"isAdmin": true,
"isDelegatedAdmin": false,
"lastLoginTime": "2013-02-05T10:30:03.325Z",
"creationTime": "2010-04-05T17:30:04.325Z",
"agreedToTerms": true,
"hashFunction: "SHA-1",
"suspended": false,
"changePasswordAtNextLogin": false,
"ipWhitelisted": false,
"ims": [
{
"type": "work",
"protocol": "gtalk",
"im": "lizim#talk.example.com",
"primary": true
}
],
"emails": [
{
"address": "liz#example.com",
"type": "work",
"customType": "",
"primary": true
}
],
"addresses": [
{
"type": "work",
"customType": "",
"streetAddress": "1600 Amphitheatre Parkway",
"locality": "Mountain View",
"region": "CA",
"postalCode": "94043"
}
],
"externalIds": [
{
"value": "employee number",
"type": "custom",
"customType": "office"
}
],
"relations": [
{
"value": "susan",
"type": "friend",
"customType": ""
}
],
"organizations": [
{
"name": "Google Inc.",
"title": "SWE",
"primary": true,
"customType": "",
"description": "Software engineer"
}
],
"phones": [
{
"value": "+1 nnn nnn nnnn",
"type": "work"
}
],
"aliases": [
"lizsmith#example.com",
"lsmith#example.com"
],
"nonEditableAliases: [
"liz#test.com"
],
"customerId": "C03az79cb",
"orgUnitPath": "corp/engineering",
"isMailboxSetup": true,
"includeInGlobalAddressList": true
},
{
"kind": "directory#user",
"id": "user unique ID",
"primaryEmail": "admin2#example.com",
"name": {
"givenName": "admin",
"familyName": "two",
"fullName": "admin two"
},
"isAdmin": true,
"isDelegatedAdmin": true,
"lastLoginTime": "2013-02-05T10:30:03.325Z",
"creationTime": "2010-04-05T17:30:04.325Z",
"agreedToTerms": true,
"hashFunction: "SHA-1",
"suspended": true,
"suspensionReason": "ADMIN",
"changePasswordAtNextLogin": false,
"ipWhitelisted": false,
"emails": [
{
"address": "admin2#example.com",
"type": "work",
"customType": "",
"primary": true
}
],
"externalIds": [
{
"value": "contractor license number",
"type": "custom",
"customType": "work"
}
],
"relations": [
{
"value": "liz",
"type": "friend",
"customType": ""
}
],
"aliases": [
"second_admin#example.com"
],
"nonEditableAliases: [
"admin#test.com"
],
"customerId": "C03az79cb",
"orgUnitPath": "corp/engineering",
"isMailboxSetup": true,
"includeInGlobalAddressList": true
}
],
"nextPageToken": "next page token"
}
You can also check out Retrieve all account users
To retrieve all users in an account which can consist of multiple domains, use the following GET request and include the authorization described in Authorize requests.

Combine JSON objects in Ruby, and output to CSV

Let's say I have two JSON objects (call them 'websites' and 'links'). I need to end up with both objects in a single CSV (ideally in separate columns).
I'm working with something like this:
File.open("file.json", "w") do |f|
combined = [websites, links]
f.write(JSON.pretty_generate(combined))
end
And then I'm using the Ruby gem json2csv to convert this file to a CSV. But when I do, I get the following error:
error: undefined method 'keys' for #<Array:0x007fea8a8e33f8>
I can't figure out what's wrong. When I look in file.json, it appears to be structured like this: [{websites}, {links}]. From my limited knowledge of JSON, I think that's right, but I could easily be wrong.
Also, I know this won't get me separate columns in the CSV. If anyone has an answer for that part, major bonus points.
EDIT: JSON examples included below; error message changed after minor fix on my end.
websites:
{
"uri": "https://v1/websites",
"id": 28235674,
"background": null,
"createdDate": 1399585684000,
"lastActivityDate": 1430682494000,
"lastCommunicationDate": 1430682494000,
"lastNonCommunicationChronicleDate": 1430330886000,
"lastModifiedDate": 1449263116000,
"lastViewedDate": 1421429034000,
"preferredContactType": null,
"rss": "",
"emailAddresses": [
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "not found",
"type": "Work"
}
],
"phoneNumbers": [
],
"streetAddresses": [
],
"socialNetworks": [
{
"profileUrl": "http://twitter.com",
"name": "Twitter"
},
{
"profileUrl": "http://www.facebook.com",
"name": "Facebook"
},
{
"profileUrl": "http://plus.google.com",
"name": "GooglePlus"
},
{
"profileUrl": "http://www.linkedin.com",
"name": "LinkedIn"
},
{
"profileUrl": "http://twitter.com",
"name": "Twitter"
}
],
"contactUrls": [
],
"tags": [
"tag1",
"tag2"
],
"mostRecentActivity": "https://v1/history",
"mostRecentChronicle": "https://v1/history",
"mostRecentCommunication": "https://v1/history",
"mostRecentNonCommunicationChronicle": "https://v1/history",
"projectStates": "https://v1/websites",
"history": "https://v1/history",
"customFieldValues": [
],
"name": "",
"primaryDomain": "",
"domains": [
""
],
"associatedPeople": "https://v1/people",
"payments": "https://payments",
"links": "https://v1/links",
"type": "https://v1/websites"
}
links:
{
"uri": "https://v1/links/custom_fields",
"id": 15529329,
"value": "Name",
"backgroundColor": null,
"customField": "https://v1/links/custom_fields"
}
combined output:
[
{
"uri": "https://v1/websites",
"id": 28235674,
"background": null,
"createdDate": 1399585684000,
"lastActivityDate": 1430682494000,
"lastCommunicationDate": 1430682494000,
"lastNonCommunicationChronicleDate": 1430330886000,
"lastModifiedDate": 1449263116000,
"lastViewedDate": 1421429034000,
"preferredContactType": null,
"rss": "",
"emailAddresses": [
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "not found",
"type": "Work"
}
],
"phoneNumbers": [
],
"streetAddresses": [
],
"socialNetworks": [
{
"profileUrl": "http://twitter.com/",
"name": "Twitter"
},
{
"profileUrl": "http://www.facebook.com",
"name": "Facebook"
},
{
"profileUrl": "http://plus.google.com",
"name": "GooglePlus"
},
{
"profileUrl": "http://www.linkedin.com/",
"name": "LinkedIn"
},
{
"profileUrl": "http://twitter.com/",
"name": "Twitter"
}
],
"contactUrls": [
],
"tags": [
"tag1",
"tag2"
],
"mostRecentActivity": "https://v1/history/",
"mostRecentChronicle": "https://v1/history/",
"mostRecentCommunication": "https://v1/history/",
"mostRecentNonCommunicationChronicle": "https://v1/history/",
"projectStates": "https://v1/websites/",
"history": "https://v1/history",
"customFieldValues": [
],
"name": "",
"primaryDomain": "",
"domains": [
""
],
"associatedPeople": "https://v1/people",
"links": "https://v1/links",
"type": "https://v1/websites"
},
{
"uri": "https://links/custom_fields",
"id": 15529329,
"value": "Name",
"backgroundColor": null,
"customField": "https://links/custom_fields"
}
]
JSON.pretty_generate() is expecting a hash and you are passing an array of 2 hashes. Start with: combined.map { |c| f.write(JSON.pretty_generate(c)) } and then mapping them into your CSV should be as easy as following the CSV documentation.

ArrowDB dashboard upload photo to user

when I upload a photo using the arrowdb dashboard on https://platform.appcelerator.com
Cloud.Users.query only shows the photo_id
but whne I created a new user using the dashboard and attached a phot it is showing in the Cloud.Users.query
eg . photo uploaded after user created
{
"id": "563019f18cb04aede69e2111",
"first_name": "store1",
"last_name": "123",
"created_at": "2015-10-28T00:42:25+0000",
"updated_at": "2016-01-22T08:59:44+0000",
"external_accounts": [],
"confirmed_at": "2015-10-28T00:42:25+0000",
"username": "user",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
"photo_id": "56a1dc083a654d090d126792",
"friend_counts": {
"requests": 0,
"friends": 0
}
}
eg. photo uploaded while creating user
{
"id": "56a1f0333a65234234390d7",
"first_name": "qqqq",
"last_name": "wwwe",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:07:18+0000",
"external_accounts": [],
"confirmed_at": "2016-01-22T09:02:43+0000",
"username": "qwe",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
"photo": {
"id": "56a1f0333a654d090d0390d8",
"filename": "userPhoto.jpg",
"size": 25394,
"md5": "e20f4fcadf6cde9fccfb458dd11951d4",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:02:43+0000",
"processed": true,
"urls": {
"original": "https://s3-us-west-1.amazonaws.com/storage-platform.cloud.appcelerator.com/xmqh1djNEIChtQFP6d37HNH5DQNCXQoX/photos/51/d4/56a1f0333a654d090d0390d9/userPhoto_original.jpg"
},
"content_type": "image/jpeg",
"user": {
"id": "56a1f0333a65234234390d7",
"first_name": "qqqq",
"last_name": "wwwe",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:07:18+0000",
"external_accounts": [],
"confirmed_at": "2016-01-22T09:02:43+0000",
"username": "qwe",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
"photo_id": "56a1f0333a654d090d0390d8",
"friend_counts": {
"requests": 0,
"friends": 0
}
}
},
"friend_counts": {
"requests": 0,
"friends": 0
}
}
basically the user which had photo uploaded during creation shows this extra info
"photo": {
"id": "56a1f0333a654d090d0390d8",
"filename": "userPhoto.jpg",
"size": 25394,
"md5": "e20f4fcadf6cde9fccfb458dd11951d4",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:02:43+0000",
"processed": true,
"urls": {
"original": "https://s3-us-west-1.amazonaws.com/storage-platform.cloud.appcelerator.com/xmqh1djNEIChtQFP6d37HNH5DQNCXQoX/photos/51/d4/56a1f0333a654d090d0390d9/userPhoto_original.jpg"
},
"content_type": "image/jpeg",
"user": {
"id": "56a1f0333a65234234390d7",
"first_name": "qqqq",
"last_name": "wwwe",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:07:18+0000",
"external_accounts": [],
"confirmed_at": "2016-01-22T09:02:43+0000",
"username": "qwe",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
I've been experiencing also that kind of problem, plus I've noticed that the images won't show up from the ArrowDB user interface (not sure if related).
The API returns only an empty object when you query the model:
photo: {}
I've been creating a ticket for the ArrowDB user interface https://jira.appcelerator.org/browse/API-1277.
sachinmw did you create a ticket for the initial problem yet?
A workaround could be to use the photo_id and run another separate query to retrieve the photo model but this is not good for network optimisation purposes.
EDIT
Ok after dealing with Appcelerator directly about having an empty photo: {} Object return the answer is pretty simple:
Whenever you use the query() function like Cloud.Objects.query() from ti.cloud on any ArrowDB object, there is a parameter called response_json_depth which is set to 1 by default and will only return one level of the JSON Object returned by the API.
Without touching that parameter I was seeing:
{
"Vehicle": [
{
"name": "foo",
"photo: {}
}
]
}
By setting response_json_depth to 3 I managed to have:
{
"Vehicle": [
{
"name": "foo",
"photo: {
"urls": {
"original": "http://bar.com"
}
}
}
]
}
Hope that will help someone. The also applies for the Cloud.Objects.show() method for any ArrowDB object.

Resources