11package com .nylas ;
22
3+ import java .io .IOException ;
34import java .nio .charset .StandardCharsets ;
45import java .security .GeneralSecurityException ;
56import java .time .Instant ;
67import java .util .Arrays ;
78import java .util .List ;
9+ import java .util .Map ;
810
911import javax .crypto .Mac ;
1012import javax .crypto .spec .SecretKeySpec ;
1113
14+ import com .squareup .moshi .FromJson ;
15+ import com .squareup .moshi .Json ;
1216import com .squareup .moshi .JsonAdapter ;
17+ import com .nylas .JobStatus .Action ;
18+ import com .squareup .moshi .JsonReader ;
1319
1420public class Notification {
1521
@@ -98,8 +104,8 @@ public static class ObjectData {
98104 private String object ;
99105 private String account_id ;
100106 private String id ;
101- private Attributes attributes ;
102107 private MessageTrackingData metadata ;
108+ private transient Attributes attributes ;
103109
104110 /**
105111 * The type of the object that triggered this notification
@@ -146,7 +152,14 @@ public String toString() {
146152 }
147153
148154 }
149-
155+
156+ /**
157+ * Attributes for a message notification
158+ * <br>
159+ * Note: In the next major release Attributes will become an interface,
160+ * and this class will become "MessageNotificationAttributes" extending
161+ * from Attributes
162+ */
150163 public static class Attributes {
151164 private String received_date ;
152165 private String thread_id ;
@@ -170,10 +183,160 @@ public String toString() {
170183 return "Attributes [receivedDate=" + received_date + ", threadId=" + thread_id + "]" ;
171184 }
172185 }
186+
187+ /**
188+ * Attributes for event notifications
189+ */
190+ public static class EventNotificationAttributes extends Attributes {
191+ private String calendar_id ;
192+ private Boolean created_before_account_connection ;
193+
194+ /**
195+ * Calendar ID of the event
196+ */
197+ public String getCalendarId () {
198+ return calendar_id ;
199+ }
200+
201+ /**
202+ * Indicates if the event was created before the account was connected to Nylas
203+ */
204+ public Boolean getCreatedBeforeAccountConnection () {
205+ return created_before_account_connection ;
206+ }
207+
208+ @ Override
209+ public String toString () {
210+ return "EventNotificationAttributes [calendarId=" + calendar_id + ", createdBeforeAccountConnection=" + created_before_account_connection + "]" ;
211+ }
212+ }
213+
214+ /**
215+ * Attributes for job status notifications
216+ */
217+ public static class JobStatusNotificationAttributes extends Attributes {
218+ private Action action ;
219+ private String message_id ;
220+ private String job_status_id ;
221+ private Extras extras ;
222+
223+ /**
224+ * Event that triggered the job status webhook
225+ */
226+ public Action getAction () {
227+ return action ;
228+ }
229+
230+ /**
231+ * ID of the message associated with the Job
232+ */
233+ public String getMessageId () {
234+ return message_id ;
235+ }
236+
237+ /**
238+ * ID of the job
239+ */
240+ public String getJobStatusId () {
241+ return job_status_id ;
242+ }
243+
244+ /**
245+ * If the job has a status of cancelled, delayed, or failed then extras will contain more information
246+ */
247+ public Extras getExtras () {
248+ return extras ;
249+ }
250+
251+ @ Override
252+ public String toString () {
253+ return "JobStatusNotificationAttributes [action=" + action + ", threadId=" + getThreadId () + ", messageId="
254+ + message_id + ", jobStatusId=" + job_status_id + ", extras=" + extras + "]" ;
255+ }
256+
257+ /**
258+ * Extra information in the event that a job was cancelled, delayed or failed
259+ */
260+ public static class Extras {
261+ private String reason ;
262+ private Long send_at ;
263+ private Long original_send_at ;
264+
265+ /**
266+ * Reason for status
267+ */
268+ public String getReason () {
269+ return reason ;
270+ }
271+
272+ /**
273+ * Unix timestamp for when the message was sent
274+ */
275+ public Instant getSendAt () {
276+ return Instants .toNullableInstant (send_at );
277+ }
278+
279+ /**
280+ * Unix timestamp assigned from sending a message
281+ */
282+ public Instant getOriginalSendAt () {
283+ return Instants .toNullableInstant (original_send_at );
284+ }
285+
286+ @ Override
287+ public String toString () {
288+ return "Extras [reason=" + reason + ", sendAt=" + getSendAt () + ", originalSendAt=" + getOriginalSendAt () + "]" ;
289+ }
290+ }
291+ }
292+
293+ /**
294+ * This adapter identifies the type of object this notification is for,
295+ * and deserializes it to the appropriate Attributes class.
296+ */
297+ @ SuppressWarnings ("unchecked" )
298+ static class WebhookDeltaAdapter {
299+ @ FromJson
300+ Delta fromJson (JsonReader reader , JsonAdapter <Delta > delegate ) throws IOException {
301+ Map <String , Object > json = JsonHelper .jsonToMap (reader );
302+ Delta delta = delegate .fromJson (JsonHelper .mapToJson (json ));
303+ if (delta != null && delta .object_data != null ) {
304+ Map <String , Object > objectDataJson = (Map <String , Object >) json .get ("object_data" );
305+ if (objectDataJson .get ("attributes" ) != null ) {
306+ Map <String , Object > attributesJson = (Map <String , Object >) objectDataJson .get ("attributes" );
307+ if (attributesJson != null ) {
308+ if (delta .object != null ) {
309+ Class <? extends Attributes > attributeClass ;
310+ switch (delta .object ) {
311+ case "event" :
312+ attributeClass = EventNotificationAttributes .class ;
313+ break ;
314+ case "job_status" :
315+ attributeClass = JobStatusNotificationAttributes .class ;
316+ break ;
317+ case "message" :
318+ default :
319+ attributeClass = Attributes .class ;
320+ }
321+ delta .object_data .attributes = JsonHelper
322+ .moshi ()
323+ .adapter (attributeClass )
324+ .fromJson (JsonHelper .mapToJson (attributesJson ));
325+ }
326+ }
327+ }
328+ }
329+
330+ return delta ;
331+ }
332+ }
173333
174- /*
175- * Perhaps this class could be better served by splitting into subclasses for specific
176- * notification types. Not sure it's worth the time investment yet to get the Moshi JSON parsing done.
334+ /**
335+ * Metadata for webhook notifications
336+ * <br>
337+ * Note: In the next major release this class will be split into
338+ * smaller classes more specific to the different types of metadata
339+ * depending on the type of webhook notification
177340 */
178341 public static class MessageTrackingData {
179342 private String message_id ;
@@ -192,6 +355,11 @@ public static class MessageTrackingData {
192355 // message.link_clicked specific fields
193356 private List <LinkClickCount > link_data ;
194357 private List <LinkClick > recents ; // also in message.opened
358+
359+ // event specific fields
360+ @ Json (name = "event-type" )
361+ private String eventType ;
362+ private String message ;
195363
196364 /**
197365 * Nylas message ID for the tracked message
@@ -283,12 +451,30 @@ public List<LinkClick> getRecentClicks() {
283451 return recents ;
284452 }
285453
454+ /**
455+ * The custom event type set for the Event
456+ *
457+ * Available for event notifications only
458+ */
459+ public String getEventType () {
460+ return eventType ;
461+ }
462+
463+ /**
464+ * The custom message set for the Event
465+ *
466+ * Available for event notifications only
467+ */
468+ public String getMessage () {
469+ return message ;
470+ }
471+
286472 @ Override
287473 public String toString () {
288474 return "MessageTrackingData [messageId=" + message_id + ", senderAppId=" + sender_app_id + ", payload="
289475 + payload + ", timestamp=" + getTimestamp () + ", threadId=" + thread_id + ", fromSelf=" + from_self
290476 + ", replyToMessageId=" + reply_to_message_id + ", openedCount=" + count + ", linkClickCounts="
291- + link_data + ", recentClicks=" + recents + "]" ;
477+ + link_data + ", recentClicks=" + recents + ", eventType=" + eventType + ", message=" + message + " ]" ;
292478 }
293479 }
294480
0 commit comments