internal static bool Equals(Event googleException, Outlook.Exception outlookException) { bool googleExceptionDeleted = googleException.Status == "cancelled"; bool exceptionEventScheduleEqual; if (outlookException.Deleted) { return (googleException.OriginalStartTime.DateTime.Value.Date == outlookException.OriginalDate && googleExceptionDeleted); } else { exceptionEventScheduleEqual = outlookException.AppointmentItem.AllDayEvent ? ( googleException.Start.Date == outlookException.AppointmentItem.Start.ToString("yyyy-MM-dd") && googleException.End.Date == outlookException.AppointmentItem.End.ToString("yyyy-MM-dd") ) : ( googleException.Start.DateTime.Value == outlookException.AppointmentItem.Start && googleException.End.DateTime.Value == outlookException.AppointmentItem.End ); return (googleException.OriginalStartTime.DateTime == outlookException.OriginalDate && !googleExceptionDeleted && exceptionEventScheduleEqual); } }
private static Boolean exceptionIsDeleted(Microsoft.Office.Interop.Outlook.Exception oExcp) { if (oExcp.Deleted) { return(true); } AppointmentItem ai = null; try { ai = oExcp.AppointmentItem; return(false); } catch (System.Exception ex) { OGCSexception.Analyse(ex); if (ex.Message == "You changed one of the recurrences of this item, and this instance no longer exists. Close any open items and try again.") { log.Warn("This Outlook recurrence instance has become inaccessible, probably due to caching"); return(true); } else { log.Warn("Error when determining if Outlook recurrence is deleted or not.\r\n" + ex.Message); return(true); } } finally { ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai); } }
internal RecurrenceException(Outlook.Exception outlookException, EventRecurrence parentRecurrence = null) { this._parentRecurrence = parentRecurrence != null ? parentRecurrence : new EventRecurrence(outlookException.Parent as Outlook.RecurrencePattern); this.OriginalDate = outlookException.OriginalDate; this.Deleted = outlookException.Deleted; if (!this.Deleted) { this.ModifiedEvent = new CalendarEvent(outlookException.AppointmentItem); } }
internal static bool Contains(IEnumerable <Event> googleExceptions, Outlook.Exception outlookException) { foreach (var googleException in googleExceptions) { if (Equals(googleException, outlookException)) { return(true); } } return(false); }
private static void getOutlookInstance(RecurrencePattern oPattern, DateTime instanceDate, ref AppointmentItem ai) { //First check if this is not yet an exception try { ai = oPattern.GetOccurrence(instanceDate); } catch { } if (ai == null) { //The Outlook API is rubbish as the date argument is how it exists NOW (not OriginalDate). //If this has changed >1 in Google then there's no way of knowing what it might be! Exceptions oExcps = null; try { oExcps = oPattern.Exceptions; for (int e = 1; e <= oExcps.Count; e++) { Microsoft.Office.Interop.Outlook.Exception oExcp = null; try { oExcp = oExcps[e]; if (oExcp.OriginalDate.Date == instanceDate.Date) { try { log.Debug("Found Outlook exception for " + instanceDate); if (exceptionIsDeleted(oExcp)) { log.Debug("This exception is deleted."); break; } else { ai = oExcp.AppointmentItem; break; } } catch (System.Exception ex) { MainForm.Instance.Logboxout(ex.Message); MainForm.Instance.Logboxout("If this keeps happening, please restart OGCS."); break; } finally { OutlookCalendar.ReleaseObject(oExcp); } } } finally { oExcp = (Microsoft.Office.Interop.Outlook.Exception)OutlookCalendar.ReleaseObject(oExcp); } } } finally { oExcps = (Exceptions)OutlookCalendar.ReleaseObject(oExcps); } if (ai == null) { log.Warn("Unable to find Outlook exception for " + instanceDate); } } }
public Event GetGoogleInstance(Microsoft.Office.Interop.Outlook.Exception oExcp, String gRecurringEventID, String oEntryID) { Boolean oIsDeleted = exceptionIsDeleted(oExcp); log.Debug("Finding Google instance for " + (oIsDeleted ? "deleted " : "") + "Outlook exception:-"); log.Debug(" Original date: " + oExcp.OriginalDate.ToString("dd/MM/yyyy")); if (!oIsDeleted) { log.Debug(" Current date: " + oExcp.AppointmentItem.Start.ToString("dd/MM/yyyy")); } foreach (Event gExcp in googleExceptions) { if (gExcp.RecurringEventId == gRecurringEventID) { if ((!oIsDeleted && GoogleCalendar.GoogleTimeFrom(oExcp.OriginalDate) == (gExcp.OriginalStartTime.Date ?? gExcp.OriginalStartTime.DateTime) ) || (oIsDeleted && GoogleCalendar.GoogleTimeFrom(oExcp.OriginalDate) == (gExcp.OriginalStartTime.Date ?? GoogleCalendar.GoogleTimeFrom(DateTime.Parse(gExcp.OriginalStartTime.DateTime).Date)) )) { return(gExcp); } } } log.Debug("Google exception event is not cached. Retrieving all recurring instances..."); List <Event> gInstances = GoogleCalendar.Instance.GetCalendarEntriesInRecurrence(gRecurringEventID); //Add any new exceptions to local cache googleExceptions = googleExceptions.Union(gInstances.Where(ev => !String.IsNullOrEmpty(ev.RecurringEventId))).ToList(); foreach (Event gInst in gInstances) { if (gInst.RecurringEventId == gRecurringEventID) { if (((!oIsDeleted || (oIsDeleted && !oExcp.Deleted)) && /* Weirdness when exception is cancelled by organiser but not yet deleted/accepted by recipient */ GoogleCalendar.GoogleTimeFrom(oExcp.OriginalDate) == GoogleCalendar.GoogleTimeFrom(DateTime.Parse(gInst.OriginalStartTime.Date ?? gInst.OriginalStartTime.DateTime)) ) || (oIsDeleted && GoogleCalendar.GoogleTimeFrom(oExcp.OriginalDate) == GoogleCalendar.GoogleTimeFrom(DateTime.Parse(gInst.OriginalStartTime.Date ?? gInst.OriginalStartTime.DateTime).Date) )) { return(gInst); } } } return(null); }
private static Boolean exceptionIsDeleted(Microsoft.Office.Interop.Outlook.Exception oExcp) { if (oExcp.Deleted) { return(true); } try { AppointmentItem ai = oExcp.AppointmentItem; return(false); } catch (System.Exception ex) { if (ex.Message == "You changed one of the recurrences of this item, and this instance no longer exists. Close any open items and try again.") { //log.Debug("This Outlook recurrence instance has been deleted, but the API is reporting it incorrectly due to caching"); return(true); } else { log.Warn("Error when determining if Outlook recurrence is deleted or not.\r\n" + ex.Message); return(true); } } }
public static void UpdateGoogleExceptions(AppointmentItem ai, Event ev, Boolean dirtyCache) { if (ai.IsRecurring) { RecurrencePattern rp = null; Exceptions excps = null; try { rp = ai.GetRecurrencePattern(); excps = rp.Exceptions; if (excps.Count > 0) { log.Debug(OutlookOgcs.Calendar.GetEventSummary(ai)); log.Debug("This is a recurring appointment with " + excps.Count + " exceptions that will now be iteratively compared."); for (int e = 1; e <= excps.Count; e++) { Microsoft.Office.Interop.Outlook.Exception oExcp = null; AppointmentItem aiExcp = null; try { oExcp = excps[e]; int excp_itemModified = 0; //Check the exception falls in the date range being synced Boolean oIsDeleted = exceptionIsDeleted(oExcp); String logDeleted = oIsDeleted ? " deleted and" : ""; DateTime oExcp_currDate; if (oIsDeleted) { oExcp_currDate = oExcp.OriginalDate; } else { aiExcp = oExcp.AppointmentItem; oExcp_currDate = aiExcp.Start; aiExcp = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(aiExcp); } if (oExcp_currDate < Settings.Instance.SyncStart.Date || oExcp_currDate > Settings.Instance.SyncEnd.Date) { log.Fine("Exception is" + logDeleted + " outside date range being synced: " + oExcp_currDate.Date.ToString("dd/MM/yyyy")); continue; } Event gExcp = Recurrence.Instance.getGoogleInstance(ref oExcp, ev.RecurringEventId ?? ev.Id, OutlookOgcs.Calendar.Instance.IOutlook.GetGlobalApptID(ai), dirtyCache); if (gExcp != null) { log.Debug("Matching Google Event recurrence found."); if (gExcp.Status == "cancelled") { log.Debug("It is deleted in Google, so cannot compare items."); if (!oIsDeleted) { log.Warn("Outlook is NOT deleted though - a mismatch has occurred somehow!"); String syncDirectionTip = (Settings.Instance.SyncDirection == Sync.Direction.Bidirectional) ? "<br/><i>Ensure you <b>first</b> set OGCS to one-way sync O->G.</i>" : ""; Forms.Main.Instance.Console.Update(OutlookOgcs.Calendar.GetEventSummary(ai) + "<br/>" + "The occurrence on " + oExcp.OriginalDate.ToShortDateString() + " does not exist in Google, but does in Outlook.<br/>" + "This can happen if, for example, you declined the occurrence (which is synced to Google) and proposed a new time that is subsequently accepted by the organiser.<br/>" + "<u>Suggested fix</u>: delete the entire series in Google and let OGCS recreate it." + syncDirectionTip, Console.Markup.warning); } continue; } else if (oIsDeleted && gExcp.Status != "cancelled") { gExcp.Status = "cancelled"; log.Debug("Exception deleted."); excp_itemModified++; } else { try { aiExcp = oExcp.AppointmentItem; //Force a compare of the exception if both G and O have been modified in last 24 hours TimeSpan modifiedDiff = (TimeSpan)(gExcp.Updated - aiExcp.LastModificationTime); log.Fine("Difference in days between G and O exception: " + modifiedDiff); Boolean forceCompare = modifiedDiff < TimeSpan.FromDays(1); GoogleOgcs.Calendar.Instance.UpdateCalendarEntry(aiExcp, gExcp, ref excp_itemModified, forceCompare); } catch (System.Exception ex) { log.Error(ex.Message); log.Error(ex.StackTrace); throw; } } if (excp_itemModified > 0) { try { GoogleOgcs.Calendar.Instance.UpdateCalendarEntry_save(ref gExcp); } catch (System.Exception ex) { Forms.Main.Instance.Console.UpdateWithError("Updated event exception failed to save.", ex); OGCSexception.Analyse(ex, true); if (OgcsMessageBox.Show("Updated Google event exception failed to save. Continue with synchronisation?", "Sync item failed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { continue; } else { throw new UserCancelledSyncException("User chose not to continue sync."); } } } } else { log.Debug("No matching Google Event recurrence found."); if (oIsDeleted) { log.Debug("The Outlook appointment is deleted, so not a problem."); } } } finally { aiExcp = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(aiExcp); oExcp = (Microsoft.Office.Interop.Outlook.Exception)OutlookOgcs.Calendar.ReleaseObject(oExcp); } } } } finally { excps = (Exceptions)OutlookOgcs.Calendar.ReleaseObject(excps); rp = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(rp); } } }
public static void CreateGoogleExceptions(AppointmentItem ai, String recurringEventId) { if (!ai.IsRecurring) { return; } log.Debug("Creating Google recurrence exceptions."); List <Event> gRecurrences = GoogleOgcs.Calendar.Instance.GetCalendarEntriesInRecurrence(recurringEventId); if (gRecurrences != null) { RecurrencePattern rp = null; Exceptions excps = null; try { rp = ai.GetRecurrencePattern(); excps = rp.Exceptions; for (int e = 1; e <= excps.Count; e++) { Microsoft.Office.Interop.Outlook.Exception oExcp = null; try { oExcp = excps[e]; for (int g = 0; g < gRecurrences.Count; g++) { Event ev = gRecurrences[g]; DateTime gDate = ev.OriginalStartTime.DateTime ?? DateTime.Parse(ev.OriginalStartTime.Date); Boolean isDeleted = exceptionIsDeleted(oExcp); if (isDeleted && !ai.AllDayEvent) //Deleted items get truncated?! { gDate = gDate.Date; } if (oExcp.OriginalDate == gDate) { if (isDeleted) { Forms.Main.Instance.Console.Update(GoogleOgcs.Calendar.GetEventSummary(ev), Console.Markup.calendar); Forms.Main.Instance.Console.Update("Recurrence deleted."); ev.Status = "cancelled"; GoogleOgcs.Calendar.Instance.UpdateCalendarEntry_save(ref ev); } else { int exceptionItemsModified = 0; Event modifiedEv = GoogleOgcs.Calendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, ev, ref exceptionItemsModified, forceCompare: true); if (exceptionItemsModified > 0) { GoogleOgcs.Calendar.Instance.UpdateCalendarEntry_save(ref modifiedEv); } } break; } } } finally { oExcp = (Microsoft.Office.Interop.Outlook.Exception)OutlookOgcs.Calendar.ReleaseObject(oExcp); } } } finally { excps = (Exceptions)OutlookOgcs.Calendar.ReleaseObject(excps); rp = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(rp); } } }
private Event getGoogleInstance(ref Microsoft.Office.Interop.Outlook.Exception oExcp, String gRecurringEventID, String oEntryID, Boolean dirtyCache) { Boolean oIsDeleted = exceptionIsDeleted(oExcp); log.Debug("Finding Google instance for " + (oIsDeleted ? "deleted " : "") + "Outlook exception:-"); log.Debug(" Original date: " + oExcp.OriginalDate.ToString("dd/MM/yyyy")); if (!oIsDeleted) { AppointmentItem ai = null; try { ai = oExcp.AppointmentItem; log.Debug(" Current date: " + ai.Start.ToString("dd/MM/yyyy")); } finally { ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai); } } if (dirtyCache) { log.Debug("Google exception cache not being used. Retrieving all recurring instances afresh..."); //Remove dirty items googleExceptions.RemoveAll(ev => ev.RecurringEventId == gRecurringEventID); } else { foreach (Event gExcp in googleExceptions) { if (gExcp.RecurringEventId == gRecurringEventID) { if ((!oIsDeleted && oExcp.OriginalDate == (gExcp.OriginalStartTime.DateTime ?? DateTime.Parse(gExcp.OriginalStartTime.Date)) ) || (oIsDeleted && oExcp.OriginalDate == (gExcp.OriginalStartTime.DateTime ?? DateTime.Parse(gExcp.OriginalStartTime.Date)).Date )) { return(gExcp); } } } log.Debug("Google exception event is not cached. Retrieving all recurring instances..."); } List <Event> gInstances = GoogleOgcs.Calendar.Instance.GetCalendarEntriesInRecurrence(gRecurringEventID); //Add any new exceptions to local cache googleExceptions = googleExceptions.Union(gInstances.Where(ev => !String.IsNullOrEmpty(ev.RecurringEventId))).ToList(); foreach (Event gInst in gInstances) { if (gInst.RecurringEventId == gRecurringEventID) { if (((!oIsDeleted || (oIsDeleted && !oExcp.Deleted)) && /* Weirdness when exception is cancelled by organiser but not yet deleted/accepted by recipient */ oExcp.OriginalDate == (gInst.OriginalStartTime.DateTime ?? DateTime.Parse(gInst.OriginalStartTime.Date)) ) || (oIsDeleted && oExcp.OriginalDate == (gInst.OriginalStartTime.DateTime ?? DateTime.Parse(gInst.OriginalStartTime.Date)).Date )) { return(gInst); } } } return(null); }
public static void UpdateGoogleExceptions(AppointmentItem ai, Event ev, Boolean dirtyCache) { if (ai.IsRecurring) { RecurrencePattern rp = null; Exceptions excps = null; try { rp = ai.GetRecurrencePattern(); excps = rp.Exceptions; if (excps.Count > 0) { log.Debug(OutlookCalendar.GetEventSummary(ai)); log.Debug("This is a recurring appointment with " + excps.Count + " exceptions that will now be iteratively compared."); for (int e = 1; e <= excps.Count; e++) { Microsoft.Office.Interop.Outlook.Exception oExcp = null; AppointmentItem aiExcp = null; try { oExcp = excps[e]; int excp_itemModified = 0; //Check the exception falls in the date range being synced Boolean oIsDeleted = exceptionIsDeleted(oExcp); String logDeleted = oIsDeleted ? " deleted and" : ""; DateTime oExcp_currDate; if (oIsDeleted) { oExcp_currDate = oExcp.OriginalDate; } else { aiExcp = oExcp.AppointmentItem; oExcp_currDate = aiExcp.Start; aiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(aiExcp); } if (oExcp_currDate < Settings.Instance.SyncStart.Date || oExcp_currDate > Settings.Instance.SyncEnd.Date) { log.Fine("Exception is" + logDeleted + " outside date range being synced: " + oExcp_currDate.Date.ToString("dd/MM/yyyy")); continue; } Event gExcp = Recurrence.Instance.getGoogleInstance(ref oExcp, ev.RecurringEventId ?? ev.Id, OutlookCalendar.Instance.IOutlook.GetGlobalApptID(ai), dirtyCache); if (gExcp != null) { log.Debug("Matching Google Event recurrence found."); if (gExcp.Status == "cancelled") { log.Debug("It is deleted in Google, so cannot compare items."); if (!oIsDeleted) { log.Warn("Outlook is NOT deleted though - a mismatch has occurred somehow!"); } continue; } else if (oIsDeleted && gExcp.Status != "cancelled") { gExcp.Status = "cancelled"; log.Debug("Exception deleted."); excp_itemModified++; } else { try { aiExcp = oExcp.AppointmentItem; GoogleCalendar.Instance.UpdateCalendarEntry(aiExcp, gExcp, ref excp_itemModified); } catch (System.Exception ex) { log.Error(ex.Message); log.Error(ex.StackTrace); throw ex; } } if (excp_itemModified > 0) { try { GoogleCalendar.Instance.UpdateCalendarEntry_save(ref gExcp); } catch (System.Exception ex) { MainForm.Instance.Logboxout("WARNING: Updated event exception failed to save.\r\n" + ex.Message); log.Error(ex.StackTrace); if (MessageBox.Show("Updated Google event exception failed to save. Continue with synchronisation?", "Sync item failed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { continue; } else { throw new UserCancelledSyncException("User chose not to continue sync."); } } } } else { log.Debug("No matching Google Event recurrence found."); if (oIsDeleted) { log.Debug("The Outlook appointment is deleted, so not a problem."); } } } finally { aiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(aiExcp); oExcp = (Microsoft.Office.Interop.Outlook.Exception)OutlookCalendar.ReleaseObject(oExcp); } } } } finally { excps = (Exceptions)OutlookCalendar.ReleaseObject(excps); rp = (RecurrencePattern)OutlookCalendar.ReleaseObject(rp); } } }