22
33package io .getstream ;
44
5+ import com .fasterxml .jackson .databind .DeserializationFeature ;
56import com .fasterxml .jackson .databind .JsonNode ;
67import com .fasterxml .jackson .databind .ObjectMapper ;
78import io .getstream .models .ActivityAddedEvent ;
104105import io .getstream .models .FeedDeletedEvent ;
105106import io .getstream .models .FeedGroupChangedEvent ;
106107import io .getstream .models .FeedGroupDeletedEvent ;
108+ import io .getstream .models .FeedGroupRestoredEvent ;
107109import io .getstream .models .FeedMemberAddedEvent ;
108110import io .getstream .models .FeedMemberRemovedEvent ;
109111import io .getstream .models .FeedMemberUpdatedEvent ;
154156import io .getstream .models .UserDeactivatedEvent ;
155157import io .getstream .models .UserDeletedEvent ;
156158import io .getstream .models .UserFlaggedEvent ;
159+ import io .getstream .models .UserGroupCreatedEvent ;
160+ import io .getstream .models .UserGroupDeletedEvent ;
161+ import io .getstream .models .UserGroupMemberAddedEvent ;
162+ import io .getstream .models .UserGroupMemberRemovedEvent ;
163+ import io .getstream .models .UserGroupUpdatedEvent ;
157164import io .getstream .models .UserMessagesDeletedEvent ;
158165import io .getstream .models .UserMutedEvent ;
159166import io .getstream .models .UserReactivatedEvent ;
172179/** Webhook utilities for Stream webhooks. */
173180public class Webhook {
174181 private static final String HMAC_SHA256 = "HmacSHA256" ;
175- private static final ObjectMapper objectMapper = new ObjectMapper ();
182+ private static final ObjectMapper objectMapper =
183+ new ObjectMapper ().configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
176184
177185 /** Webhook event type constants. */
178186 public static class EventType {
@@ -289,6 +297,7 @@ public static class EventType {
289297 public static final String FEEDS_FEED_UPDATED = "feeds.feed.updated" ;
290298 public static final String FEEDS_FEED_GROUP_CHANGED = "feeds.feed_group.changed" ;
291299 public static final String FEEDS_FEED_GROUP_DELETED = "feeds.feed_group.deleted" ;
300+ public static final String FEEDS_FEED_GROUP_RESTORED = "feeds.feed_group.restored" ;
292301 public static final String FEEDS_FEED_MEMBER_ADDED = "feeds.feed_member.added" ;
293302 public static final String FEEDS_FEED_MEMBER_REMOVED = "feeds.feed_member.removed" ;
294303 public static final String FEEDS_FEED_MEMBER_UPDATED = "feeds.feed_member.updated" ;
@@ -340,6 +349,11 @@ public static class EventType {
340349 public static final String USER_UNMUTED = "user.unmuted" ;
341350 public static final String USER_UNREAD_MESSAGE_REMINDER = "user.unread_message_reminder" ;
342351 public static final String USER_UPDATED = "user.updated" ;
352+ public static final String USER_GROUP_CREATED = "user_group.created" ;
353+ public static final String USER_GROUP_DELETED = "user_group.deleted" ;
354+ public static final String USER_GROUP_MEMBER_ADDED = "user_group.member_added" ;
355+ public static final String USER_GROUP_MEMBER_REMOVED = "user_group.member_removed" ;
356+ public static final String USER_GROUP_UPDATED = "user_group.updated" ;
343357 }
344358
345359 /**
@@ -376,11 +390,7 @@ public static String getEventType(String rawEvent) {
376390 * @throws WebhookException if the event type is unknown or deserialization fails
377391 */
378392 public static Object parseWebhookEvent (byte [] rawEvent ) throws WebhookException {
379- String eventType = getEventType (rawEvent );
380- if (eventType == null || eventType .isEmpty ()) {
381- throw new WebhookException ("Webhook payload missing 'type' field" );
382- }
383-
393+ String eventType = extractEventType (rawEvent );
384394 try {
385395 Class <?> eventClass = getEventClass (eventType );
386396 return objectMapper .readValue (rawEvent , eventClass );
@@ -389,6 +399,20 @@ public static Object parseWebhookEvent(byte[] rawEvent) throws WebhookException
389399 }
390400 }
391401
402+ private static String extractEventType (byte [] rawEvent ) throws WebhookException {
403+ JsonNode node ;
404+ try {
405+ node = objectMapper .readTree (rawEvent );
406+ } catch (IOException e ) {
407+ throw new WebhookException ("Webhook payload is not valid JSON: " + e .getMessage (), e );
408+ }
409+ JsonNode typeNode = node .get ("type" );
410+ if (typeNode == null || typeNode .asText ().isEmpty ()) {
411+ throw new WebhookException ("Webhook payload missing 'type' field" );
412+ }
413+ return typeNode .asText ();
414+ }
415+
392416 /**
393417 * Deserialize a raw webhook payload into a typed event object.
394418 *
@@ -620,6 +644,8 @@ private static Class<?> getEventClass(String eventType) throws WebhookException
620644 return FeedGroupChangedEvent .class ;
621645 case "feeds.feed_group.deleted" :
622646 return FeedGroupDeletedEvent .class ;
647+ case "feeds.feed_group.restored" :
648+ return FeedGroupRestoredEvent .class ;
623649 case "feeds.feed_member.added" :
624650 return FeedMemberAddedEvent .class ;
625651 case "feeds.feed_member.removed" :
@@ -722,6 +748,16 @@ private static Class<?> getEventClass(String eventType) throws WebhookException
722748 return UserUnreadReminderEvent .class ;
723749 case "user.updated" :
724750 return UserUpdatedEvent .class ;
751+ case "user_group.created" :
752+ return UserGroupCreatedEvent .class ;
753+ case "user_group.deleted" :
754+ return UserGroupDeletedEvent .class ;
755+ case "user_group.member_added" :
756+ return UserGroupMemberAddedEvent .class ;
757+ case "user_group.member_removed" :
758+ return UserGroupMemberRemovedEvent .class ;
759+ case "user_group.updated" :
760+ return UserGroupUpdatedEvent .class ;
725761 default :
726762 throw new WebhookException ("Unknown webhook event type: " + eventType );
727763 }
0 commit comments