/// <summary> /// Use this to get events for a given user. /// </summary> /// <param name="limit">Limits the number of events returned (defaults to 500).</param> /// <param name="streamType">Restricts the types of events returned: all returns all events; changes returns events that may cause file tree changes such as file updates or collaborations; sync returns events that may cause file tree changes only for synced folders.</param> /// <param name="streamPosition">The location in the event stream from which you want to start receiving events. You can specify the special value 'now' to get 0 events and the latest stream_position value. Defaults to 'now'.</param> /// <param name="dedupeEvents">Whether or not to automatically de-duplicate events as they are received. Defaults to true.</param> /// <returns></returns> public async Task <BoxEventCollection <BoxEnterpriseEvent> > UserEventsAsync(int limit = 500, UserEventsStreamType streamType = UserEventsStreamType.all, string streamPosition = "now", bool dedupeEvents = true) { BoxRequest request = new BoxRequest(_config.EventsUri) .Param("stream_type", streamType.ToString()) .Param("limit", limit.ToString()) .Param("stream_position", streamPosition); IBoxResponse <BoxEventCollection <BoxEnterpriseEvent> > response = await ToResponseAsync <BoxEventCollection <BoxEnterpriseEvent> >(request).ConfigureAwait(false); if (dedupeEvents) { List <BoxEnterpriseEvent> filteredEvents = new List <BoxEnterpriseEvent>(); foreach (var e in response.ResponseObject.Entries) { bool notUsed = true; if (!USER_EVENTS_DEDUPE_CACHE.TryGetValue(e.EventId, out notUsed)) { USER_EVENTS_DEDUPE_CACHE.Add(e.EventId, true); filteredEvents.Add(e); } } response.ResponseObject.Entries = filteredEvents; } return(response.ResponseObject); }
/// <summary> /// Use this to get events for a given user. /// </summary> /// <param name="limit">Limits the number of events returned (defaults to 500).</param> /// <param name="streamType">Restricts the types of events returned: all returns all events; changes returns events that may cause file tree changes such as file updates or collaborations; sync returns events that may cause file tree changes only for synced folders.</param> /// <param name="streamPosition">The location in the event stream from which you want to start receiving events. You can specify the special value 'now' to get 0 events and the latest stream_position value. Defaults to 'now'.</param> /// <param name="dedupeEvents">Whether or not to automatically de-duplicate events as they are received. Defaults to true.</param> /// <returns></returns> public async Task<BoxEventCollection<BoxEnterpriseEvent>> UserEventsAsync(int limit = 500, UserEventsStreamType streamType = UserEventsStreamType.all, string streamPosition = "now", bool dedupeEvents = true) { BoxRequest request = new BoxRequest(_config.EventsUri) .Param("stream_type", streamType.ToString()) .Param("limit", limit.ToString()) .Param("stream_position", streamPosition); IBoxResponse<BoxEventCollection<BoxEnterpriseEvent>> response = await ToResponseAsync<BoxEventCollection<BoxEnterpriseEvent>>(request).ConfigureAwait(false); if (dedupeEvents) { List<BoxEnterpriseEvent> filteredEvents = new List<BoxEnterpriseEvent>(); foreach (var e in response.ResponseObject.Entries) { bool notUsed = true; if (!USER_EVENTS_DEDUPE_CACHE.TryGetValue(e.EventId, out notUsed)) { USER_EVENTS_DEDUPE_CACHE.Add(e.EventId, true); filteredEvents.Add(e); } } response.ResponseObject.Entries = filteredEvents; } return response.ResponseObject; }
/// <summary> /// Used to get real-time notification of activity in a Box account. /// </summary> /// <param name="streamPosition">The location in the event stream from which you want to start receiving events.</param> /// <param name="newEventsCallback">Method to invoke when new events are received.</param> /// <param name="cancellationToken">Used to request that the long polling process terminate.</param> /// <param name="streamType">Restricts the types of events returned: all returns all events; changes returns events that may cause file tree changes such as file updates or collaborations; sync returns events that may cause file tree changes only for synced folders.</param> /// <param name="dedupeEvents">Whether or not to automatically de-duplicate events as they are received. Defaults to true.</param> /// <param name="retryTimeoutOverride">Used to override the retry timeout value returned from the long polling OPTIONS request.</param> /// <returns></returns> public async Task LongPollUserEvents(string streamPosition, Action <BoxEventCollection <BoxEnterpriseEvent> > newEventsCallback, CancellationToken cancellationToken, UserEventsStreamType streamType = UserEventsStreamType.all, bool dedupeEvents = true, int?retryTimeoutOverride = null) { const string NEW_CHANGE_MESSAGE = "new_change"; string nextStreamPosition = streamPosition; while (true) { BoxRequest optionsRequest = new BoxRequest(_config.EventsUri) .Param("stream_type", streamType.ToString()) .Method(RequestMethod.Options); IBoxResponse <BoxLongPollInfoCollection <BoxLongPollInfo> > optionsResponse = await ToResponseAsync <BoxLongPollInfoCollection <BoxLongPollInfo> >(optionsRequest).ConfigureAwait(false); var longPollInfo = optionsResponse.ResponseObject.Entries[0]; var numRetries = Int32.Parse(longPollInfo.MaxRetries); bool pollAgain = true; do { if (cancellationToken.IsCancellationRequested) { cancellationToken.ThrowIfCancellationRequested(); } try { var timeout = retryTimeoutOverride.HasValue ? retryTimeoutOverride.Value : longPollInfo.RetryTimeout; BoxRequest pollRequest = new BoxRequest(longPollInfo.Url) { Timeout = TimeSpan.FromSeconds(timeout) }; IBoxResponse <BoxLongPollMessage> pollResponse = await ToResponseAsync <BoxLongPollMessage>(pollRequest).ConfigureAwait(false); var message = pollResponse.ResponseObject.Message; if (message == NEW_CHANGE_MESSAGE) { BoxEventCollection <BoxEnterpriseEvent> newEvents = null; do { newEvents = await UserEventsAsync(streamType : streamType, streamPosition : nextStreamPosition, dedupeEvents : dedupeEvents).ConfigureAwait(false); nextStreamPosition = newEvents.NextStreamPosition; if (newEvents.Entries.Count > 0) { newEventsCallback.Invoke(newEvents); } } while (newEvents.Entries.Count > 0); } } catch { //Most likely request timed out. //If we've reached maximum number of retries then bounce all the way back to the OPTIONS request. pollAgain = numRetries-- > 0; } } while (pollAgain); } }
/// <summary> /// Used to get real-time notification of activity in a Box account. /// </summary> /// <param name="streamPosition">The location in the event stream from which you want to start receiving events.</param> /// <param name="newEventsCallback">Method to invoke when new events are received.</param> /// <param name="cancellationToken">Used to request that the long polling process terminate.</param> /// <param name="streamType">Restricts the types of events returned: all returns all events; changes returns events that may cause file tree changes such as file updates or collaborations; sync returns events that may cause file tree changes only for synced folders.</param> /// <param name="dedupeEvents">Whether or not to automatically de-duplicate events as they are received. Defaults to true.</param> /// <param name="retryTimeoutOverride">Used to override the retry timeout value returned from the long polling OPTIONS request.</param> /// <returns></returns> public async Task LongPollUserEvents(string streamPosition, Action<BoxEventCollection<BoxEnterpriseEvent>> newEventsCallback, CancellationToken cancellationToken, UserEventsStreamType streamType = UserEventsStreamType.all, bool dedupeEvents = true, int? retryTimeoutOverride = null) { const string NEW_CHANGE_MESSAGE = "new_change"; string nextStreamPosition = streamPosition; while (true) { BoxRequest optionsRequest = new BoxRequest(_config.EventsUri) .Param("stream_type", streamType.ToString()) .Method(RequestMethod.Options); IBoxResponse<BoxLongPollInfoCollection<BoxLongPollInfo>> optionsResponse = await ToResponseAsync<BoxLongPollInfoCollection<BoxLongPollInfo>>(optionsRequest).ConfigureAwait(false); var longPollInfo = optionsResponse.ResponseObject.Entries[0]; var numRetries = Int32.Parse(longPollInfo.MaxRetries); bool pollAgain = true; do { if (cancellationToken.IsCancellationRequested) { cancellationToken.ThrowIfCancellationRequested(); } try { var timeout = retryTimeoutOverride.HasValue ? retryTimeoutOverride.Value : longPollInfo.RetryTimeout; BoxRequest pollRequest = new BoxRequest(longPollInfo.Url) { Timeout = TimeSpan.FromSeconds(timeout) }; IBoxResponse<BoxLongPollMessage> pollResponse = await ToResponseAsync<BoxLongPollMessage>(pollRequest).ConfigureAwait(false); var message = pollResponse.ResponseObject.Message; if (message == NEW_CHANGE_MESSAGE) { BoxEventCollection<BoxEnterpriseEvent> newEvents = null; do { newEvents = await UserEventsAsync(streamType: streamType, streamPosition: nextStreamPosition, dedupeEvents: dedupeEvents).ConfigureAwait(false); nextStreamPosition = newEvents.NextStreamPosition; if (newEvents.Entries.Count > 0) { newEventsCallback.Invoke(newEvents); } } while (newEvents.Entries.Count > 0); } } catch { //Most likely request timed out. //If we've reached maximum number of retries then bounce all the way back to the OPTIONS request. pollAgain = numRetries-- > 0; } } while (pollAgain); } }