Как узнать, какое возникновение повторяющегося события было удалено?

У моего приложения есть подписка на календарь office365 под названием ConferenceRoom. Поэтому, когда событие будет создано / изменено / удалено, серверы Office365 отправят в мое приложение уведомление о том, что что-то из этих трех произошло.

В календаре я создаю повторяющееся мероприятие для каждого понедельника (через браузер). После этого мое приложение получает уведомление с ChangeType: Created и вот повторяющаяся часть события этого уведомления:

Recurrence:
 { Pattern:
    { Type: 'Weekly',
      Interval: 1,
      Month: 0,
      DayOfMonth: 0,
      DaysOfWeek: [Object],
      FirstDayOfWeek: 'Sunday',
      Index: 'First' },
   Range:
    { Type: 'NoEnd',
      StartDate: '2016-09-12',
      EndDate: '0001-01-01',
      RecurrenceTimeZone: 'FLE Standard Time',
      NumberOfOccurrences: 0 } },

И все данные этого события (идентификатор получен из уведомления):

{ '@odata.context': 'https://outlook.office.com/api/v2.0/$metadata#Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46%40ea38f869-d755-40c7-9c95-e6277325b7ae\')/Events/$entity',
  '@odata.id': 'https://outlook.office.com/api/v2.0/Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46@ea38f869-d755-40c7-9c95-e6277325b7ae\')/Events(\'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAFZAABi3Yqq_sjMSYdHHux_aUXFAAAMNRbUAAA=\')',
  '@odata.etag': 'W/"Yt2KqvrIzEmHRx7sfmlFxQAADDdF3g=="',
  Id: 'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAFZAABi3Yqq_sjMSYdHHux_aUXFAAAMNRbUAAA=',
  CreatedDateTime: '2016-09-13T03:55:43.5305953-02:00',
  LastModifiedDateTime: '2016-09-13T03:55:43.5476101-02:00',
  ChangeKey: 'Yt2KqvrIzEmHRx7sfmlFxQAADDdF3g==',
  Categories: [],
  OriginalStartTimeZone: 'FLE Standard Time',
  OriginalEndTimeZone: 'FLE Standard Time',
  ResponseStatus: { Response: 'Organizer', Time: '0001-01-01T00:00:00Z' },
  iCalUId: '040000008200E00074C5B7101A82E00800000000F9B6FC76830DD2010000000000000000100000005D7D5B0B8D1EA84E86C8AEE4014697CA',
  ReminderMinutesBeforeStart: 15,
  IsReminderOn: true,
  HasAttachments: false,
  Subject: 'standup meeting',
  Body:
   { ContentType: 'HTML',
     Content: '<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n<meta content="text/html; charset=us-ascii">\r\n<style type="text/css" style="display:none">\r\n<!--\r\np\r\n\t{margin-top:0;\r\n\tmargin-bottom:0}\r\n-->\r\n</style>\r\n</head>\r\n<body dir="ltr">\r\n<div id="divtagdefaultwrapper" style="font-size:12pt; color:#000000; background-color:#FFFFFF; font-family:Calibri,Arial,Helvetica,sans-serif">\r\n<p><br>\r\n</p>\r\n</div>\r\n</body>\r\n</html>\r\n' },
  BodyPreview: '',
  Importance: 'Normal',
  Sensitivity: 'Normal',
  Start:
   { DateTime: '2016-09-12T03:00:00.0000000',
     TimeZone: 'Etc/GMT+2' },
  End:
   { DateTime: '2016-09-12T03:30:00.0000000',
     TimeZone: 'Etc/GMT+2' },
  Location: { DisplayName: '', Address: {}, Coordinates: {} },
  IsAllDay: false,
  IsCancelled: false,
  IsOrganizer: true,
  Recurrence:
   { Pattern:
      { Type: 'Weekly',
        Interval: 1,
        Month: 0,
        DayOfMonth: 0,
        DaysOfWeek: [ 'Monday' ],
        FirstDayOfWeek: 'Sunday',
        Index: 'First' },
     Range:
      { Type: 'NoEnd',
        StartDate: '2016-09-12',
        EndDate: '0001-01-01',
        RecurrenceTimeZone: 'FLE Standard Time',
        NumberOfOccurrences: 0 } },
  ResponseRequested: false,
  SeriesMasterId: null,
  ShowAs: 'Busy',
  Type: 'SeriesMaster',
  Attendees: [],
  Organizer:
   { EmailAddress:
      { Name: 'John Smith',
        Address: 'john.smith@sample.onmicrosoft.com' } },
  WebLink: 'https://outlook.office365.com/owa/?ItemID=AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT%2FM8JoV8TI5B1BhmG2N%2BBwBi3Yqq%2BsjMSYdHHux%2BaUXFAAAAAAFZAABi3Yqq%2BsjMSYdHHux%2BaUXFAAAMNRbUAAA%3D&exvsurl=1&viewModel=ICalendarItemDetailsViewModelFactory',
  'Calendar@odata.associationLink': 'https://outlook.office.com/api/v2.0/Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46@ea38f869-d755-40c7-9c95-e6277325b7ae\')/Calendars(\'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAEGAABi3Yqq_sjMSYdHHux_aUXFAAAAAA0jAAA=\')/$ref',
  'Calendar@odata.navigationLink': 'https://outlook.office.com/api/v2.0/Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46@ea38f869-d755-40c7-9c95-e6277325b7ae\')/Calendars(\'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAEGAABi3Yqq_sjMSYdHHux_aUXFAAAAAA0jAAA=\')' }

Это вполне нормально. Проблема возникает, когда я удаляю одно вхождение этого события в календаре. Мое приложение получает уведомление с ChangeType: Updated и тело этого уведомления в значительной степени совпадает с тем, когда событие было создано. Нет информации о том, на какую дату это событие было отменено.

Данные о событии, когда eventId получил от ChangeType: Updated уведомление:

{ '@odata.context': 'https://outlook.office.com/api/v2.0/$metadata#Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46%40ea38f869-d755-40c7-9c95-e6277325b7ae\')/Events/$entity',
  '@odata.id': 'https://outlook.office.com/api/v2.0/Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46@ea38f869-d755-40c7-9c95-e6277325b7ae\')/Events(\'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAFZAABi3Yqq_sjMSYdHHux_aUXFAAAMNRbUAAA=\')',
  '@odata.etag': 'W/"Yt2KqvrIzEmHRx7sfmlFxQAADDdF3w=="',
  Id: 'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAFZAABi3Yqq_sjMSYdHHux_aUXFAAAMNRbUAAA=',
  CreatedDateTime: '2016-09-13T03:55:43.5305953-02:00',
  LastModifiedDateTime: '2016-09-13T03:57:48.2229052-02:00',
  ChangeKey: 'Yt2KqvrIzEmHRx7sfmlFxQAADDdF3w==',
  Categories: [],
  OriginalStartTimeZone: 'FLE Standard Time',
  OriginalEndTimeZone: 'FLE Standard Time',
  ResponseStatus: { Response: 'Organizer', Time: '0001-01-01T00:00:00Z' },
  iCalUId: '040000008200E00074C5B7101A82E00800000000F9B6FC76830DD2010000000000000000100000005D7D5B0B8D1EA84E86C8AEE4014697CA',
  ReminderMinutesBeforeStart: 15,
  IsReminderOn: true,
  HasAttachments: false,
  Subject: 'standup meeting',
  Body:
   { ContentType: 'HTML',
     Content: '<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n<meta content="text/html; charset=us-ascii">\r\n<style type="text/css" style="display:none">\r\n<!--\r\np\r\n\t{margin-top:0;\r\n\tmargin-bottom:0}\r\n-->\r\n</style>\r\n</head>\r\n<body dir="ltr">\r\n<div id="divtagdefaultwrapper" style="font-size:12pt; color:#000000; background-color:#FFFFFF; font-family:Calibri,Arial,Helvetica,sans-serif">\r\n<p><br>\r\n</p>\r\n</div>\r\n</body>\r\n</html>\r\n' },
  BodyPreview: '',
  Importance: 'Normal',
  Sensitivity: 'Normal',
  Start:
   { DateTime: '2016-09-12T03:00:00.0000000',
     TimeZone: 'Etc/GMT+2' },
  End:
   { DateTime: '2016-09-12T03:30:00.0000000',
     TimeZone: 'Etc/GMT+2' },
  Location: { DisplayName: '', Address: {}, Coordinates: {} },
  IsAllDay: false,
  IsCancelled: false,
  IsOrganizer: true,
  Recurrence:
   { Pattern:
      { Type: 'Weekly',
        Interval: 1,
        Month: 0,
        DayOfMonth: 0,
        DaysOfWeek: [ 'Monday' ],
        FirstDayOfWeek: 'Sunday',
        Index: 'First' },
     Range:
      { Type: 'NoEnd',
        StartDate: '2016-09-12',
        EndDate: '0001-01-01',
        RecurrenceTimeZone: 'FLE Standard Time',
        NumberOfOccurrences: 0 } },
  ResponseRequested: false,
  SeriesMasterId: null,
  ShowAs: 'Busy',
  Type: 'SeriesMaster',
  Attendees: [],
  Organizer:
   { EmailAddress:
      { Name: 'John Smith',
        Address: 'john.smith@sample.onmicrosoft.com' } },
  WebLink: 'https://outlook.office365.com/owa/?ItemID=AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT%2FM8JoV8TI5B1BhmG2N%2BBwBi3Yqq%2BsjMSYdHHux%2BaUXFAAAAAAFZAABi3Yqq%2BsjMSYdHHux%2BaUXFAAAMNRbUAAA%3D&exvsurl=1&viewModel=ICalendarItemDetailsViewModelFactory',
  'Calendar@odata.associationLink': 'https://outlook.office.com/api/v2.0/Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46@ea38f869-d755-40c7-9c95-e6277325b7ae\')/Calendars(\'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAEGAABi3Yqq_sjMSYdHHux_aUXFAAAAAA0jAAA=\')/$ref',
  'Calendar@odata.navigationLink': 'https://outlook.office.com/api/v2.0/Users(\'2ce6a929-0b04-40fb-9c73-d812370e0d46@ea38f869-d755-40c7-9c95-e6277325b7ae\')/Calendars(\'AAMkADg5YzZmNTViLWM3NjEtNGI4Mi04Yjg4LTkyOWQ4NjFjM2QzOABGAAAAAAATT-M8JoV8TI5B1BhmG2N_BwBi3Yqq_sjMSYdHHux_aUXFAAAAAAEGAABi3Yqq_sjMSYdHHux_aUXFAAAAAA0jAAA=\')' }

Вот изображение, чтобы прояснить, что именно я сделал в календаре: введите описание изображения здесь

Можете ли вы сказать мне, как узнать, какое событие этого события было удалено?

Это кажется тупиком, поэтому любая помощь будет принята с благодарностью.

Только для справки: повторяющееся событие имеет только один идентификатор события, а удаление повторяющегося события НЕ отправляет уведомление с ChangeType: DELETED

1 ответ

К сожалению, API в настоящее время не позволяет узнать, какое вхождение было удалено. Однако при удалении одного экземпляра оно вызывает обновление SeriesMaster. Когда появится это обновление, вам нужно будет рассчитать, когда все встречи должны состояться, а затем извлечь все вхождения. После итерации по вхождениям вы можете определить, какое вхождение было удалено из ваших предыдущих вычислений. Поскольку ваша встреча повторяется еженедельно, вам нужно ограничить время, с которого вы запрашиваете события.

Если вы используете Python, я настоятельно рекомендую пакет dateutil, который поставляется с удобным классом rrule: https://dateutil.readthedocs.io/en/stable/rrule.html

Другие вопросы по тегам