I have code that is creating Google calendar entries (recurring events) using the Google calendar API. This is working fine. Now I am trying to add exceptions to certain instances. I've got it working for deleted instances (by using the EXDATE parameter) but I'm having trouble changing the date/time of an instance. I am following the instructions found here:
https://developers.google.com/google-apps/calendar/recurringevents
After I create the basic recurring event, I retrieve a list of all instances. For testing, I am pulling out the entire section of json that applies to the instance I want to change, for example:
{
"kind": "calendar#event",
"etag": "\"3032281375946000\"",
"id": "_69j3ge9iccp68or1c8p3ac1nccpm8p356gpj8pb66koj2c32c5h0_20180130T203000Z",
"status": "confirmed",
"htmlLink": "https://www.google.com/calendar/event?eid=XzY5ajNnZTlpY2NwNjhvcjFjOHAzYWMxbmNjcG04cDM1NmdwajhwYjY2a29qMmMzMmM1aDBfMjAxODAxMzBUMjAzMDAwWiBqbWNrYXk5MzUxQG0",
"created": "2018-01-16T20:08:56.000Z",
"updated": "2018-01-17T00:13:59.277Z",
"summary": "Recurring test with deletes and changes",
"description": "\n",
"location": "SEattle",
"creator": {
"email": "jmckay9351#gmail.com",
"displayName": "Jeffrey McKay",
"self": true
},
"organizer": {
"email": "jmckay9351#gmail.com",
"displayName": "Jeffrey McKay",
"self": true
},
"start": {
"dateTime": "2018-01-30T13:30:00-08:00"
},
"end": {
"dateTime": "2018-01-30T14:00:00-08:00"
},
"recurringEventId": "_69j3ge9iccp68or1c8p3ac1nccpm8p356gpj8pb66koj2c32c5h0",
"originalStartTime": {
"dateTime": "2018-01-30T12:30:00-08:00"
},
"iCalUID": "2f892c2dcab2507c3dde434ef5110bab",
"sequence": 0,
"reminders": {
"useDefault": false,
"overrides": [{
"method": "popup",
"minutes": 15
}]
}
}
Then I do a http PUT of this data to this URL:
https://www.googleapis.com/calendar/v3/calendars/jmckay9351#gmail.com/events/_69j3ge9iccp68or1c8p3ac1nccpm8p356gpj8pb66koj2c32c5h0_20180130T203000Z
What I get back is a http error 400, and the error message in the returned json is "Missing end time". I get the same response regardless of how much or little data I feed into the PUT. Any idea what I'm doing wrong here?
OK I've got this working now - I don't understand what was wrong with my libcurl PUT code, but I changed it to be a POST with a custom request of "PUT" and that seemed to get to data correctly uploaded.
Related
Non-engineer here. I'm working on a program (using Google Sheets) that will help people in my office analyze their calendars.
The Google Calendar Service has methods that allow me to retrieve event start and end times, guest lists, and much more. Unfortunately, I haven't figured out how to tell the difference between a "Reminder" and an "Out of the office" event. They both show up as all day events, but the former can be ignored and the latter causes that entire day to show up as "blocked" or "scheduled". I need to be able to tell them apart, but I'm not sure how.
Any suggestions?
MORE DETAIL:
I create a "Reminder" in Google Calendar by clicking just below the day, at the top. This gives me three choices: Event, Out of the office, and Appointment slots. When I am creating a Reminder for myself I first name it (i.e. "Doctor's appointment at 2:00"), then I usually change the color to red so it's extra visible.
If I am going to be Out of the office I choose that option. The option "Automatically decline new and existing meetings" is checked by default. I add a name like, "Dev Conference" and Save it. This causes the entire day to show in a light blue color, indicating that the entire day is blocked.
You can differentiate between a normal event and a "Out of Office" event because of the latter not having the transparency attribute included and it has the description attribute filled with the following value:
"This is an out-of-office event, which can only be edited in Google Calendar. Meetings during this time will be automatically declined."
You can test this by making a Events.list request and check the results, for example:
Normal event:
{
"kind": "calendar#event",
"etag": "\"3167876463844000\"",
"id": "1nqq8sg43po8itr8h0ebedfgbq",
"status": "confirmed",
"htmlLink": "https://www.google.com/calendar/event?eid=MW5xcThzZzQzcG84aXRyOGgwZWJlZGZnYnEgdGVzdGluYUBlZ3Mtc2J0MDExLmV1",
"created": "2020-03-11T14:50:31.000Z",
"updated": "2020-03-11T14:50:31.922Z",
"summary": "test",
"creator": {
"email": "testina#egs-sbt011.eu",
"self": true
},
"organizer": {
"email": "testina#egs-sbt011.eu",
"self": true
},
"start": {
"date": "2020-03-16"
},
"end": {
"date": "2020-03-17"
},
"transparency": "transparent",
"iCalUID": "1nqq8sg43po8itr8h0ebedfgbq#google.com",
"sequence": 0,
"reminders": {
"useDefault": false
}
}
Out of Office event:
{
"kind": "calendar#event",
"etag": "\"3167876472386000\"",
"id": "29g3lpl9hojb92bevvkvdccq6p",
"status": "confirmed",
"htmlLink": "https://www.google.com/calendar/event?eid=MjlnM2xwbDlob2piOTJiZXZ2a3ZkY2NxNnAgdGVzdGluYUBlZ3Mtc2J0MDExLmV1",
"created": "2020-03-11T14:50:36.000Z",
"updated": "2020-03-11T14:50:36.289Z",
"summary": "test OOO",
"description": "This is an out-of-office event, which can only be edited in Google Calendar. Meetings during this time will be automatically declined.",
"creator": {
"email": "testina#egs-sbt011.eu",
"self": true
},
"organizer": {
"email": "testina#egs-sbt011.eu",
"self": true
},
"start": {
"dateTime": "2020-03-17T00:00:00+01:00"
},
"end": {
"dateTime": "2020-03-18T00:00:00+01:00"
},
"visibility": "public",
"iCalUID": "29g3lpl9hojb92bevvkvdccq6p#google.com",
"sequence": 0,
"reminders": {
"useDefault": false
}
}
Regarding appointment slots, these are not supported by Google Calendar API, you can +1 this open feature request to implement this.
For a while after the feature was introduced, there was no way to filter them via API other than parsing the description. There is now an eventType key on events.
https://developers.google.com/calendar/api/v3/reference/events#eventType
Look for "eventType": "outOfOffice" events.
I'm trying to send new users / new customres of my WooCommerce store into the rental management app current-rms.com as new Organisations / new contacts. Since Current RMS does not have a native Zap, I am trying to use the generic Webhook zap that Zapier maintains.
Specifically, I'd like to see the sent JSON body in Zapier posts that I make during the setup and testing of the Zap after clicking "Make a Zap!". The Task History is not detailed enough nor does it show hits during test and setup, since it's not live yet.
My trigger is a WooCommerce New Customer. This is working with Zapier WooCommerce Plugin and webhooks OK.
My action is the generic Zapier "Webhooks" Zap. The label "instant" appears next to it in the list at /app/zaps and it is "off".
One version uses JSON PAYLOAD as the action.
Another version uses CUSTOM PAYLOAD as the action.
Wrap request in array is YES.
Unflatten is YES.
My API key and subdomain are in the app URL as query strings and working OK.
When I hit test I get:
We had trouble sending your test through.
The app returned "Invalid JSON - missing or invalid entry for 'member'". This usually happens when your Zap is missing a required field or a field value isn't in a recognized format.
We made a request to api.current-rms.com and received (400) Bad Request.
Official docs are at: https://api.current-rms.com/doc#members-members-post
Logging available at Current RMS side
Part of the authentication of Current RMS involves knowing the domain of the account you are trying to access, in my case its therockfactory due to it being an account for my company https://therockfactory.net/
https://api.current-rms.com/api/v1/members?apikey=APIKEYCENSORED&subdomain=therockfactory
which returns the following when I use the correct API key:
{"webhook_logs":[],"meta":{"total_row_count":0,"row_count":0,"page":1,"per_page":20}}
Maybe if I could see the actual hit that Zapier is posting to Current I could wrap my confused brain around it better? What me worry.
The hit should look somewhat similar to this example, but I've not been able to locate it so far... (in Zapier)
Headers
Content-Type: application/json
Body
{
"member": {
"name": "Chris Bralton",
"description": "Pictures and leaned back was strewn at one would rather more. People don't want of his own means of one hand! Unless it from our pioneer has he fallen tree but that ever stronger and a. Hid among us against the full of verdure through by my eyes.",
"active": true,
"bookable": false,
"location_type": 0,
"locale": "en-GB",
"membership_type": "Contact",
"lawful_basis_type_id": 10001,
"sale_tax_class_id": 1,
"purchase_tax_class_id": 1,
"tag_list": [
"[\"Red\", \"Blue\", \"Green\"]"
],
"custom_fields": {},
"membership": {},
"primary_address": {
"name": "Chris Branson",
"street": "16 The Triangle",
"postcode": "NG2 1AE",
"city": "Nottingham",
"county": "Nottinghamshire",
"country_id": "1",
"country_name": "United Kingdom",
"type_id": 3001,
"address_type_name": "Primary",
"created_at": "2015-06-29T10:00:00.000Z",
"updated_at": "2015-06-29T10:30:00.000Z"
},
"emails": [
{
"address": "abigail.parker#ggmail.co.uk",
"type_id": 4001,
"email_type_name": "Work",
"id": 1
}
],
"phones": [
{
"number": "+44 115 9793399",
"type_id": 6001,
"phone_type_name": "Work",
"id": 1
}
],
"links": [
{
"address": "www.facebook.com/profile.php?id=566828251",
"type_id": 5002,
"link_type_name": "Facebook",
"id": 1
}
],
"addresses": [
{
"name": "Chris Branson",
"street": "16 The Triangle",
"postcode": "NG2 1AE",
"city": "Nottingham",
"county": "Nottinghamshire",
"country_id": "1",
"country_name": "United Kingdom",
"type_id": 3002,
"address_type_name": "Billing",
"created_at": "2017-06-29T10:00:00.000Z",
"updated_at": "2017-06-29T10:30:00.000Z",
"id": 1
}
],
"service_stock_levels": [
{
"item_id": 10,
"store_id": 1,
"member_id": 1,
"asset_number": "Chris Bralton",
"serial_number": "",
"location": "",
"stock_type": 3,
"stock_category": 60,
"quantity_held": "1.0",
"quantity_allocated": "0.0",
"quantity_unavailable": "0.0",
"quantity_on_order": "0.0",
"starts_at": "",
"ends_at": "",
"icon": {
"iconable_id": 85,
"id": 1,
"image_file_name": "abigail.jpeg",
"url": "https://s3.amazonaws.com/current-rms-development/64a0ccd0-5fbd-012f-2201-60f847290680/icons/46/original/abigail.jpeg",
"thumb_url": "https://s3.amazonaws.com/current-rms-development/64a0ccd0-5fbd-012f-2201-60f847290680/icons/46/thumb/abigail.jpeg",
"created_at": "2015-06-29T10:00:00.000Z",
"updated_at": "2015-06-29T10:30:00.000Z",
"iconable_type": "StockLevel"
},
"custom_fields": {},
"id": 487,
"item_name": "Sound Engineer",
"store_name": "Nottingham",
"stock_type_name": "Service",
"stock_category_name": "Resource"
}
],
"day_cost": "",
"hour_cost": "",
"distance_cost": "",
"flat_rate_cost": "",
"icon": {
"image": ""
},
"child_members": [
{
"relatable_id": 317,
"relatable_type": "Member",
"related_id": 25,
"related_type": "Member"
}
],
"parent_members": [
{
"relatable_id": 317,
"relatable_type": "Member",
"related_id": 25,
"related_type": "Member"
}
]
}
}
UPDATE: After reading my chosen answer I was able to see what Zapier was sending:
[
{
"member[emails_attributes][0][address]": "test#test.co.nz",
"member[membership_type]": "Organisation",
"member[name]": "Testafari Testing"
}
]
You can send your webhook to a tool like this one to inspect the payloads that are being sent from anywhere on the internet: https://requestbin.com/
You can find more help in regards to using Webhooks by Zapier and other ideas on how you can troubleshoot issues stemming from its use: https://zapier.com/apps/webhook/help#inspect-the-requests
I'm trying to use some results exported in JSON of a script called "Mixed Content Scan" (it's a script in order to search on a website if there is some mixed HTTP/HTTPS content and if all your pages are ok in HTTPS).
I'm a beginner with JSON, I read and watched a lot of tutorials in order to understand how to structure JSON data but I'm stumbling on something.
Here is a sample of my data (first 3 lines) :
{"message":"Scanning https://mywebsite.com/","context":[],"level":250,"level_name":"NOTICE","channel":"MCS","datetime":{"date":"2018-10-05 23:48:50.268196","timezone_type":3,"timezone":"America/New_York"},"extra":[]}
{"message":"00000 - https://mywebsite.com/","context":[],"level":400,"level_name":"ERROR","channel":"MCS","datetime":{"date":"2018-10-05 23:48:50.760948","timezone_type":3,"timezone":"America/New_York"},"extra":[]}
{"message":"http://mywebsite.com/wp-content/uploads/2015/03/image.jpg","context":[],"level":300,"level_name":"WARNING","channel":"MCS","datetime":{"date":"2018-10-05 23:48:50.761082","timezone_type":3,"timezone":"America/New_York"},"extra":[]}
I know I need to wrap my data around some {} or [] (tried both), but I think I'm missing something, for example, every JSON data validator websites are telling me that I have an error between 2 lines when I add a "," when I try to have multiple results into it.
How can I upgrade this raw data in order for a JSON validator to validate it?
Thanks!
How's this
[{
"message": "Scanning https://mywebsite.com/",
"context": [],
"level": 250,
"level_name": "NOTICE",
"channel": "MCS",
"datetime": {
"date": "2018-10-05 23:48:50.268196",
"timezone_type": 3,
"timezone": "America/New_York"
},
"extra": []
}, {
"message": "00000 - https://mywebsite.com/",
"context": [],
"level": 400,
"level_name": "ERROR",
"channel": "MCS",
"datetime": {
"date": "2018-10-05 23:48:50.760948",
"timezone_type": 3,
"timezone": "America/New_York"
},
"extra": []
}, {
"message": "http://mywebsite.com/wp-content/uploads/2015/03/image.jpg",
"context": [],
"level": 300,
"level_name": "WARNING",
"channel": "MCS",
"datetime": {
"date": "2018-10-05 23:48:50.761082",
"timezone_type": 3,
"timezone": "America/New_York"
},
"extra": []
}]
Entries in an array need to be separated by commas.
Is there a way to create an event in Office calendar ( with the Graph API ) setting the iCalUId?
I have tested with the Graph Explorer tool (from the web site) inserting this event (POST /v1.0/me/events):
{
"subject": "My event",
"start": {
"dateTime": "2018-02-19T10:39:01.355Z",
"timeZone": "UTC"
},
"end": {
"dateTime": "2018-02-26T10:39:01.355Z",
"timeZone": "UTC"
},
"iCalUid": "040000008200E00074C5B7101A82E00800000000F44A7CFB6DA9D301000000000000000100000004A4B349D0E9F1744BBA2F67E4D522179"
}
The system creates my event correctly, but it changes the UID with another ( auto-created, I suppose).
This is a part of the JSON response:
{
"iCalUId": "040000008200E00074C5B7101A82E008000000005BBB3A076EA9D301000000000000000010000000389E2C56CB68B74E807FE83A5CC60AAB",
"subject": "My event",
"start": {
"dateTime": "2018-02-19T10:39:01.3550000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2018-02-26T10:39:01.3550000",
"timeZone": "UTC"
}
}
From the documentation only the ID field is read-only, so I am wondering if there is a way to set the iCalUId.
iCalUid is a read-only calculated value so it cannot be manually set. You can see the details on how it is calculated in the PidLidGlobalObjectId Property documentation.
Here's an undocumented way (as far as I can tell, anyway) to modify the iCalUId. I've only tested with creation and not with updating, but I think it should work. Note that I don't know what other side-effects this will have, but for my use-case, it has worked so far.
The iCalUId gets its value from the PidLidGlobalObjectId property. You can modify this value using SingleValueExtendedProperties. For instances of recurring events, the iCalUId uses the PidLidCleanGlobalObjectId which oddly enough doesn't calculate its value from the normal PidLidGlobalObjectId, so you'll want to modify that too.
{
"subject": "Subject",
"start": ...,
"end": ...,
// the rest of your event request
"singleValueExtendedProperties": [
// PidLidGlobalObjectId
{
"id": "Binary {6ED8DA90-450B-101B-98DA-00AA003F1305} Id 0x003",
"value": "" // base-64 encoded PidLidGlobalObjectId, it should start with BAAAA...
},
// PidLidCleanGlobalObjectId
{
"id": "Binary {6ED8DA90-450B-101B-98DA-00AA003F1305} Id 0x023",
"value": "" // base-64 encoded PidLidCleanGlobalObjectId, it should start with BAAAA...
}
]
}
Be sure to check out the format
of the PidLidGlobalObjectId and PidLidCleanGlobalObjectId, otherwise you might get "Data is corrupt" or some other such errors when trying to create or update events.
Since recently the JSON API always seems to add a day when returning the timespan for full-day events.
Display in Google Calendar Web app:
Yet what the JSON API returns is this:
{
"kind": "calendar#event",
"etag": "\"2896554426340000\"",
"id": "...",
"status": "confirmed",
"htmlLink": "https://calendar.google.com/calendar/event?eid=...",
[...]
"summary": "...",
[...]
"start": {
"date": "2016-02-01"
},
"end": {
"date": "2016-02-02"
},
[...]
"iCalUID": "...#google.com",
"sequence": 0
}
In the Calendar API the start is inclusive and the end is exclusive. That's why the end will be the next day (which is excluded).