private Event outlookToGoogleObject(Appointment appt) { AppointmentItem outAppt = outlookAppointments.Find(o => o.EntryID == appt.iCalUID); if (outAppt == null) //Deleted event { return(null); } Event googleAppointment = new Event(); googleAppointment.Id = appt.googleId; googleAppointment.ICalUID = appt.iCalUID; googleAppointment.Summary = outAppt.Subject; googleAppointment.Start = new EventDateTime(); googleAppointment.Start.DateTime = outAppt.Start; googleAppointment.Start.TimeZone = outAppt.StartTimeZone.Name; googleAppointment.End = new EventDateTime(); googleAppointment.End.DateTime = outAppt.End; googleAppointment.End.TimeZone = outAppt.EndTimeZone.Name; googleAppointment.Description = outAppt.Body; googleAppointment.Location = outAppt.Location; if (outAppt.IsRecurring) { googleAppointment.Recurrence = new String[] { OutlookRecurrenceToGoogleRecurrence.convert(outAppt.GetRecurrencePattern()) }; } return(googleAppointment); }
private void processOutlookExceptions(ref AppointmentItem ai, Event ev, Boolean forceCompare) { if (!HasExceptions(ev, checkLocalCacheOnly: true)) { return; } RecurrencePattern oPattern = null; try { oPattern = ai.GetRecurrencePattern(); foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id)) { DateTime oExcpDate = gExcp.OriginalStartTime.DateTime ?? DateTime.Parse(gExcp.OriginalStartTime.Date); log.Fine("Found Google exception for " + oExcpDate.ToString()); AppointmentItem newAiExcp = null; try { getOutlookInstance(oPattern, oExcpDate, ref newAiExcp); if (newAiExcp == null) { continue; } if (gExcp.Status == "cancelled") { Forms.Main.Instance.Console.Update(OutlookOgcs.Calendar.GetEventSummary(newAiExcp) + "<br/>Deleted.", Console.Markup.calendar); newAiExcp.Delete(); } else if (Settings.Instance.ExcludeDeclinedInvites && gExcp.Attendees != null && gExcp.Attendees.Count(a => a.Self == true && a.ResponseStatus == "declined") == 1) { Forms.Main.Instance.Console.Update(OutlookOgcs.Calendar.GetEventSummary(newAiExcp) + "<br/>Declined.", Console.Markup.calendar); newAiExcp.Delete(); } else { int itemModified = 0; OutlookOgcs.Calendar.Instance.UpdateCalendarEntry(ref newAiExcp, gExcp, ref itemModified, forceCompare); if (itemModified > 0) { try { newAiExcp.Save(); } catch (System.Exception ex) { OGCSexception.Analyse(ex); if (ex.Message == "Cannot save this item.") { Forms.Main.Instance.Console.Update("Uh oh! Outlook wasn't able to save this recurrence exception! " + "You may have two occurences on the same day, which it doesn't allow.", Console.Markup.warning); } } } } } finally { newAiExcp = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(newAiExcp); } } } finally { oPattern = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(oPattern); } }
public static void CreateGoogleExceptions(AppointmentItem ai, String recurringEventId) { if (!ai.IsRecurring) return; log.Debug("Creating Google recurrence exceptions."); List<Event> gRecurrences = GoogleCalendar.Instance.GetCalendarEntriesInRecurrence(recurringEventId); if (gRecurrences != null) { Microsoft.Office.Interop.Outlook.Exceptions exps = ai.GetRecurrencePattern().Exceptions; foreach (Microsoft.Office.Interop.Outlook.Exception oExcp in exps) { for (int g = 0; g < gRecurrences.Count; g++) { Event ev = gRecurrences[g]; String gDate = ev.OriginalStartTime.DateTime ?? ev.OriginalStartTime.Date; Boolean isDeleted = exceptionIsDeleted(oExcp); if (isDeleted && !ai.AllDayEvent) { //Deleted items get truncated?! gDate = GoogleCalendar.GoogleTimeFrom(DateTime.Parse(gDate).Date); } if (oExcp.OriginalDate == DateTime.Parse(gDate)) { if (isDeleted) { MainForm.Instance.Logboxout(GoogleCalendar.GetEventSummary(ev)); MainForm.Instance.Logboxout("Recurrence deleted."); ev.Status = "cancelled"; GoogleCalendar.Instance.UpdateCalendarEntry_save(ref ev); } else { int exceptionItemsModified = 0; Event modifiedEv = GoogleCalendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, ev, ref exceptionItemsModified, forceCompare: true); if (exceptionItemsModified > 0) { GoogleCalendar.Instance.UpdateCalendarEntry_save(ref modifiedEv); } } break; } } } } }
/// <summary> /// Gets the Outlook AppointmentItem representation of this CalendarItem /// </summary> /// <param name="item">The AppointmentItem to edit</param> /// <returns>An Outlook AppointmentItem representation of this CalendarItem</returns> public AppointmentItem GetOutlookAppointment(AppointmentItem item) { try { item.Start = DateTime.Parse(Start); item.End = DateTime.Parse(End); item.Location = Location; item.Body = Body; item.Subject = Subject; item.AllDayEvent = IsAllDayEvent; Microsoft.Office.Interop.Outlook.TimeZone startTz = OutlookSync.Syncer.CurrentApplication.TimeZones[TimeZoneConverter.IanaToWindows(StartTimeZone)]; Microsoft.Office.Interop.Outlook.TimeZone endTz = OutlookSync.Syncer.CurrentApplication.TimeZones[TimeZoneConverter.IanaToWindows(EndTimeZone)]; item.StartTimeZone = startTz; item.EndTimeZone = endTz; if (!m_isUsingDefaultReminders) { item.ReminderMinutesBeforeStart = ReminderTime; item.ReminderSet = true; } if (Recurrence != null) { var pattern = item.GetRecurrencePattern(); Recurrence.GetOutlookPattern(ref pattern, IsAllDayEvent); } foreach (var attendee in Attendees) { var recipt = item.Recipients.Add(attendee.Name); bool result = recipt.Resolve(); if (!result) { ContactItem contact = new ContactItem(attendee.Name, attendee.Email); result = contact.CreateContact(); } result &= recipt.Resolve(); if (result) { recipt.AddressEntry.Address = attendee.Email; recipt.Type = attendee.Required ? (int)OlMeetingRecipientType.olRequired : (int)OlMeetingRecipientType.olOptional; } } return(item); } catch (COMException ex) { Log.Write(ex); MessageBox.Show( "CalendarItem: There has been an error when trying to create a outlook appointment item from a CalendarItem.", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return(null); }
private void processOutlookExceptions(AppointmentItem ai, Event ev, Boolean forceCompare) { if (!HasExceptions(ev, checkLocalCacheOnly: true)) { return; } if (!ai.Saved) { ai.Save(); } RecurrencePattern oPattern = ai.GetRecurrencePattern(); foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id)) { log.Fine("Found Google exception for " + (gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date)); DateTime oExcpDate = DateTime.Parse(gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date); AppointmentItem newAiExcp = getOutlookInstance(oPattern, oExcpDate); if (newAiExcp == null) { continue; } if (gExcp.Status != "cancelled") { int itemModified = 0; newAiExcp = OutlookCalendar.Instance.UpdateCalendarEntry(newAiExcp, gExcp, ref itemModified, forceCompare); if (itemModified > 0) { try { newAiExcp.Save(); } catch (System.Exception ex) { log.Warn(ex.Message); if (ex.Message == "Cannot save this item.") { MainForm.Instance.Logboxout("Uh oh! Outlook wasn't able to save this recurrence exception! " + "You may have two occurences on the same day, which it doesn't allow."); } } } } else { MainForm.Instance.Logboxout(OutlookCalendar.GetEventSummary(ai) + "\r\nDeleted."); newAiExcp.Delete(); } newAiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(newAiExcp); } if (!ai.Saved) { ai.Save(); } oPattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(oPattern); }
public List<String> BuildGooglePattern(AppointmentItem ai, Event ev) { if (!ai.IsRecurring || ai.RecurrenceState != OlRecurrenceState.olApptMaster) return null; log.Debug("Creating Google iCalendar definition for recurring event."); List<String> gPattern = new List<String>(); gPattern.Add("RRULE:" + buildRrule(ai.GetRecurrencePattern())); log.Debug(string.Join("\r\n", gPattern.ToArray())); return gPattern; }
/// <summary> /// Merges the recurrence. /// </summary> /// <param name="outlookCalendarItem">The outlook calendar item.</param> /// <param name="recurrence">The recurrence.</param> /// <returns>True if Change.</returns> public static bool MergeRecurrence(this AppointmentItem outlookCalendarItem, Recurrence recurrence) { if (recurrence != null && !string.IsNullOrWhiteSpace(recurrence.Value)) { var result = false; var outlookRecurrencePattern = outlookCalendarItem.GetRecurrencePattern(); var googleRecurrencePattern = RecurrenceSerializer.Deserialize(recurrence.Value); try { result |= outlookCalendarItem.ApplyProperty(r => r.AllDayEvent, googleRecurrencePattern.AllDayEvent); } catch (TargetInvocationException) { } result |= outlookRecurrencePattern.ApplyProperty(r => r.RecurrenceType, googleRecurrencePattern.RecurrenceType); result |= outlookRecurrencePattern.ApplyProperty(r => r.PatternStartDate, googleRecurrencePattern.StartPattern.HasValue ? googleRecurrencePattern.StartPattern.Value.Date : DateTime.Today); if (googleRecurrencePattern.EndPattern.HasValue) { result |= outlookRecurrencePattern.ApplyProperty(r => r.PatternEndDate, googleRecurrencePattern.EndPattern.Value.Date); } else { result |= outlookRecurrencePattern.ApplyProperty(r => r.NoEndDate, true); } result |= outlookRecurrencePattern.ApplyProperty(r => r.DayOfMonth, googleRecurrencePattern.DayOfMonth); result |= outlookRecurrencePattern.ApplyProperty(r => r.DayOfWeekMask, googleRecurrencePattern.DayOfWeek); result |= outlookRecurrencePattern.ApplyProperty(r => r.MonthOfYear, googleRecurrencePattern.MonthOfYear); if (outlookRecurrencePattern.StartTime.TimeOfDay.Ticks != googleRecurrencePattern.StartTime.TimeOfDay.Ticks) { result |= outlookRecurrencePattern.ApplyProperty(r => r.StartTime, googleRecurrencePattern.StartTime); } if (outlookRecurrencePattern.EndTime.TimeOfDay.Ticks != googleRecurrencePattern.EndTime.TimeOfDay.Ticks) { result |= outlookRecurrencePattern.ApplyProperty(r => r.EndTime, googleRecurrencePattern.EndTime); } if (googleRecurrencePattern.Count.HasValue) { result |= outlookRecurrencePattern.ApplyProperty(r => r.Occurrences, googleRecurrencePattern.Count.Value); } if (googleRecurrencePattern.Interval.HasValue) { result |= outlookRecurrencePattern.ApplyProperty(r => r.Interval, googleRecurrencePattern.Interval.Value); } return(result); } if (outlookCalendarItem.RecurrenceState == OlRecurrenceState.olApptNotRecurring) { outlookCalendarItem.ClearRecurrencePattern(); return(true); } return(false); }
//internal EventSchedule(Event googleItem, List<Event> recurrenceExceptions = null) //{ // this.AllDayEvent = !string.IsNullOrEmpty(googleItem.Start.Date); // this.TimeZone = googleItem.Start.TimeZone; // if (this.AllDayEvent) // { // this.StartTime = DateTime.Parse(googleItem.Start.Date); // this.EndTime = DateTime.Parse(googleItem.End.Date); // } else // { // this.StartTime = googleItem.Start.DateTime.Value; // this.EndTime = googleItem.End.DateTime.Value; // } // if (googleItem.Recurrence != null) // { // this.RecurrencePattern = new EventRecurrence(googleItem, recurrenceExceptions); // } //} internal EventSchedule(AppointmentItem outlookItem) { this.StartTime = outlookItem.Start; this.EndTime = outlookItem.End; this.AllDayEvent = outlookItem.AllDayEvent; this.TimeZone = outlookItem.StartTimeZone.ID; if (outlookItem.IsRecurring && (outlookItem.RecurrenceState == OlRecurrenceState.olApptMaster)) { this.RecurrencePattern = new EventRecurrence(outlookItem.GetRecurrencePattern()); } }
public void TestReplaceCalendar() { Application app = new Application(); OutlookCalendarWithSifE agent = new OutlookCalendarWithSifE(app); OutlookCalendar outlookAgent = new OutlookCalendar(app, CalendarPeriod.All); string existingEntryId = AddCalendar(); XElement x = XElement.Load(MockPath + "SifE.xml"); string entryId = agent.ReplaceItem(x.ToString(), existingEntryId); Assert.IsTrue(entryId == existingEntryId); AppointmentItem appointment = outlookAgent.GetItemByEntryId(entryId); Assert.AreEqual(appointment.Subject, x.Element("Subject").Value); Assert.AreEqual(((int)appointment.BusyStatus).ToString(), x.Element("BusyStatus").Value); Assert.AreEqual(appointment.Categories, x.Element("Categories").Value); Assert.AreEqual(appointment.Companies, x.Element("Companies").Value); Assert.AreEqual(((int)appointment.Importance).ToString(), x.Element("Importance").Value); Assert.AreEqual(appointment.AllDayEvent, x.Element("AllDayEvent").Value == "0"?false:true); // Assert.AreEqual(appointment.IsRecurring, x.Element("IsRecurring").Value=="0"?false:true);no need to check recurring events in sync. Assert.AreEqual(appointment.Location, x.Element("Location").Value); Assert.AreEqual(((int)appointment.MeetingStatus).ToString(), x.Element("MeetingStatus").Value); Assert.AreEqual(appointment.Mileage, x.Element("Mileage").Value); Assert.AreEqual(appointment.ReminderMinutesBeforeStart.ToString(), x.Element("ReminderMinutesBeforeStart").Value); Assert.AreEqual(appointment.ReminderSet, x.Element("ReminderSet").Value == "0"?false:true); Assert.AreEqual(appointment.ReminderSoundFile, x.Element("ReminderSoundFile").Value); Assert.AreEqual(DataUtility.DateTimeToIsoText(appointment.ReplyTime.ToUniversalTime()), x.Element("ReplyTime").Value); // Assert.AreEqual(((int)appointment.Sensitivity).ToString(), x.Element("Sensitivity").Value); if (appointment.IsRecurring) { Microsoft.Office.Interop.Outlook.RecurrencePattern pattern = appointment.GetRecurrencePattern(); Assert.AreEqual(pattern.Interval.ToString(), x.Element("Interval").Value); Assert.AreEqual(pattern.MonthOfYear.ToString(), x.Element("MonthOfYear").Value); Assert.AreEqual(pattern.DayOfMonth.ToString(), x.Element("DayOfMonth").Value); Assert.AreEqual(((int)pattern.DayOfWeekMask).ToString(), x.Element("DayOfWeekMask").Value); Assert.AreEqual(pattern.Instance.ToString(), x.Element("Instance").Value); Assert.AreEqual(DataUtility.DateTimeToIsoText(pattern.PatternStartDate), x.Element("PatternStartDate").Value); Assert.AreEqual(DataUtility.DateTimeToIsoText(pattern.PatternEndDate), x.Element("PatternEndDate").Value); Assert.AreEqual(pattern.NoEndDate, x.Element("NoEndDate").Value == "0" ? false : true); // Assert.AreEqual(pattern.Occurrences.ToString(), x.Element("Occurrences").Value); no need to test } else { Assert.AreEqual(appointment.Start.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"), x.Element("Start").Value); Assert.AreEqual(appointment.End.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"), x.Element("End").Value); } }
public void CompareOutlookPattern(Event ev, AppointmentItem ai, SyncDirection syncDirection, System.Text.StringBuilder sb, ref int itemModified) { if (ev.Recurrence == null) { return; } log.Fine("Building a temporary recurrent Appointment generated from Event"); AppointmentItem evAI = OutlookCalendar.Instance.IOutlook.UseOutlookCalendar().Items.Add() as AppointmentItem; evAI.Start = DateTime.Parse(ev.Start.Date ?? ev.Start.DateTime); RecurrencePattern evOpattern; RecurrencePattern aiOpattern = ai.GetRecurrencePattern(); BuildOutlookPattern(ev, evAI, out evOpattern); log.Fine("Comparing Google recurrence to Outlook equivalent"); if (MainForm.CompareAttribute("Recurrence Type", syncDirection, evOpattern.RecurrenceType.ToString(), aiOpattern.RecurrenceType.ToString(), sb, ref itemModified)) { aiOpattern.RecurrenceType = evOpattern.RecurrenceType; } if (MainForm.CompareAttribute("Recurrence Occurences", syncDirection, evOpattern.Occurrences.ToString(), aiOpattern.Occurrences.ToString(), sb, ref itemModified)) { aiOpattern.Occurrences = evOpattern.Occurrences; } if (MainForm.CompareAttribute("Recurrence Interval", syncDirection, evOpattern.Interval.ToString(), aiOpattern.Interval.ToString(), sb, ref itemModified)) { aiOpattern.Interval = evOpattern.Interval; } if (MainForm.CompareAttribute("Recurrence Instance", syncDirection, evOpattern.Instance.ToString(), aiOpattern.Instance.ToString(), sb, ref itemModified)) { aiOpattern.Instance = evOpattern.Instance; } if (MainForm.CompareAttribute("Recurrence DoW", syncDirection, evOpattern.DayOfWeekMask.ToString(), aiOpattern.DayOfWeekMask.ToString(), sb, ref itemModified)) { aiOpattern.DayOfWeekMask = evOpattern.DayOfWeekMask; } if (MainForm.CompareAttribute("Recurrence MoY", syncDirection, evOpattern.MonthOfYear.ToString(), aiOpattern.MonthOfYear.ToString(), sb, ref itemModified)) { aiOpattern.MonthOfYear = evOpattern.MonthOfYear; } aiOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(aiOpattern); evOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(evOpattern); evAI = (AppointmentItem)OutlookCalendar.ReleaseObject(evAI); }
internal void GetOutlookRecurrence(AppointmentItem outlookItem) { RecurrencePattern outlookRec = outlookItem.GetRecurrencePattern(); if (!this.AllDayEvent) { /// Set time of the event taking consideration difference of time zones. /// This makes sense only in case the event isn't all day one /// Google event time is already converted to local time zone var googleTimeZone = TimeZoneInfo.Local; var outlookTimeZone = TimeZoneInfo.FindSystemTimeZoneById(outlookItem.StartTimeZone.ID); /// StartTime property contains only time (not date) outlookRec.StartTime = TimeZoneInfo.ConvertTime(this.StartTime, googleTimeZone, outlookTimeZone); } outlookRec.Duration = (int)(this.EndTime - this.StartTime).TotalMinutes; outlookRec.RecurrenceType = (OlRecurrenceType)this.RecurrencePattern.Frequency; if ((this.RecurrencePattern.Frequency == RecurrenceFrequency.Weekly) || (this.RecurrencePattern.Frequency == RecurrenceFrequency.MonthlyNth)) { outlookRec.DayOfWeekMask = (OlDaysOfWeek)this.RecurrencePattern.DayOfWeekMask; } if (this.RecurrencePattern.Interval > 1) { if ((outlookRec.RecurrenceType != OlRecurrenceType.olRecursYearly) || (VSTO.Properties.Settings.Default.OutlookVersion >= 14)) { outlookRec.Interval = this.RecurrencePattern.Interval; } } outlookRec.PatternStartDate = this.RecurrencePattern.StartDate; if (this.RecurrencePattern.EndMethod == EndBy.Date) { outlookRec.PatternEndDate = this.RecurrencePattern.EndDate; } if (this.RecurrencePattern.EndMethod == EndBy.OccurencesCount) { outlookRec.Occurrences = this.RecurrencePattern.Count; } if ((this.RecurrencePattern.Frequency == RecurrenceFrequency.Monthly) || (this.RecurrencePattern.Frequency == RecurrenceFrequency.Yearly)) { outlookRec.DayOfMonth = this.RecurrencePattern.DayOfMonth; } /// As it was found out RecurrencePattern.Instance is valid for olRecursMonthNth only. /// Not sure yet whether Google provides such frequency model. If not - it will be just omited //outlookRec.Instance = this.WeekInterval; if (this.RecurrencePattern.Frequency == RecurrenceFrequency.Yearly) { outlookRec.MonthOfYear = this.RecurrencePattern.Month; } //outlookRec.NoEndDate = this.EndMethod == EndBy.NoEnd; }
public static Boolean HasExceptions(AppointmentItem ai) { RecurrencePattern rp = null; Exceptions excps = null; try { rp = ai.GetRecurrencePattern(); excps = rp.Exceptions; return(excps.Count != 0); } finally { excps = (Exceptions)OutlookOgcs.Calendar.ReleaseObject(excps); rp = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(rp); } }
public List <String> BuildGooglePattern(AppointmentItem ai, Event ev) { if (!ai.IsRecurring || ai.RecurrenceState != OlRecurrenceState.olApptMaster) { return(null); } log.Debug("Creating Google iCalendar definition for recurring event."); List <String> gPattern = new List <String>(); gPattern.Add("RRULE:" + buildRrule(ai.GetRecurrencePattern())); log.Debug(string.Join("\r\n", gPattern.ToArray())); return(gPattern); }
public AppointmentSchedule(AppointmentItem appointment) { _appointment = appointment; if (appointment.IsRecurring && appointment.RecurrenceState == OlRecurrenceState.olApptMaster) { try { Recurrence = new AppointmentRecurrence(_appointment.GetRecurrencePattern()); } catch (ArgumentOutOfRangeException ex) { Logger.Warning(ex.Message); } } }
public static void CreateGoogleExceptions(AppointmentItem ai, String recurringEventId) { if (!ai.IsRecurring) { return; } log.Debug("Creating Google recurrence exceptions."); List <Event> gRecurrences = GoogleCalendar.Instance.GetCalendarEntriesInRecurrence(recurringEventId); if (gRecurrences != null) { Microsoft.Office.Interop.Outlook.Exceptions exps = ai.GetRecurrencePattern().Exceptions; foreach (Microsoft.Office.Interop.Outlook.Exception oExcp in exps) { for (int g = 0; g < gRecurrences.Count; g++) { Event ev = gRecurrences[g]; String gDate = ev.OriginalStartTime.DateTime ?? ev.OriginalStartTime.Date; Boolean isDeleted = exceptionIsDeleted(oExcp); if (isDeleted && !ai.AllDayEvent) //Deleted items get truncated?! { gDate = GoogleCalendar.GoogleTimeFrom(DateTime.Parse(gDate).Date); } if (oExcp.OriginalDate == DateTime.Parse(gDate)) { if (isDeleted) { MainForm.Instance.Logboxout(GoogleCalendar.GetEventSummary(ev)); MainForm.Instance.Logboxout("Recurrence deleted."); ev.Status = "cancelled"; GoogleCalendar.Instance.UpdateCalendarEntry_save(ref ev); } else { int exceptionItemsModified = 0; Event modifiedEv = GoogleCalendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, ev, ref exceptionItemsModified, forceCompare: true); if (exceptionItemsModified > 0) { GoogleCalendar.Instance.UpdateCalendarEntry_save(ref modifiedEv); } } break; } } } } }
private void processOutlookExceptions(AppointmentItem ai, Event ev, Boolean forceCompare) { if (!HasExceptions(ev, checkLocalCacheOnly: true)) { return; } if (!ai.Saved) { ai.Save(); } RecurrencePattern oPattern = ai.GetRecurrencePattern(); foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id)) { log.Fine("Found Google exception for " + (gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date)); DateTime oExcpDate = DateTime.Parse(gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date); AppointmentItem newAiExcp = getOutlookInstance(oPattern, oExcpDate); if (newAiExcp == null) { continue; } if (gExcp.Status != "cancelled") { int itemModified = 0; newAiExcp = OutlookCalendar.Instance.UpdateCalendarEntry(newAiExcp, gExcp, ref itemModified, forceCompare); if (itemModified > 0) { newAiExcp.Save(); } } else { MainForm.Instance.Logboxout(OutlookCalendar.GetEventSummary(ai) + "\r\nDeleted."); newAiExcp.Delete(); } newAiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(newAiExcp); } if (!ai.Saved) { ai.Save(); } oPattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(oPattern); }
public static void DeleteEventOutlook(CancelMeetingRoomForm data) { try { Application app = new Application(); MAPIFolder calendar = app.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar); Items calendarItems = calendar.Items; AppointmentItem item = calendarItems["Test Appointment"] as AppointmentItem; RecurrencePattern pattern = item.GetRecurrencePattern(); AppointmentItem itemDelete = pattern.GetOccurrence(new DateTime(2006, 6, 28, 8, 0, 0)); if (itemDelete != null) { itemDelete.Delete(); } } catch (System.Exception) { } }
public List <String> BuildGooglePattern(AppointmentItem ai, Event ev) { if (!ai.IsRecurring || ai.RecurrenceState != OlRecurrenceState.olApptMaster) { return(null); } log.Debug("Creating Google iCalendar definition for recurring event."); List <String> gPattern = new List <String>(); RecurrencePattern rp = null; try { rp = ai.GetRecurrencePattern(); DateTime localEnd = rp.PatternEndDate + ai.EndInEndTimeZone.TimeOfDay; DateTime utcEnd = TimeZoneInfo.ConvertTimeToUtc(localEnd, TimeZoneInfo.FindSystemTimeZoneById(ai.EndTimeZone.ID)); gPattern.Add("RRULE:" + buildRrule(rp, utcEnd)); } finally { rp = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(rp); } log.Debug(string.Join("\r\n", gPattern.ToArray())); return(gPattern); }
public static void AddItemCalendar(List <BirthdayItem> listItem, int hour_begin, int min_begin, int duration, int remind_min) { Application Application = null; Application = new Application(); MAPIFolder primaryCalendar = Application.ActiveExplorer().Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar); foreach (var item in listItem) { //var personalCalendar = primaryCalendar.Folders["Birthday"]; //if (personalCalendar == null) return; AppointmentItem newEvent = primaryCalendar.Items.Add(OlItemType.olAppointmentItem) as AppointmentItem; //AppointmentItem newEvent = personalCalendar.Items.Add(OlItemType.olAppointmentItem) as AppointmentItem; if (newEvent != null) { var date = new DateTime(DateTime.Now.Year, item.Birthday.Month, item.Birthday.Day, hour_begin, min_begin, 0); newEvent.Start = date; //newEvent.End = item.EndDateTime; var recur = newEvent.GetRecurrencePattern(); recur.RecurrenceType = OlRecurrenceType.olRecursYearly; recur.PatternStartDate = date; recur.StartTime = date; recur.Duration = duration; recur.NoEndDate = true; //recur.EndTime = DateTime.Now.AddMinutes(10); newEvent.ReminderMinutesBeforeStart = remind_min; newEvent.Subject = $"[B] День рождения {item.Name}"; newEvent.Body = $"День рождения {item.Name}. Дата рождения {item.Birthday:d}"; newEvent.Save(); AddProcProgressBar?.Invoke(null, null); } } Application.ActiveExplorer().CurrentFolder.Display(); }
private void buildOutlookPattern(Event ev, AppointmentItem ai, out RecurrencePattern oPattern) { if (ev.Recurrence == null) { oPattern = null; return; } Dictionary <String, String> ruleBook = explodeRrule(ev.Recurrence); if (ruleBook == null) { throw new ApplicationException("WARNING: The recurrence pattern is not compatible with Outlook. This event cannot be synced."); } log.Fine("Building Outlook recurrence pattern"); oPattern = ai.GetRecurrencePattern(); #region RECURRENCE PATTERN //RRULE:FREQ=WEEKLY;UNTIL=20150906T000000Z;BYDAY=SA switch (ruleBook["FREQ"]) { case "DAILY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursDaily; break; } case "WEEKLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursWeekly; // Need to work out dayMask from "BY" pattern // Eg "BYDAY=MO,TU,WE,TH,FR" OlDaysOfWeek dowMask = getDOWmask(ruleBook); if (dowMask != 0) { oPattern.DayOfWeekMask = dowMask; } break; } case "MONTHLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (oPattern.DayOfWeekMask == (OlDaysOfWeek)127 && gInstance == -1 && (ev.Start.DateTime ?? DateTime.Parse(ev.Start.Date)).Day > 28) { //In Outlook this is simply a monthly recurring oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; } } if (ruleBook.ContainsKey("BYDAY")) { if (ruleBook["BYDAY"].StartsWith("-1")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = 5; oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart("-1".ToCharArray())); } else if ("1,2,3,4".Contains(ruleBook["BYDAY"].Substring(0, 1))) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = Convert.ToInt16(ruleBook["BYDAY"].Substring(0, 1)); oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart(oPattern.Instance.ToString().ToCharArray())); } } break; } case "YEARLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearly; //Google interval is years, Outlook is months if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1) { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]) * 12; } if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (ruleBook.ContainsKey("BYMONTH")) { oPattern.MonthOfYear = Convert.ToInt16(ruleBook["BYMONTH"]); } } break; } } #endregion #region RANGE ai = OutlookOgcs.Calendar.Instance.IOutlook.WindowsTimeZone_set(ai, ev); oPattern.PatternStartDate = ev.Start.DateTime ?? DateTime.Parse(ev.Start.Date); if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1 && ruleBook["FREQ"] != "YEARLY") { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]); } if (ruleBook.ContainsKey("COUNT")) { oPattern.Occurrences = Convert.ToInt16(ruleBook["COUNT"]); } if (ruleBook.ContainsKey("UNTIL")) { if (ruleBook["UNTIL"].StartsWith("4500")) { log.Warn("Outlook can't handle end dates this far in the future. Converting to no end date."); oPattern.NoEndDate = true; } else { oPattern.PatternEndDate = DateTime.ParseExact(ruleBook["UNTIL"].ToString().Substring(0, 8), "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture).Date; } } if (!ruleBook.ContainsKey("COUNT") && !ruleBook.ContainsKey("UNTIL")) { oPattern.NoEndDate = true; } #endregion }
private void buildOutlookPattern(Event ev, AppointmentItem ai, out RecurrencePattern oPattern) { if (ev.Recurrence == null) { oPattern = null; return; } Dictionary <String, String> ruleBook = explodeRrule(ev.Recurrence); if (ruleBook == null) { throw new ApplicationException("WARNING: The recurrence pattern is not compatible with Outlook. This event cannot be synced."); } log.Fine("Building Outlook recurrence pattern"); oPattern = ai.GetRecurrencePattern(); #region RECURRENCE PATTERN //RRULE:FREQ=WEEKLY;UNTIL=20150906T000000Z;BYDAY=SA switch (ruleBook["FREQ"]) { case "DAILY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursDaily; break; } case "WEEKLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursWeekly; // Need to work out dayMask from "BY" pattern // Eg "BYDAY=MO,TU,WE,TH,FR" OlDaysOfWeek dowMask = getDOWmask(ruleBook); if (dowMask != 0) { oPattern.DayOfWeekMask = dowMask; } break; } case "MONTHLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (oPattern.DayOfWeekMask == (OlDaysOfWeek)127 && gInstance == -1 && (ev.Start.DateTime ?? DateTime.Parse(ev.Start.Date)).Day > 28) { //In Outlook this is simply a monthly recurring oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; } } if (ruleBook.ContainsKey("BYDAY")) { if (ruleBook["BYDAY"].StartsWith("-1")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = 5; oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart("-1".ToCharArray())); } else if ("1,2,3,4".Contains(ruleBook["BYDAY"].Substring(0, 1))) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = Convert.ToInt16(ruleBook["BYDAY"].Substring(0, 1)); oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart(oPattern.Instance.ToString().ToCharArray())); } } break; } case "YEARLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearly; //Google interval is years, Outlook is months if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1) { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]) * 12; } if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (ruleBook.ContainsKey("BYMONTH")) { oPattern.MonthOfYear = Convert.ToInt16(ruleBook["BYMONTH"]); } } break; } } #endregion #region RANGE ai = OutlookOgcs.Calendar.Instance.IOutlook.WindowsTimeZone_set(ai, ev); oPattern.PatternStartDate = ev.Start.DateTime ?? DateTime.Parse(ev.Start.Date); if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1 && ruleBook["FREQ"] != "YEARLY") { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]); } if (ruleBook.ContainsKey("COUNT")) { oPattern.Occurrences = Convert.ToInt16(ruleBook["COUNT"]); } if (ruleBook.ContainsKey("UNTIL")) { if (ruleBook["UNTIL"].StartsWith("4500")) { log.Warn("Outlook can't handle end dates this far in the future. Converting to no end date."); oPattern.NoEndDate = true; } else { DateTime endDate; if (ruleBook["UNTIL"].Length == 8 && !ruleBook["UNTIL"].EndsWith("Z")) { endDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture).Date; } else { endDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMddTHHmmssZ", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal); endDate = endDate.AddHours(TimezoneDB.GetUtcOffset(ev.End.TimeZone)).Date; } if (endDate < oPattern.PatternStartDate) { log.Debug("PatternStartDate: " + oPattern.PatternStartDate.ToString("yyyyMMddHHmmss")); log.Debug("PatternEndDate: " + ruleBook["UNTIL"].ToString()); String summary = GoogleOgcs.Calendar.GetEventSummary(ev, onlyIfNotVerbose: true); Forms.Main.Instance.Console.Update(summary + "The recurring Google event has an end date <i>before</i> the start date, which Outlook doesn't allow.<br/>" + "The synced Outlook recurrence has been changed to a single occurrence.", Console.Markup.warning); oPattern.Occurrences = 1; } else { oPattern.PatternEndDate = endDate; } } } if (!ruleBook.ContainsKey("COUNT") && !ruleBook.ContainsKey("UNTIL")) { oPattern.NoEndDate = true; } #endregion }
public static void UpdateGoogleExceptions(AppointmentItem ai, Event ev) { if (ai.IsRecurring) { RecurrencePattern recurrence = ai.GetRecurrencePattern(); try { if (recurrence.Exceptions.Count > 0) { log.Debug(OutlookCalendar.GetEventSummary(ai)); log.Debug("This is a recurring appointment with " + recurrence.Exceptions.Count + " exceptions that will now be iteratively compared."); foreach (Microsoft.Office.Interop.Outlook.Exception oExcp in recurrence.Exceptions) { 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 = oIsDeleted ? oExcp.OriginalDate : oExcp.AppointmentItem.Start; 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(oExcp, ev.RecurringEventId ?? ev.Id, OutlookCalendar.Instance.IOutlook.GetGlobalApptID(ai)); 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; } try { GoogleCalendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, gExcp, ref excp_itemModified); } catch (System.Exception ex) { if (oIsDeleted) { if (gExcp.Status != "cancelled") { gExcp.Status = "cancelled"; excp_itemModified++; } } else { 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 { recurrence = (RecurrencePattern)OutlookCalendar.ReleaseObject(recurrence); } } }
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 void CompareOutlookPattern(Event ev, AppointmentItem ai, System.Text.StringBuilder sb, ref int itemModified) { if (ev.Recurrence == null) return; log.Fine("Building a temporary recurrent Appointment generated from Event"); AppointmentItem evAI = OutlookCalendar.Instance.IOutlook.UseOutlookCalendar().Items.Add() as AppointmentItem; RecurrencePattern evOpattern; RecurrencePattern aiOpattern = ai.GetRecurrencePattern(); BuildOutlookPattern(ev, evAI, out evOpattern); log.Fine("Comparing Google recurrence to Outlook equivalent"); if (MainForm.CompareAttribute("Recurrence Type", Settings.Instance.SyncDirection, evOpattern.RecurrenceType.ToString(), aiOpattern.RecurrenceType.ToString(), sb, ref itemModified)) { aiOpattern.RecurrenceType = evOpattern.RecurrenceType; } if (MainForm.CompareAttribute("Recurrence Interval", Settings.Instance.SyncDirection, evOpattern.Interval.ToString(), aiOpattern.Interval.ToString(), sb, ref itemModified)) { aiOpattern.Interval = evOpattern.Interval; } if (MainForm.CompareAttribute("Recurrence Instance", Settings.Instance.SyncDirection, evOpattern.Instance.ToString(), aiOpattern.Instance.ToString(), sb, ref itemModified)) { aiOpattern.Instance= evOpattern.Instance; } if (MainForm.CompareAttribute("Recurrence DoW", Settings.Instance.SyncDirection, evOpattern.DayOfWeekMask.ToString(), aiOpattern.DayOfWeekMask.ToString(), sb, ref itemModified)) { aiOpattern.DayOfWeekMask = evOpattern.DayOfWeekMask; } if (MainForm.CompareAttribute("Recurrence MoY", Settings.Instance.SyncDirection, evOpattern.MonthOfYear.ToString(), aiOpattern.MonthOfYear.ToString(), sb, ref itemModified)) { aiOpattern.MonthOfYear = evOpattern.MonthOfYear; } aiOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(aiOpattern); evOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(evOpattern); evAI = (AppointmentItem)OutlookCalendar.ReleaseObject(evAI); }
private String FormattedEvent(AppointmentItem item, String created, bool cancelled, bool expandRecurring) { String str = "BEGIN:VEVENT\r\n"; str += "CREATED:" + created + "\r\n"; // If we're not expanding recurring events, this is an exception, which means it's cancelled if (!expandRecurring) { str += "TRANSP:TRANSPARENT\r\n"; } else { str += "TRANSP:OPAQUE\r\n"; } str += wrapString("DESCRIPTION:" + item.Body.Replace("\r\n", "\\n").Replace(",", "\\,") + "\\n") + "\r\n"; str += wrapString("SUMMARY:" + item.Subject) + "\r\n"; str += wrapString("UID:" + item.GlobalAppointmentID) + "\r\n"; str += wrapString("ORGANIZER;CN=\"" + item.GetOrganizer().Name + "\":mailto:" + item.GetOrganizer().PropertyAccessor.GetProperty(@"http://schemas.microsoft.com/mapi/proptag/0x39FE001E").ToString()) + "\r\n"; Recipients recipients = item.Recipients; if (recipients.Count > 1) { foreach (Recipient recipient in recipients) { String recip = "ATTENDEE;CN=\"" + recipient.Name + "\""; switch (recipient.Type) { case (int)NetOffice.OutlookApi.Enums.OlMeetingRecipientType.olOptional: recip += ";ROLE=OPT-PARTICIPANT"; break; case (int)NetOffice.OutlookApi.Enums.OlMeetingRecipientType.olRequired: recip += ";ROLE=REQ-PARTICIPANT"; break; case (int)NetOffice.OutlookApi.Enums.OlMeetingRecipientType.olOrganizer: recip += ";ROLE=CHAIR"; break; case (int)NetOffice.OutlookApi.Enums.OlMeetingRecipientType.olResource: recip += ";ROLE=NON-PARTICIPANT"; break; } if (item.ResponseRequested) { recip += ";RSVP=TRUE"; } switch (recipient.MeetingResponseStatus) { case NetOffice.OutlookApi.Enums.OlResponseStatus.olResponseAccepted: recip += ";PARTSTAT=ACCEPTED"; break; case NetOffice.OutlookApi.Enums.OlResponseStatus.olResponseDeclined: recip += ";PARTSTAT=DECLINED"; break; case NetOffice.OutlookApi.Enums.OlResponseStatus.olResponseNotResponded: recip += ";PARTSTAT=NEEDS-ACTION"; break; case NetOffice.OutlookApi.Enums.OlResponseStatus.olResponseOrganized: recip += ";PARTSTAT=ACCEPTED"; break; case NetOffice.OutlookApi.Enums.OlResponseStatus.olResponseTentative: recip += ";PARTSTAT=TENTATIVE"; break; } str += wrapString(recip + ":mailto:" + recipient.PropertyAccessor.GetProperty(@"http://schemas.microsoft.com/mapi/proptag/0x39FE001E").ToString()) + "\r\n"; } } if (item.Location.Length > 0) { str += wrapString("LOCATION:" + item.Location) + "\r\n"; } { str += "PRIORITY:"; switch (item.Importance) { case NetOffice.OutlookApi.Enums.OlImportance.olImportanceNormal: str += "5" + "\r\n"; break; case NetOffice.OutlookApi.Enums.OlImportance.olImportanceLow: str += "6" + "\r\n"; break; case NetOffice.OutlookApi.Enums.OlImportance.olImportanceHigh: str += "1" + "\r\n"; break; } } { // SENSITIVITY switch (item.Sensitivity) { case NetOffice.OutlookApi.Enums.OlSensitivity.olNormal: str += "CLASS:PUBLIC" + "\r\n"; break; case NetOffice.OutlookApi.Enums.OlSensitivity.olConfidential: str += "CLASS:CONFIDENTIAL" + "\r\n"; break; case NetOffice.OutlookApi.Enums.OlSensitivity.olPrivate: str += "CLASS:PRIVATE" + "\r\n"; break; case NetOffice.OutlookApi.Enums.OlSensitivity.olPersonal: str += "CLASS:PRIVATE" + "\r\n"; break; } } if (item.AllDayEvent) { str += "DTSTART;VALUE=DATE:" + item.Start.ToString(@"yyyyMMdd") + "\r\n"; str += "DTEND;VALUE=DATE:" + item.End.ToString(@"yyyyMMdd") + "\r\n"; } else { str += "DTSTART;TZID=" + TZConvert.WindowsToIana(item.StartTimeZone.ID, "NL") + ":" + item.StartInStartTimeZone.ToString(@"yyyyMMdd\THHmmss") + "\r\n"; str += "DTEND;TZID=" + TZConvert.WindowsToIana(item.EndTimeZone.ID, "NL") + ":" + item.EndInEndTimeZone.ToString(@"yyyyMMdd\THHmmss") + "\r\n"; } str += "LAST-MODIFIED:" + item.LastModificationTime.ToUniversalTime().ToString(@"yyyyMMdd\THHmmssZ") + "\r\n"; str += "DTSTAMP:" + item.CreationTime.ToUniversalTime().ToString(@"yyyyMMdd\THHmmssZ") + "\r\n"; // Reminder if (item.ReminderSet) { str += "BEGIN:VALARM\r\n"; str += "TRIGGER:-PT" + item.ReminderMinutesBeforeStart + "M\r\n"; str += "ACTION:DISPLAY\r\n"; str += "DESCRIPTION:Reminder\r\n"; str += "END:VALARM\r\n"; } if (expandRecurring && item.IsRecurring) { Console.WriteLine("Recurring meeting: " + item.Subject); RecurrencePattern rp = item.GetRecurrencePattern(); str += "RRULE:"; switch (rp.RecurrenceType) { case NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursDaily: str += "FREQ=DAILY"; break; case NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursMonthly: str += "FREQ=MONTHLY"; break; case NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursMonthNth: str += "FREQ=MONTHLY"; break; case NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursWeekly: str += "FREQ=WEEKLY"; break; case NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursYearly: str += "FREQ=YEARLY"; break; case NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursYearNth: break; } if (!rp.NoEndDate) { // There is an end-date, either in occurrences or an end-date if (rp.PatternEndDate != null) { str += ";UNTIL=" + rp.PatternEndDate.ToUniversalTime().ToString(@"yyyyMMdd\THHmmssZ"); } else { str += ";COUNT=" + rp.Occurrences; } } if (rp.Interval > 1) { str += ";INTERVAL=" + rp.Interval; } string days = ""; if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olMonday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olMonday) { if (days.Length > 0) { days += ","; } days += "MO"; } if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olTuesday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olTuesday) { if (days.Length > 0) { days += ","; } days += "TU"; } if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olWednesday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olWednesday) { if (days.Length > 0) { days += ","; } days += "WE"; } if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olThursday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olThursday) { if (days.Length > 0) { days += ","; } days += "TH"; } if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olFriday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olFriday) { if (days.Length > 0) { days += ","; } days += "FR"; } if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olSaturday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olSaturday) { if (days.Length > 0) { days += ","; } days += "SA"; } if ((rp.DayOfWeekMask & NetOffice.OutlookApi.Enums.OlDaysOfWeek.olSunday) == NetOffice.OutlookApi.Enums.OlDaysOfWeek.olSunday) { if (days.Length > 0) { days += ","; } days += "SU"; } str += ";BYDAY=" + days; if (rp.RecurrenceType == NetOffice.OutlookApi.Enums.OlRecurrenceType.olRecursMonthNth) { str += ";BYSETPOS=1"; } str += "\r\n"; str += "END:VEVENT" + "\r\n"; Exceptions exceptions = rp.Exceptions; foreach (NetOffice.OutlookApi.Exception exc in exceptions) { Console.WriteLine("Found an exception to item " + item.Subject); try { str += FormattedEvent(exc.AppointmentItem, created, true, false); Console.WriteLine("Wrote the exception"); } catch (System.Runtime.InteropServices.COMException e) { // Let's ignore any errors for the moment, they come from items out of the current range i think... Console.WriteLine("Error writing exception: " + e.Message); } } } else { str += "END:VEVENT" + "\r\n"; } return(str); }
public AppointmentItem UpdateCalendarEntry(AppointmentItem ai, Event ev, ref int itemModified, Boolean forceCompare = false) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { //The exception child objects might have changed log.Debug("Processing recurring master appointment."); } else { if (!(MainForm.Instance.ManualForceCompare || forceCompare)) { //Needed if the exception has just been created, but now needs updating if (Settings.Instance.SyncDirection != SyncDirection.Bidirectional) { if (DateTime.Parse(GoogleCalendar.GoogleTimeFrom(ai.LastModificationTime)) > DateTime.Parse(ev.Updated)) return null; } else { if (GoogleCalendar.GetOGCSlastModified(ev).AddSeconds(5) >= DateTime.Parse(ev.Updated)) //Google last modified by OGCS return null; if (DateTime.Parse(GoogleCalendar.GoogleTimeFrom(ai.LastModificationTime)) > DateTime.Parse(ev.Updated)) return null; } } } String evSummary = GoogleCalendar.GetEventSummary(ev); log.Debug("Processing >> " + evSummary); System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.AppendLine(evSummary); if (ai.RecurrenceState != OlRecurrenceState.olApptMaster) { if (ai.AllDayEvent != (ev.Start.DateTime == null)) { sb.AppendLine("All-Day: " + ai.AllDayEvent + " => " + (ev.Start.DateTime == null)); ai.AllDayEvent = (ev.Start.DateTime == null); itemModified++; } } RecurrencePattern oPattern = (ai.RecurrenceState == OlRecurrenceState.olApptMaster) ? ai.GetRecurrencePattern() : null; Recurrence.Instance.CompareOutlookPattern(ev, ai, SyncDirection.GoogleToOutlook, sb, ref itemModified); DateTime evParsedDate = DateTime.Parse(ev.Start.Date ?? ev.Start.DateTime); if (MainForm.CompareAttribute("Start time", SyncDirection.GoogleToOutlook, GoogleCalendar.GoogleTimeFrom(evParsedDate), GoogleCalendar.GoogleTimeFrom(ai.Start), sb, ref itemModified)) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { oPattern.PatternStartDate = evParsedDate; oPattern.StartTime = evParsedDate; } else { ai.Start = evParsedDate; } } evParsedDate = DateTime.Parse(ev.End.Date ?? ev.End.DateTime); if (MainForm.CompareAttribute("End time", SyncDirection.GoogleToOutlook, GoogleCalendar.GoogleTimeFrom(evParsedDate), GoogleCalendar.GoogleTimeFrom(ai.End), sb, ref itemModified)) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { oPattern.EndTime = evParsedDate; } else { ai.End = evParsedDate; } } if (oPattern != null) { oPattern.Duration = Convert.ToInt32((evParsedDate - DateTime.Parse(ev.Start.Date ?? ev.Start.DateTime)).TotalMinutes); oPattern = (RecurrencePattern)ReleaseObject(oPattern); } if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { if (ev.Recurrence == null || ev.RecurringEventId != null) { log.Debug("Converting to non-recurring events."); ai.ClearRecurrencePattern(); itemModified++; } else { Recurrence.Instance.UpdateOutlookExceptions(ai, ev); } } else if (ai.RecurrenceState == OlRecurrenceState.olApptNotRecurring) { if (!ai.IsRecurring && ev.Recurrence != null && ev.RecurringEventId == null) { log.Debug("Converting to recurring appointment."); Recurrence.Instance.CreateOutlookExceptions(ai, ev); itemModified++; } } String summaryObfuscated = Obfuscate.ApplyRegex(ev.Summary, SyncDirection.GoogleToOutlook); if (MainForm.CompareAttribute("Subject", SyncDirection.GoogleToOutlook, summaryObfuscated, ai.Subject, sb, ref itemModified)) { ai.Subject = summaryObfuscated; } if (!Settings.Instance.AddDescription) ev.Description = ""; if (Settings.Instance.SyncDirection == SyncDirection.GoogleToOutlook || !Settings.Instance.AddDescription_OnlyToGoogle) { if (MainForm.CompareAttribute("Description", SyncDirection.GoogleToOutlook, ev.Description, ai.Body, sb, ref itemModified)) ai.Body = ev.Description; } if (MainForm.CompareAttribute("Location", SyncDirection.GoogleToOutlook, ev.Location, ai.Location, sb, ref itemModified)) ai.Location = ev.Location; String oPrivacy = (ai.Sensitivity == OlSensitivity.olNormal) ? "default" : "private"; String gPrivacy = ev.Visibility ?? "default"; if (MainForm.CompareAttribute("Private", SyncDirection.GoogleToOutlook, gPrivacy, oPrivacy, sb, ref itemModified)) { ai.Sensitivity = (ev.Visibility != null && ev.Visibility == "private") ? OlSensitivity.olPrivate : OlSensitivity.olNormal; } String oFreeBusy = (ai.BusyStatus == OlBusyStatus.olFree) ? "transparent" : "opaque"; String gFreeBusy = ev.Transparency ?? "opaque"; if (MainForm.CompareAttribute("Free/Busy", SyncDirection.GoogleToOutlook, gFreeBusy, oFreeBusy, sb, ref itemModified)) { ai.BusyStatus = (ev.Transparency != null && ev.Transparency == "transparent") ? OlBusyStatus.olFree : OlBusyStatus.olBusy; } if (Settings.Instance.AddAttendees) { if (ev.Description != null && ev.Description.Contains("===--- Attendees ---===")) { //Protect against <v1.2.4 where attendees were stored as text log.Info("This event still has attendee information in the description - cannot sync them."); } else if (Settings.Instance.SyncDirection == SyncDirection.Bidirectional && ev.Attendees != null && ev.Attendees.Count == 0 && ai.Recipients.Count > 150) { log.Info("Attendees not being synced - there are too many ("+ ai.Recipients.Count +") for Google."); } else { //Build a list of Outlook attendees. Any remaining at the end of the diff must be deleted. List<Recipient> removeRecipient = new List<Recipient>(); if (ai.Recipients != null) { foreach (Recipient recipient in ai.Recipients) { if (recipient.Name != ai.Organizer) removeRecipient.Add(recipient); } } if (ev.Attendees != null) { for (int g = ev.Attendees.Count - 1; g >= 0; g--) { bool foundRecipient = false; EventAttendee attendee = ev.Attendees[g]; foreach (Recipient recipient in ai.Recipients) { if (!recipient.Resolved) recipient.Resolve(); String recipientSMTP = IOutlook.GetRecipientEmail(recipient); if (recipientSMTP.ToLower() == attendee.Email.ToLower()) { foundRecipient = true; removeRecipient.Remove(recipient); //Optional attendee bool oOptional = (ai.OptionalAttendees != null && ai.OptionalAttendees.Contains(attendee.DisplayName ?? attendee.Email)); bool gOptional = (attendee.Optional == null) ? false : (bool)attendee.Optional; if (MainForm.CompareAttribute("Recipient " + recipient.Name + " - Optional Check", SyncDirection.GoogleToOutlook, gOptional, oOptional, sb, ref itemModified)) { if (gOptional) { recipient.Type = (int)OlMeetingRecipientType.olOptional; } else { recipient.Type = (int)OlMeetingRecipientType.olRequired; } } //Response is readonly in Outlook :( break; } } if (!foundRecipient && (attendee.DisplayName != ai.Organizer)) //Attendee in Google is owner in Outlook, so can't also be added as a recipient) { sb.AppendLine("Recipient added: " + (attendee.DisplayName ?? attendee.Email)); createRecipient(attendee, ai); itemModified++; } } } foreach (Recipient recipient in removeRecipient) { sb.AppendLine("Recipient removed: " + recipient.Name); recipient.Delete(); itemModified++; } } } //Reminders if (Settings.Instance.AddReminders) { if (ev.Reminders.Overrides != null) { //Find the popup reminder in Google for (int r = ev.Reminders.Overrides.Count - 1; r >= 0; r--) { EventReminder reminder = ev.Reminders.Overrides[r]; if (reminder.Method == "popup") { if (ai.ReminderSet) { if (MainForm.CompareAttribute("Reminder", SyncDirection.GoogleToOutlook, reminder.Minutes.ToString(), ai.ReminderMinutesBeforeStart.ToString(), sb, ref itemModified)) { ai.ReminderMinutesBeforeStart = (int)reminder.Minutes; } } else { sb.AppendLine("Reminder: nothing => " + reminder.Minutes); ai.ReminderSet = true; ai.ReminderMinutesBeforeStart = (int)reminder.Minutes; itemModified++; } //if Outlook reminders set } //if google reminder found } //foreach reminder } else { //no google reminders set if (ai.ReminderSet && IsOKtoSyncReminder(ai)) { sb.AppendLine("Reminder: " + ai.ReminderMinutesBeforeStart + " => removed"); ai.ReminderSet = false; itemModified++; } } } if (itemModified > 0) { MainForm.Instance.Logboxout(sb.ToString(), false, verbose: true); MainForm.Instance.Logboxout(itemModified + " attributes updated.", verbose: true); System.Windows.Forms.Application.DoEvents(); } return ai; }
/// <summary> /// Merges the with. /// </summary> /// <param name="googleCalendarItem">The google calendar item.</param> /// <param name="outlookCalendarItem">The outlook calendar item.</param> /// <returns>True if Changed.</returns> public static bool MergeWith(this EventEntry googleCalendarItem, AppointmentItem outlookCalendarItem) { var result = false; result |= googleCalendarItem.Title.ApplyProperty(g => g.Text, outlookCalendarItem.Subject); result |= googleCalendarItem.Content.ApplyProperty(g => g.Content, outlookCalendarItem.Body); if (googleCalendarItem.EventTransparency == null) { googleCalendarItem.EventTransparency = new EventEntry.Transparency(); } result |= googleCalendarItem.EventTransparency.ApplyProperty(g => g.Value, outlookCalendarItem.BusyStatus.GetStatus()); if (googleCalendarItem.EventVisibility == null) { googleCalendarItem.EventVisibility = new EventEntry.Visibility(); } result |= googleCalendarItem.EventVisibility.ApplyProperty(g => g.Value, outlookCalendarItem.Sensitivity.GetStatus()); result |= googleCalendarItem.Locations.Merge(outlookCalendarItem.Location); result |= googleCalendarItem.Participants.Merge(outlookCalendarItem); if (outlookCalendarItem.RecurrenceState == OlRecurrenceState.olApptNotRecurring) { When time = googleCalendarItem.Times.FirstOrInstance(); if (!googleCalendarItem.Times.Any()) { googleCalendarItem.Times.Add(time); } result |= time.ApplyProperty(t => t.AllDay, outlookCalendarItem.AllDayEvent); result |= time.ApplyProperty(t => t.StartTime, outlookCalendarItem.Start); result |= time.ApplyProperty(t => t.EndTime, outlookCalendarItem.End); if (outlookCalendarItem.ReminderSet) { Google.GData.Extensions.Reminder reminder = time.Reminders.FirstOrInstance(t => t.Method == Google.GData.Extensions.Reminder.ReminderMethod.alert); var timespan = TimeSpan.FromMinutes(outlookCalendarItem.ReminderMinutesBeforeStart); result |= reminder.ApplyProperty(r => r.Method, Google.GData.Extensions.Reminder.ReminderMethod.alert); result |= reminder.ApplyProperty(r => r.Minutes, timespan.Minutes); result |= reminder.ApplyProperty(r => r.Hours, timespan.Hours); result |= reminder.ApplyProperty(r => r.Days, timespan.Days); } } else { if (googleCalendarItem.Recurrence == null) { googleCalendarItem.Recurrence = new Recurrence(); } result |= googleCalendarItem.Recurrence.ApplyProperty(r => r.Value, RecurrenceSerializer.Serialize(outlookCalendarItem.GetRecurrencePattern(), outlookCalendarItem.Start, outlookCalendarItem.AllDayEvent)); } return(result); }
private static void UpdateOutlookAppointment(AppointmentItem appointment, string mtg_id, MeetingRequest request, bool reload_pattern = false) { int mrbs_id = -1; int.TryParse(mtg_id.Substring(0, mtg_id.IndexOf(";")), out mrbs_id); // appointment.Subject = request.Description; if ((appointment.RecurrenceState != OlRecurrenceState.olApptMaster) || (appointment.EntryID == "")) { appointment.Start = request.Start; appointment.End = request.End; } appointment.Location = String.Format("{0} - {1}", Database.GetAreaNameByRoomId(request.RoomId), Database.GetRoomNameById(request.RoomId)); if (request.RepeatTypeId > 0) { RecurrencePattern pattern; if (reload_pattern) { appointment.ClearRecurrencePattern(); } pattern = appointment.GetRecurrencePattern(); switch (request.RepeatTypeId) { case 1: pattern.RecurrenceType = OlRecurrenceType.olRecursDaily; pattern.Interval = 1; break; case 2: char[] rev = request.RepeatWeeklyCode.ToCharArray(); pattern.RecurrenceType = OlRecurrenceType.olRecursWeekly; pattern.Interval = request.RepeatNumberOfWeeks; pattern.DayOfWeekMask = (OlDaysOfWeek)Convert.ToInt32(new string(request.RepeatWeeklyCode.ToCharArray().Reverse().ToArray()), 2); break; case 3: if (request.RepeatMonthlyByWeekday) { pattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; pattern.Interval = 1; pattern.DayOfWeekMask = (OlDaysOfWeek)((int)Math.Pow(2, request.RepeatWeekdayOfMonth)); pattern.Instance = request.RepeatWeekdaysOfMonth; } else { pattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; pattern.Interval = 1; pattern.DayOfMonth = request.RepeatDayOfMonth; } break; case 4: pattern.RecurrenceType = OlRecurrenceType.olRecursYearly; break; } pattern.Duration = (request.End - request.Start).Minutes; pattern.EndTime = request.RepeatEnd.Date + request.End.TimeOfDay; pattern.NoEndDate = false; pattern.PatternStartDate = request.Start; pattern.PatternEndDate = request.RepeatEnd + request.End.TimeOfDay; pattern.StartTime = request.Start; } try { appointment.UserProperties.Add("MJ-MRBS-ID", OlUserPropertyType.olText, true, OlFormatText.olFormatTextText); } catch (UnauthorizedAccessException) { //appointment.UserProperties.Add("MJ-MRBS-ID", OlUserPropertyType.olText, true, OlFormatText.olFormatTextText); } appointment.UserProperties["MJ-MRBS-ID"].Value = mtg_id; if (!appointment.Body.Contains("has been linked to a reservation in MRBS.")) { appointment.Body += String.Format("\n\n\n***** This {0} has been linked to a reservation in MRBS. To change the {0} location, you must use the Modify Reservation button in the ribbon. *****", appointment.MeetingStatus == OlMeetingStatus.olNonMeeting ? "appointment" : "meeting"); } appointment.Save(); if (request.RepeatTypeId > 0) { RecurrencePattern pattern = appointment.GetRecurrencePattern(); List <Entry> entries = Database.GetAllEntries(mrbs_id); List <Entry> conflicts = Database.FindConflicts(request, mrbs_id); foreach (Entry conflict in conflicts) { DateTime start_time = Database.UnixTimeStampToDateTime(conflict.start_time); AppointmentItem item = pattern.GetOccurrence(start_time); item.Delete(); } foreach (Entry entry in entries) { try { DateTime start_time = Database.UnixTimeStampToDateTime(entry.start_time); AppointmentItem item = pattern.GetOccurrence(start_time); item.UserProperties.Add("MJ-MRBS-ID", OlUserPropertyType.olText, true, OlFormatText.olFormatTextText); item.UserProperties["MJ-MRBS-ID"].Value = String.Format("{0};{1}", entry.id, entry.ical_uid); item.Save(); } catch { } } appointment.Save(); } }
public void BuildOutlookPattern(Event ev, AppointmentItem ai, out RecurrencePattern oPattern) { if (ev.Recurrence == null) { oPattern = null; return; } Dictionary<String, String> ruleBook = explodeRrule(ev.Recurrence); log.Fine("Building Outlook recurrence pattern"); oPattern = ai.GetRecurrencePattern(); #region RECURRENCE PATTERN //RRULE:FREQ=WEEKLY;UNTIL=20150906T000000Z;BYDAY=SA switch (ruleBook["FREQ"]) { case "DAILY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursDaily; break; } case "WEEKLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursWeekly; // Need to work out dayMask from "BY" pattern // Eg "BYDAY=MO,TU,WE,TH,FR" OlDaysOfWeek dowMask = getDOWmask(ruleBook); if (dowMask != 0) { oPattern.DayOfWeekMask = dowMask; } break; } case "MONTHLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (oPattern.DayOfWeekMask == (OlDaysOfWeek)127 && gInstance == -1 && DateTime.Parse(ev.Start.DateTime ?? ev.Start.Date).Day > 28) { //In Outlook this is simply a monthly recurring oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; oPattern.DayOfWeekMask = 0; } } if (ruleBook.ContainsKey("BYDAY")) { if (ruleBook["BYDAY"].StartsWith("-1")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = 5; oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart("-1".ToCharArray())); } else if ("1,2,3,4".Contains(ruleBook["BYDAY"].Substring(0, 1))) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = Convert.ToInt16(ruleBook["BYDAY"].Substring(0, 1)); oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart(oPattern.Instance.ToString().ToCharArray())); } } break; } case "YEARLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearly; //Google interval is years, Outlook is months if (ruleBook.ContainsKey("INTERVAL")) oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]) * 12; if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (ruleBook.ContainsKey("BYMONTH")) { oPattern.MonthOfYear = Convert.ToInt16(ruleBook["BYMONTH"]); } } break; } } #endregion #region RANGE if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1 && ruleBook["FREQ"] != "YEARLY") oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]); if (ruleBook.ContainsKey("COUNT")) oPattern.Occurrences = Convert.ToInt16(ruleBook["COUNT"]); if (ruleBook.ContainsKey("UNTIL")) oPattern.PatternEndDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMddTHHmmssZ", System.Globalization.CultureInfo.InvariantCulture); #endregion ai = OutlookCalendar.Instance.IOutlook.WindowsTimeZone_set(ai, ev); }
public static Boolean HasExceptions(AppointmentItem ai) { return ai.GetRecurrencePattern().Exceptions.Count != 0; }
public void BuildOutlookPattern(Event ev, AppointmentItem ai, out RecurrencePattern oPattern) { if (ev.Recurrence == null) { oPattern = null; return; } Dictionary <String, String> ruleBook = explodeRrule(ev.Recurrence); log.Fine("Building Outlook recurrence pattern"); oPattern = ai.GetRecurrencePattern(); #region RECURRENCE PATTERN //RRULE:FREQ=WEEKLY;UNTIL=20150906T000000Z;BYDAY=SA switch (ruleBook["FREQ"]) { case "DAILY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursDaily; break; } case "WEEKLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursWeekly; // Need to work out dayMask from "BY" pattern // Eg "BYDAY=MO,TU,WE,TH,FR" OlDaysOfWeek dowMask = getDOWmask(ruleBook); if (dowMask != 0) { oPattern.DayOfWeekMask = dowMask; } break; } case "MONTHLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (oPattern.DayOfWeekMask == (OlDaysOfWeek)127 && gInstance == -1 && DateTime.Parse(ev.Start.DateTime ?? ev.Start.Date).Day > 28) { //In Outlook this is simply a monthly recurring oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; oPattern.DayOfWeekMask = 0; } } if (ruleBook.ContainsKey("BYDAY")) { if (ruleBook["BYDAY"].StartsWith("-1")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = 5; oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart("-1".ToCharArray())); } else if ("1,2,3,4".Contains(ruleBook["BYDAY"].Substring(0, 1))) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = Convert.ToInt16(ruleBook["BYDAY"].Substring(0, 1)); oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart(oPattern.Instance.ToString().ToCharArray())); } } break; } case "YEARLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearly; //Google interval is years, Outlook is months if (ruleBook.ContainsKey("INTERVAL")) { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]) * 12; } if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (ruleBook.ContainsKey("BYMONTH")) { oPattern.MonthOfYear = Convert.ToInt16(ruleBook["BYMONTH"]); } } break; } } #endregion #region RANGE if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1 && ruleBook["FREQ"] != "YEARLY") { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]); } if (ruleBook.ContainsKey("COUNT")) { oPattern.Occurrences = Convert.ToInt16(ruleBook["COUNT"]); } if (ruleBook.ContainsKey("UNTIL")) { if (ruleBook["UNTIL"].Length == 8) { oPattern.PatternEndDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture); } else { if (ruleBook["UNTIL"].ToString().Substring(8) == "T000000Z" && ev.Start.DateTime != null) { oPattern.PatternEndDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMddTHHmmssZ", System.Globalization.CultureInfo.InvariantCulture).AddDays(-1); } else { oPattern.PatternEndDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMddTHHmmssZ", System.Globalization.CultureInfo.InvariantCulture); } } } #endregion ai = OutlookCalendar.Instance.IOutlook.WindowsTimeZone_set(ai, ev); }
private void processOutlookExceptions(AppointmentItem ai, Event ev, Boolean forceCompare) { if (!HasExceptions(ev, checkLocalCacheOnly: true)) return; if (!ai.Saved) ai.Save(); RecurrencePattern oPattern = ai.GetRecurrencePattern(); foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id)) { log.Fine("Found Google exception for " + (gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date)); DateTime oExcpDate = DateTime.Parse(gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date); AppointmentItem newAiExcp = getOutlookInstance(oPattern, oExcpDate); if (newAiExcp == null) continue; if (gExcp.Status != "cancelled") { int itemModified = 0; newAiExcp = OutlookCalendar.Instance.UpdateCalendarEntry(newAiExcp, gExcp, ref itemModified, forceCompare); if (itemModified > 0) newAiExcp.Save(); } else { MainForm.Instance.Logboxout(OutlookCalendar.GetEventSummary(ai) +"\r\nDeleted."); newAiExcp.Delete(); } newAiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(newAiExcp); } if (!ai.Saved) ai.Save(); oPattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(oPattern); }
public static Boolean HasExceptions(AppointmentItem ai) { return(ai.GetRecurrencePattern().Exceptions.Count != 0); }
private List <AppointmentInfo> LoadAllData() { List <AppointmentInfo> allData = new List <AppointmentInfo>(); Log.Write($"allData cleared."); try { foreach (var folder in AllMAPIFolders) { Log.Write($"LoadAllData: {folder.Folder.FullFolderPath}"); try { SetStatus(folder.ToString(), 0); Items items = folder.Folder.Items; if (items == null) { Log.Write($"LoadAllData: Items in folder {folder.Folder.FullFolderPath} is null!"); } items.IncludeRecurrences = true; Log.Write($"LoadAllData: Total {items.Count} items"); int n = 0; int lastProgress = 0; int p = 0; foreach (var item in items) { n += 1; p = 100 * n / items.Count; if (p != lastProgress) { SetStatus(null, p); lastProgress = p; } AppointmentItem ai = item as AppointmentItem; if (ai == null) { continue; } //Log.Write($"LoadAllData: Processing item {n} - {ai.Subject}"); if (ai.Sensitivity != 0) { // Log.Write("Skipping private event"); continue; } if (ai.IsRecurring) { // Log.Write($"LoadAllData: {ai.Subject} is recurring..."); Microsoft.Office.Interop.Outlook.RecurrencePattern rp = ai.GetRecurrencePattern(); Microsoft.Office.Interop.Outlook.AppointmentItem recur = null; for (DateTime cur = monthCalendar1.SelectionStart.AddHours(ai.Start.Hour).AddMinutes(ai.Start.Minute); cur < monthCalendar2.SelectionStart.AddDays(1); cur = cur.AddDays(1)) { try { recur = rp.GetOccurrence(cur); //Log.Write($"LoadAllData: Adding occurence of recurring item {ai.Subject} for date {cur}"); allData.Add(new AppointmentInfo(recur, folder)); } catch { } } } else { if ((ai.Start >= monthCalendar1.SelectionStart) && (ai.End < monthCalendar2.SelectionStart.AddDays(1))) { //Log.Write($"LoadAllData: Adding item {ai.Subject}"); allData.Add(new AppointmentInfo(ai, folder)); } else { //Log.Write($"LoadAllData: {ai.Subject} is out of date frame, continuing..."); continue; } } } } catch (System.Exception ex) { Log.Write($"[EXCEPTION] Nastala výjimka při zpracování složky {folder.Folder.Name}:\r\n {ex.Message}"); MessageBox.Show($"Nastala výjimka při zpracování složky {folder.Folder.Name}:\r\n {ex.Message}", "Výjimka", MessageBoxButtons.OK); } finally { folder.WasProcessed = true; } } } finally { SetStatus("Načteno", -1); } return(allData); }
private SyncResult synchronize() { Console console = Forms.Main.Instance.Console; console.Update("Finding Calendar Entries", Console.Markup.mag_right, newLine: false); List <AppointmentItem> outlookEntries = null; List <Event> googleEntries = null; try { #region Read Outlook items console.Update("Scanning Outlook calendar..."); outlookEntries = OutlookOgcs.Calendar.Instance.GetCalendarEntriesInRange(false); console.Update(outlookEntries.Count + " Outlook calendar entries found.", Console.Markup.sectionEnd, newLine: false); if (CancellationPending) { return(SyncResult.UserCancelled); } #endregion #region Read Google items console.Update("Scanning Google calendar..."); try { googleEntries = GoogleOgcs.Calendar.Instance.GetCalendarEntriesInRange(); } catch (AggregateException agex) { OGCSexception.AnalyseAggregate(agex); } catch (Google.Apis.Auth.OAuth2.Responses.TokenResponseException ex) { OGCSexception.AnalyseTokenResponse(ex, false); return(SyncResult.Fail); } catch (System.Net.Http.HttpRequestException ex) { OGCSexception.Analyse(ex); ex.Data.Add("OGCS", "ERROR: Unable to connect to the Google calendar. Please try again."); throw ex; } catch (System.Exception ex) { OGCSexception.Analyse(ex); ex.Data.Add("OGCS", "ERROR: Unable to connect to the Google calendar."); if (OGCSexception.GetErrorCode(ex) == "0x8013153B") //ex.Message == "A task was canceled." - likely timed out. { ex.Data["OGCS"] += " Please try again."; } throw ex; } Recurrence.Instance.SeparateGoogleExceptions(googleEntries); if (Recurrence.Instance.GoogleExceptions != null && Recurrence.Instance.GoogleExceptions.Count > 0) { console.Update(googleEntries.Count + " Google calendar entries found."); console.Update(Recurrence.Instance.GoogleExceptions.Count + " are exceptions to recurring events.", Console.Markup.sectionEnd, newLine: false); } else { console.Update(googleEntries.Count + " Google calendar entries found.", Console.Markup.sectionEnd, newLine: false); } if (CancellationPending) { return(SyncResult.UserCancelled); } #endregion #region Normalise recurring items in sync window console.Update("Total inc. recurring items spanning sync date range..."); //Outlook returns recurring items that span the sync date range, Google doesn't //So check for master Outlook items occurring before sync date range, and retrieve Google equivalent for (int o = outlookEntries.Count - 1; o >= 0; o--) { log.Fine("Processing " + (o + 1) + "/" + outlookEntries.Count); AppointmentItem ai = null; try { if (outlookEntries[o] is AppointmentItem) { ai = outlookEntries[o]; } else if (outlookEntries[o] is MeetingItem) { log.Info("Calendar object appears to be a MeetingItem, so retrieving associated AppointmentItem."); MeetingItem mi = outlookEntries[o] as MeetingItem; outlookEntries[o] = mi.GetAssociatedAppointment(false); ai = outlookEntries[o]; } else { log.Warn("Unknown calendar object type - cannot sync it."); skipCorruptedItem(ref outlookEntries, outlookEntries[o], "Unknown object type."); outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]); continue; } } catch (System.Exception ex) { log.Warn("Encountered error casting calendar object to AppointmentItem - cannot sync it."); log.Debug(ex.Message); skipCorruptedItem(ref outlookEntries, outlookEntries[o], ex.Message); outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]); ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai); continue; } //Now let's check there's a start/end date - sometimes it can be missing, even though this shouldn't be possible!! String entryID; try { entryID = outlookEntries[o].EntryID; DateTime checkDates = ai.Start; checkDates = ai.End; } catch (System.Exception ex) { log.Warn("Calendar item does not have a proper date range - cannot sync it."); log.Debug(ex.Message); skipCorruptedItem(ref outlookEntries, outlookEntries[o], ex.Message); outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]); ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai); continue; } if (ai.IsRecurring && ai.Start.Date < Settings.Instance.SyncStart && ai.End.Date < Settings.Instance.SyncStart) { //We won't bother getting Google master event if appointment is yearly reoccurring in a month outside of sync range //Otherwise, every sync, the master event will have to be retrieved, compared, concluded nothing's changed (probably) = waste of API calls RecurrencePattern oPattern = ai.GetRecurrencePattern(); try { if (oPattern.RecurrenceType.ToString().Contains("Year")) { log.Fine("It's an annual event."); Boolean monthInSyncRange = false; DateTime monthMarker = Settings.Instance.SyncStart; while (Convert.ToInt32(monthMarker.ToString("yyyyMM")) <= Convert.ToInt32(Settings.Instance.SyncEnd.ToString("yyyyMM")) && !monthInSyncRange) { if (monthMarker.Month == ai.Start.Month) { monthInSyncRange = true; } monthMarker = monthMarker.AddMonths(1); } log.Fine("Found it to be " + (monthInSyncRange ? "inside" : "outside") + " sync range."); if (!monthInSyncRange) { outlookEntries.Remove(ai); log.Fine("Removed."); continue; } } Event masterEv = Recurrence.Instance.GetGoogleMasterEvent(ai); if (masterEv != null && masterEv.Status != "cancelled") { Event cachedEv = googleEntries.Find(x => x.Id == masterEv.Id); if (cachedEv == null) { googleEntries.Add(masterEv); } else { if (masterEv.Updated > cachedEv.Updated) { log.Debug("Refreshing cache for this Event."); googleEntries.Remove(cachedEv); googleEntries.Add(masterEv); } } } } catch (System.Exception ex) { console.Update("Failed to retrieve master for Google recurring event outside of sync range.", Console.Markup.error); throw ex; } finally { oPattern = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(oPattern); } } //Completely dereference object and retrieve afresh (due to GetRecurrencePattern earlier) ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai); OutlookOgcs.Calendar.Instance.IOutlook.GetAppointmentByID(entryID, out ai); outlookEntries[o] = ai; } console.Update("Outlook " + outlookEntries.Count + ", Google " + googleEntries.Count); GoogleOgcs.Calendar.ExportToCSV("Outputting all Events.", "google_events.csv", googleEntries); OutlookOgcs.Calendar.ExportToCSV("Outputting all Appointments.", "outlook_appointments.csv", outlookEntries); if (CancellationPending) { return(SyncResult.UserCancelled); } #endregion Boolean success = true; String bubbleText = ""; if (Settings.Instance.SyncDirection != Direction.GoogleToOutlook) { success = outlookToGoogle(outlookEntries, googleEntries, ref bubbleText); if (CancellationPending) { return(SyncResult.UserCancelled); } } if (!success) { return(SyncResult.Fail); } if (Settings.Instance.SyncDirection != Direction.OutlookToGoogle) { if (bubbleText != "") { bubbleText += "\r\n"; } success = googleToOutlook(googleEntries, outlookEntries, ref bubbleText); if (CancellationPending) { return(SyncResult.UserCancelled); } } if (bubbleText != "") { Forms.Main.Instance.NotificationTray.ShowBubbleInfo(bubbleText); } return(SyncResult.OK); } finally { for (int o = outlookEntries.Count() - 1; o >= 0; o--) { outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]); outlookEntries.RemoveAt(o); } } }
public AppointmentItem UpdateCalendarEntry(AppointmentItem ai, Event ev, ref int itemModified, Boolean forceCompare = false) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) //The exception child objects might have changed { log.Debug("Processing recurring master appointment."); } else { if (!forceCompare) //Needed if the exception has just been created, but now needs updating { if (Settings.Instance.SyncDirection != SyncDirection.Bidirectional) { if (DateTime.Parse(GoogleCalendar.GoogleTimeFrom(ai.LastModificationTime)) > DateTime.Parse(ev.Updated)) { return(null); } } else { if (GoogleCalendar.OGCSlastModified(ev).AddSeconds(5) >= DateTime.Parse(ev.Updated)) { //Google last modified by OGCS return(null); } if (DateTime.Parse(GoogleCalendar.GoogleTimeFrom(ai.LastModificationTime)) > DateTime.Parse(ev.Updated)) { return(null); } } } } String evSummary = GoogleCalendar.GetEventSummary(ev); log.Debug("Processing >> " + evSummary); System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.AppendLine(evSummary); RecurrencePattern oPattern = (ai.RecurrenceState == OlRecurrenceState.olApptNotRecurring) ? null : ai.GetRecurrencePattern(); if (ev.Start.Date != null) { if (ai.RecurrenceState != OlRecurrenceState.olApptMaster) { ai.AllDayEvent = true; } if (MainForm.CompareAttribute("Start time", SyncDirection.GoogleToOutlook, ev.Start.Date, ai.Start.ToString("yyyy-MM-dd"), sb, ref itemModified)) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { oPattern.PatternStartDate = DateTime.Parse(ev.Start.Date); } else { ai.Start = DateTime.Parse(ev.Start.Date); } } if (MainForm.CompareAttribute("End time", SyncDirection.GoogleToOutlook, ev.End.Date, ai.End.ToString("yyyy-MM-dd"), sb, ref itemModified)) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { oPattern.PatternEndDate = DateTime.Parse(ev.End.Date); } else { ai.End = DateTime.Parse(ev.End.Date); } } } else { if (ai.RecurrenceState != OlRecurrenceState.olApptMaster) { ai.AllDayEvent = false; } if (MainForm.CompareAttribute("Start time", SyncDirection.GoogleToOutlook, GoogleCalendar.GoogleTimeFrom(DateTime.Parse(ev.Start.DateTime)), GoogleCalendar.GoogleTimeFrom(ai.Start), sb, ref itemModified)) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { oPattern.PatternStartDate = DateTime.Parse(ev.Start.DateTime); } else { ai.Start = DateTime.Parse(ev.Start.DateTime); } } if (MainForm.CompareAttribute("End time", SyncDirection.GoogleToOutlook, GoogleCalendar.GoogleTimeFrom(DateTime.Parse(ev.End.DateTime)), GoogleCalendar.GoogleTimeFrom(ai.End), sb, ref itemModified)) { if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { oPattern.PatternEndDate = DateTime.Parse(ev.End.DateTime); } else { ai.End = DateTime.Parse(ev.End.DateTime); } } } oPattern = (RecurrencePattern)ReleaseObject(oPattern); if (ai.RecurrenceState == OlRecurrenceState.olApptMaster) { if (ev.Recurrence == null || ev.RecurringEventId != null) { log.Debug("Converting to non-recurring events."); ai.ClearRecurrencePattern(); itemModified++; } else { Recurrence.Instance.CompareOutlookPattern(ev, ai, sb, ref itemModified); Recurrence.Instance.UpdateOutlookExceptions(ai, ev); } } else if (ai.RecurrenceState == OlRecurrenceState.olApptNotRecurring) { if (!ai.IsRecurring && ev.Recurrence != null && ev.RecurringEventId == null) { log.Debug("Converting to recurring appointment."); Recurrence.Instance.CreateOutlookExceptions(ai, ev); itemModified++; } } String summaryObfuscated = Obfuscate.ApplyRegex(ev.Summary, SyncDirection.GoogleToOutlook); if (MainForm.CompareAttribute("Subject", SyncDirection.GoogleToOutlook, summaryObfuscated, ai.Subject, sb, ref itemModified)) { ai.Subject = summaryObfuscated; } if (!Settings.Instance.AddDescription) { ev.Description = ""; } if (Settings.Instance.SyncDirection == SyncDirection.GoogleToOutlook || !Settings.Instance.AddDescription_OnlyToGoogle) { if (MainForm.CompareAttribute("Description", SyncDirection.GoogleToOutlook, ev.Description, ai.Body, sb, ref itemModified)) { ai.Body = ev.Description; } } if (MainForm.CompareAttribute("Location", SyncDirection.GoogleToOutlook, ev.Location, ai.Location, sb, ref itemModified)) { ai.Location = ev.Location; } String oPrivacy = (ai.Sensitivity == OlSensitivity.olNormal) ? "default" : "private"; String gPrivacy = (ev.Visibility == null ? "default" : ev.Visibility); if (MainForm.CompareAttribute("Private", SyncDirection.GoogleToOutlook, gPrivacy, oPrivacy, sb, ref itemModified)) { ai.Sensitivity = (ev.Visibility != null && ev.Visibility == "private") ? OlSensitivity.olPrivate : OlSensitivity.olNormal; } String oFreeBusy = (ai.BusyStatus == OlBusyStatus.olFree) ? "transparent" : "opaque"; String gFreeBusy = (ev.Transparency == null ? "opaque" : ev.Transparency); if (MainForm.CompareAttribute("Free/Busy", SyncDirection.GoogleToOutlook, gFreeBusy, oFreeBusy, sb, ref itemModified)) { ai.BusyStatus = (ev.Transparency != null && ev.Transparency == "transparent") ? OlBusyStatus.olFree : OlBusyStatus.olBusy; } if (Settings.Instance.AddAttendees) { if (ev.Description != null && ev.Description.Contains("===--- Attendees ---===")) { //Protect against <v1.2.4 where attendees were stored as text log.Info("This event still has attendee information in the description - cannot sync them."); } else if (Settings.Instance.SyncDirection == SyncDirection.Bidirectional && ev.Attendees != null && ev.Attendees.Count == 0 && ai.Recipients.Count > 150) { log.Info("Attendees not being synced - there are too many (" + ai.Recipients.Count + ") for Google."); } else { //Build a list of Outlook attendees. Any remaining at the end of the diff must be deleted. List <Recipient> removeRecipient = new List <Recipient>(); if (ai.Recipients != null) { foreach (Recipient recipient in ai.Recipients) { if (recipient.Name != ai.Organizer) { removeRecipient.Add(recipient); } } } if (ev.Attendees != null) { for (int g = ev.Attendees.Count - 1; g >= 0; g--) { bool foundRecipient = false; EventAttendee attendee = ev.Attendees[g]; foreach (Recipient recipient in ai.Recipients) { if (!recipient.Resolved) { recipient.Resolve(); } String recipientSMTP = IOutlook.GetRecipientEmail(recipient); if (recipientSMTP.ToLower() == attendee.Email.ToLower()) { foundRecipient = true; removeRecipient.Remove(recipient); //Optional attendee bool oOptional = (ai.OptionalAttendees != null && ai.OptionalAttendees.Contains(attendee.DisplayName ?? attendee.Email)); bool gOptional = (attendee.Optional == null) ? false : (bool)attendee.Optional; if (MainForm.CompareAttribute("Recipient " + recipient.Name + " - Optional Check", SyncDirection.GoogleToOutlook, gOptional, oOptional, sb, ref itemModified)) { if (gOptional) { recipient.Type = (int)OlMeetingRecipientType.olOptional; } else { recipient.Type = (int)OlMeetingRecipientType.olRequired; } } //Response is readonly in Outlook :( break; } } if (!foundRecipient && (attendee.DisplayName != ai.Organizer)) //Attendee in Google is owner in Outlook, so can't also be added as a recipient) { sb.AppendLine("Recipient added: " + (attendee.DisplayName ?? attendee.Email)); createRecipient(attendee, ai); itemModified++; } } } foreach (Recipient recipient in removeRecipient) { sb.AppendLine("Recipient removed: " + recipient.Name); recipient.Delete(); itemModified++; } } } //Reminders if (Settings.Instance.AddReminders) { if (ev.Reminders.Overrides != null) { //Find the popup reminder in Google for (int r = ev.Reminders.Overrides.Count - 1; r >= 0; r--) { EventReminder reminder = ev.Reminders.Overrides[r]; if (reminder.Method == "popup") { if (ai.ReminderSet) { if (MainForm.CompareAttribute("Reminder", SyncDirection.GoogleToOutlook, reminder.Minutes.ToString(), ai.ReminderMinutesBeforeStart.ToString(), sb, ref itemModified)) { ai.ReminderMinutesBeforeStart = (int)reminder.Minutes; } } else { sb.AppendLine("Reminder: nothing => " + reminder.Minutes); ai.ReminderSet = true; ai.ReminderMinutesBeforeStart = (int)reminder.Minutes; itemModified++; } //if Outlook reminders set } //if google reminder found } //foreach reminder } else //no google reminders set { if (ai.ReminderSet) { sb.AppendLine("Reminder: " + ai.ReminderMinutesBeforeStart + " => removed"); ai.ReminderSet = false; itemModified++; } } } if (itemModified > 0) { MainForm.Instance.Logboxout(sb.ToString(), false, verbose: true); MainForm.Instance.Logboxout(itemModified + " attributes updated.", verbose: true); System.Windows.Forms.Application.DoEvents(); } return(ai); }
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 void processOutlookExceptions(AppointmentItem ai, Event ev, Boolean forceCompare) { if (!HasExceptions(ev, checkLocalCacheOnly: true)) return; if (!ai.Saved) ai.Save(); RecurrencePattern oPattern = ai.GetRecurrencePattern(); foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id)) { log.Fine("Found Google exception for " + (gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date)); DateTime oExcpDate = DateTime.Parse(gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date); AppointmentItem newAiExcp = getOutlookInstance(oPattern, oExcpDate); if (newAiExcp == null) continue; if (gExcp.Status != "cancelled") { int itemModified = 0; newAiExcp = OutlookCalendar.Instance.UpdateCalendarEntry(newAiExcp, gExcp, ref itemModified, forceCompare); if (itemModified > 0) { try { newAiExcp.Save(); } catch (System.Exception ex) { log.Warn(ex.Message); if (ex.Message == "Cannot save this item.") { MainForm.Instance.Logboxout("Uh oh! Outlook wasn't able to save this recurrence exception! " + "You may have two occurences on the same day, which it doesn't allow."); } } } } else { MainForm.Instance.Logboxout(OutlookCalendar.GetEventSummary(ai) + "\r\nDeleted."); newAiExcp.Delete(); } newAiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(newAiExcp); } if (!ai.Saved) ai.Save(); oPattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(oPattern); }
public static void UpdateGoogleExceptions(AppointmentItem ai, Event ev) { if (ai.IsRecurring) { RecurrencePattern recurrence = ai.GetRecurrencePattern(); if (recurrence.Exceptions.Count > 0) { log.Debug(OutlookCalendar.GetEventSummary(ai)); log.Debug("This is a recurring appointment with " + recurrence.Exceptions.Count + " exceptions that will now be iteratively compared."); foreach (Microsoft.Office.Interop.Outlook.Exception oExcp in recurrence.Exceptions) { 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 = oIsDeleted ? oExcp.OriginalDate : oExcp.AppointmentItem.Start; 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(oExcp, ev.RecurringEventId ?? ev.Id, OutlookCalendar.Instance.IOutlook.GetGlobalApptID(ai)); 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; } try { GoogleCalendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, gExcp, ref excp_itemModified); } catch (System.Exception ex) { if (oIsDeleted) { if (gExcp.Status != "cancelled") { gExcp.Status = "cancelled"; excp_itemModified++; } } else { log.Error(ex.Message); log.Error(ex.StackTrace); recurrence = (RecurrencePattern)OutlookCalendar.ReleaseObject(recurrence); throw ex; } } if (excp_itemModified > 0) { try { GoogleCalendar.Instance.UpdateCalendarEntry_save(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."); } } finally { recurrence = (RecurrencePattern)OutlookCalendar.ReleaseObject(recurrence); } } } else { log.Debug("No matching Google Event recurrence found."); if (oIsDeleted) log.Debug("The Outlook appointment is deleted, so not a problem."); } } } recurrence = (RecurrencePattern)OutlookCalendar.ReleaseObject(recurrence); } }
/// <summary> /// Merges the with. /// </summary> /// <param name="googleCalendarItem">The google calendar item.</param> /// <param name="outlookCalendarItem">The outlook calendar item.</param> /// <returns>True if Changed.</returns> public static bool MergeWith(this EventEntry googleCalendarItem, AppointmentItem outlookCalendarItem) { var result = false; result |= googleCalendarItem.Title.ApplyProperty(g => g.Text, outlookCalendarItem.Subject); result |= googleCalendarItem.Content.ApplyProperty(g => g.Content, outlookCalendarItem.Body); if (googleCalendarItem.EventTransparency == null) googleCalendarItem.EventTransparency = new EventEntry.Transparency(); result |= googleCalendarItem.EventTransparency.ApplyProperty(g => g.Value, outlookCalendarItem.BusyStatus.GetStatus()); if (googleCalendarItem.EventVisibility == null) googleCalendarItem.EventVisibility = new EventEntry.Visibility(); result |= googleCalendarItem.EventVisibility.ApplyProperty(g => g.Value, outlookCalendarItem.Sensitivity.GetStatus()); result |= googleCalendarItem.Locations.Merge(outlookCalendarItem.Location); result |= googleCalendarItem.Participants.Merge(outlookCalendarItem); if (outlookCalendarItem.RecurrenceState == OlRecurrenceState.olApptNotRecurring) { When time = googleCalendarItem.Times.FirstOrInstance(); if (!googleCalendarItem.Times.Any()) googleCalendarItem.Times.Add(time); result |= time.ApplyProperty(t => t.AllDay, outlookCalendarItem.AllDayEvent); result |= time.ApplyProperty(t => t.StartTime, outlookCalendarItem.Start); result |= time.ApplyProperty(t => t.EndTime, outlookCalendarItem.End); if (outlookCalendarItem.ReminderSet) { Google.GData.Extensions.Reminder reminder = time.Reminders.FirstOrInstance(t => t.Method == Google.GData.Extensions.Reminder.ReminderMethod.alert); var timespan = TimeSpan.FromMinutes(outlookCalendarItem.ReminderMinutesBeforeStart); result |= reminder.ApplyProperty(r => r.Method, Google.GData.Extensions.Reminder.ReminderMethod.alert); result |= reminder.ApplyProperty(r => r.Minutes, timespan.Minutes); result |= reminder.ApplyProperty(r => r.Hours, timespan.Hours); result |= reminder.ApplyProperty(r => r.Days, timespan.Days); } } else { if (googleCalendarItem.Recurrence == null) googleCalendarItem.Recurrence = new Recurrence(); result |= googleCalendarItem.Recurrence.ApplyProperty(r => r.Value, RecurrenceSerializer.Serialize(outlookCalendarItem.GetRecurrencePattern(), outlookCalendarItem.Start, outlookCalendarItem.AllDayEvent)); } return result; }