Google event attendees list not updating on Outlook calendar event - google-calendar-api

I am writing a calendar integration and using the Google Calendar api and Outlook Graph api to sync calendar events. I am receiving webhooks as changes are made to events, so it is important that events are identical across calendar providers.
When I update the event attendees on a Google event however, an event update is not sent to Outlook attendees. The result is that Outlook attendees do not have an accurate attendee list.
If I change the Title/Description/Time, Google sends an event update and the Google and Outlook events get synced (the Outlook event is updated with the correct attendee list).
I have tried updating fields the user doesn't see (ex: sequence, extended properties) in hopes that the change would trigger an event update from Google but that doesn't seem to work.
Has anyone found a way to trigger a Google event update when attendees are added or removed?
UPDATE:
For Outlook users, I create a subscription (using the graph SDK) to each user’s calendar:
var graphClient = await MicrosoftAuthenticationProvider.GetGraphClient(CALENDAR_CLIENT_ID, CALENDAR_CLIENT_SECRET, CALENDAR_REDIRECT_URI, CALENDAR_ACCESS_SCOPES, RefreshToken).ConfigureAwait(false);
var tmpSubscription = new Subscription
{
ChangeType = WEBHOOK_SUBSCRIPTION_CHANGETYPE,
NotificationUrl = WEBHOOK_NOTIFICATION_ENDPOINT,
Resource = WEBHOOK_EVENT_RESOURCE_NAME,
ExpirationDateTime = maxSubscriptionLength,
ClientState = clientState
};
var subscription = await graphClient.Subscriptions
.Request()
.AddAsync(tmpSubscription)
.ConfigureAwait(false);
When an Outlook event is updated, my webhook notification endpoint receives a notification from Outlook. This happens successfully when I edit the summary, description, start or end of an event in Google. It does not happen when I add or remove attendees.
To replicate: create an event in Google that has an attendee that uses Outlook. You will see the event in Outlook. Add another attendee to the Google event. Google does not send Outlook an update email (the way it does if the title/time/description changes). The Google and Outlook events attendees are now different.

I found a work-around:
If I know the attendees have changed, I am changing the description of the event and sending a silent patch request to Google:
var tmpEvent = new Google.Apis.Calendar.v3.Data.Event
{
Description = Event.Description + "---attendees updated---",
};
//don't send the notification to anyone
//all attendees will get the notification when we resave the event with the original description
var patchRequest = service.Events.Patch(tmpEvent, GOOGLE_PRIMARY_CALENDARID, ExternalID);
patchRequest.SendUpdates = EventsResource.PatchRequest.SendUpdatesEnum.None;
await patchRequest.ExecuteAsync().ConfigureAwait(false);
For the patch, setting SendUpdates to None means attendees won’t receive a notification about the change, so all calendar events will be updated silently.
Finally, I save the entire event (with the proper description and attendees) and send the updates to all of the attendees:
var tmpEvent = new Google.Apis.Calendar.v3.Data.Event
{
Id = ExternalID == null ? Convert.ToString(Event.ID) : ExternalID,
Start = new EventDateTime
{
DateTime = Event.StartDate,
TimeZone = GetGoogleTimeZoneFromSystemTimeZone(timeZoneInfo.Id)
},
End = new EventDateTime
{
DateTime = Event.EndDate,
TimeZone = GetGoogleTimeZoneFromSystemTimeZone(timeZoneInfo.Id)
},
Summary = Event.Title,
Description = Event.Description,
Attendees = attendees.Select(a => new EventAttendee
{
Email = a.Value,
ResponseStatus = "accepted"
}).ToList(),
GuestsCanInviteOthers = false,
Location = Event.Location
};
var updateRequest = service.Events.Update(tmpEvent, GOOGLE_PRIMARY_CALENDARID, ExternalID);
updateRequest.SendUpdates = EventsResource.UpdateRequest.SendUpdatesEnum.All;
savedEvent = await updateRequest.ExecuteAsync().ConfigureAwait(false);
This isn't ideal because it requires two calls to Google's API just to properly save the attendees, but on the plus side, attendees are only notified of the change once.

Related

User-Id for Push-Notification on Actions for Google

I try to make a push notification for my google assistant app.
I used the sendNotification Code form the google developer site: https://developers.google.com/actions/assistant/updates/notifications
I am coding Java.
Everything is working, expect getting the correct user id.
When I hardcode my user it works, but how do I get the user id in the code?
I tried following code:
Argument arg_userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
String userId = request.getUser().getUserId();
--> I get "java.lang.reflect.InvocationTargetException"
String userId = arg_userId.getRawText();
--> same Exception
There are two problems with the approach you're taking to get the notification ID:
The ID attached to the user object is deprecated and probably unavailable.
This wasn't the ID you wanted anyway.
In the response where the user finalizes the notification, that response includes an ID which you should get and store. Since you're using Java, the code might look something like this:
ResponseBuilder responseBuilder = getResponseBuilder(request);
Argument permission = request.getArgument(ConstantsKt.ARG_PERMISSION);
if (permission != null) {
Argument userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
// code to save intent and userID in your db
responseBuilder.add("Ok, I'll start alerting you.").endConversation();
} else {
responseBuilder.add("Ok, I won't alert you.");
}
return responseBuilder.build();

GCalendar API - Exclude Events By ID?

I'm particularly trying to write this in C#, but has anyone managed to create a LIST request for events that OMIT events by a list of IDs? The idea here is to omit Google Calendar events that I've already pulled before in my previous requests (this would be stored in my application data) so that the events are always new. Here's my current list request code below:
// Create Google Calendar API service.
var service = new v3GCal.CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
// Define parameters of request.
v3GCal.EventsResource.ListRequest request = service.Events.List("manager#affirmmedicalweightloss.com");
request.TimeMin = today;
request.TimeMax = tomorrow;
request.ShowDeleted = false;
request.SingleEvents = true;
request.Q = "";
request.MaxResults = 10;
request.OrderBy = v3GCal.EventsResource.ListRequest.OrderByEnum.StartTime;
I'm not too hopeful - I've been digging around trying to find something with this feature, but with no luck. I would ideally include in the request something like:
"id NOT IN " + collection of existing id strings
But I don't see documentation on this anywhere.
Has anyone pulled this off, or considered filing a feature request for it? I thought of filing one, but given the issue tracker that I found at issuetracker.google.com, I'm not too hopeful this would get implemented anytime soon...
If your issue is regarding recurring event, you can try to use Events: instances that returns instances of the specified recurring event. Doing so excludes the recurring events, but includes all expanded instances. If not, you can file a bug here.

meteor-shopify User Creation/ Login after Auth callback

Assuming I want to create users upon authorizing the app, how would I grab their email during the onAuth callback...? Looks like the callback assumes the user is already logged in. Am I thinking about it correctly?
I noticed when installing the Fishbowl Prizes app, after auth I can click on the accounts tab and see that all my account info is pre-populated from my shopify store account (name, email, address, etc).
I'm not sure if I should go by the title or the content of the post in terms of answering your question, so I'll provide a very simple example of how to get the info from the API and do something with it here.
I have provided a more in depth answer related specifically to grabbing the details from the API for user account creation here: https://github.com/froatsnook/meteor-shopify/issues/15#issuecomment-177413630
Looks like the callback assumes the user is already logged in.
The userId param is undefined if there is no user. If your onAuth operations don't need to do anything with the user, you can just leave it out of the params. In your case you'll just want to handle it conditionally using an if/else block:
if(!userId){
// do stuff
} else {
// do other stuff
}
On to the example of grabbing those details from the API:
All the prepopulated information you are seeing is available from the Shopify API in the shop object. You already have the access token when onAuth callbacks are fired, so you can just grab it from the API immediately after you have inserted the shop's Keyset.
For the sake of simplicity, in this example we'll assume the user already exists and is logged in. In your server-side onAuth callback (after you have inserted the keyset) you can do something like this to add those fields to the user's profile object:
Shopify.onAuth(function(access_token, authConfig, userId) {
var shopUUID = uuid.new(); // Not secure to name keyset same as the shop!
Shopify.addKeyset(shopUUID, {
access_token: access_token
});
var api = new Shopify.API({
shop: authConfig.shop,
keyset: shopUUID
});
// get the Shop object from the API
var shopObj = api.getShop();
var userInfo = {
'profile.name': shopObj.shop_owner,
'profile.email': shopObj.email,
'profile.phone': shopObj.phone,
'profile.shopName': shopObj.name
};
Meteor.users.update({_id: userId}, {$set: userInfo})
});
Then you can use them in templates like this:
{{currentUser.profile.name}} or {{currentUser.profile.email}}
Or in functions like so:
var realName = Meteor.user().profile.name
or
var userEmail = Meteor.user().profile.email etc
For a more about using this data for user creation, see my explanation here:
https://github.com/froatsnook/meteor-shopify/issues/15#issuecomment-177413630

Firebase user counter

I'm trying to display the amount of users that are currently viewing my page using firebase and shopify's API. Haven't been able to find any documentation.
You could implement a presence system - see this Firebase blog post.
When a user logs in,
Authenticate the user
Set the onDisconnect listener to remove the presence object (#3) when the user disconnects.
Set the user's presence ref to true
Example (from blog post)
var amOnline = new Firebase('https://<demo>.firebaseio.com/.info/connected');
var userRef = new Firebase('https://<demo>.firebaseio.com/presence/' + userid);
amOnline.on('value', function(snapshot) {
if (snapshot.val()) {
userRef.onDisconnect().remove();
userRef.set(true);
}
});

MailChimp.Net User is not subscribed

I'm trying to call MailChimp Subscribe with MailChimp.Net NuGet package to add user to list in MailChimp.
The request is performed with success as far as I can see from MailChimp dashboard but the user is not subscribed in the list.
Did anyone faced such issue?
var myMergeVars = new MergeVar();
myMergeVars.Add("FNAME", "Testy");
myMergeVars.Add("LNAME", "Testerson");
var mc = new MailChimpManager("MYKEY");
// Create the email parameter
var email = new EmailParameter()
{
Email = "test.spektor#gmail.com"
};
EmailParameter results = mc.Subscribe("LISTID", email);
The request should be made with doubleOptIn: false option, otherwise user will receive an email with confirmation on his email box.
var result = mc.Subscribe(listId, emailParameter, myMergeVars, doubleOptIn: false, updateExisting: true);

Resources