88import { BetaGraph , IGraph , Providers , error , log } from '@microsoft/mgt-element' ;
99import * as signalR from '@microsoft/signalr' ;
1010import { ThreadEventEmitter } from './ThreadEventEmitter' ;
11- import type { Subscription , ChatMessage , Chat , AadUserConversationMember } from '@microsoft/microsoft-graph-types' ;
12- import { } from '@microsoft/microsoft-graph-types-beta' ;
11+ import type {
12+ Entity ,
13+ Subscription ,
14+ ChatMessage ,
15+ Chat ,
16+ AadUserConversationMember
17+ } from '@microsoft/microsoft-graph-types' ;
1318import { GraphConfig } from './GraphConfig' ;
1419import { SubscriptionsCache } from './Caching/SubscriptionCache' ;
1520
@@ -21,18 +26,25 @@ export const appSettings = {
2126
2227type ChangeTypes = 'created' | 'updated' | 'deleted' ;
2328
24- type Notification = {
29+ type Notification < T extends Entity > = {
2530 subscriptionId : string ;
2631 changeType : ChangeTypes ;
2732 resource : string ;
28- resourceData : {
33+ resourceData : T & {
2934 id : string ;
3035 '@odata.type' : string ;
3136 '@odata.id' : string ;
3237 } ;
33- encryptedContent : string ;
38+ EncryptedContent : string ;
3439} ;
3540
41+ type ReceivedNotification = Notification < Chat > | Notification < ChatMessage > | Notification < AadUserConversationMember > ;
42+
43+ const isMessageNotification = ( o : Notification < Entity > ) : o is Notification < ChatMessage > =>
44+ o . resource . includes ( '/messages(' ) ;
45+ const isMembershipNotification = ( o : Notification < Entity > ) : o is Notification < AadUserConversationMember > =>
46+ o . resource . includes ( '/members' ) ;
47+
3648const stripWssScheme = ( notificationUrl : string ) : string => notificationUrl . replace ( 'wss:' , '' ) ;
3749
3850export class GraphNotificationClient {
@@ -70,22 +82,27 @@ export class GraphNotificationClient {
7082 return ( await Promise . resolve ( encryptedData ) ) as T ;
7183 }
7284
73- private readonly receiveNotificationMessage = async ( notification : Notification ) => {
85+ private readonly receiveNotificationMessage = ( message : string ) => {
86+ if ( typeof message !== 'string' ) throw new Error ( 'Expected string from receivenotificationmessageasync' ) ;
87+
88+ const notification : ReceivedNotification = JSON . parse ( message ) as ReceivedNotification ;
7489 log ( 'received notification message' , notification ) ;
7590 const emitter : ThreadEventEmitter | undefined = this . emitter ;
76- if ( ! notification . encryptedContent ) throw new Error ( 'Message did not contain encrypted content ' ) ;
77- if ( notification . resource . indexOf ( '/messages' ) !== - 1 ) {
78- await this . processMessageNotification ( notification , emitter ) ;
79- } else if ( notification . resource . indexOf ( '/members' ) !== - 1 ) {
80- await this . processMembershipNotification ( notification , emitter ) ;
91+ if ( ! notification . resourceData ) throw new Error ( 'Message did not contain resourceData ' ) ;
92+ if ( isMessageNotification ( notification ) ) {
93+ this . processMessageNotification ( notification , emitter ) ;
94+ } else if ( isMembershipNotification ( notification ) ) {
95+ this . processMembershipNotification ( notification , emitter ) ;
8196 } else {
82- await this . processChatPropertiesNotification ( notification , emitter ) ;
97+ this . processChatPropertiesNotification ( notification , emitter ) ;
8398 }
99+ return { StatusCode : '200' } ;
100+
84101 return new signalR . HttpResponse ( 200 ) ;
85102 } ;
86103
87- private async processMessageNotification ( notification : Notification , emitter : ThreadEventEmitter | undefined ) {
88- const message = await this . decryptMessage < ChatMessage > ( notification . encryptedContent ) ;
104+ private processMessageNotification ( notification : Notification < ChatMessage > , emitter : ThreadEventEmitter | undefined ) {
105+ const message = notification . resourceData ;
89106
90107 switch ( notification . changeType ) {
91108 case 'created' :
@@ -102,8 +119,11 @@ export class GraphNotificationClient {
102119 }
103120 }
104121
105- private async processMembershipNotification ( notification : Notification , emitter : ThreadEventEmitter | undefined ) {
106- const member = await this . decryptMessage < AadUserConversationMember > ( notification . encryptedContent ) ;
122+ private processMembershipNotification (
123+ notification : Notification < AadUserConversationMember > ,
124+ emitter : ThreadEventEmitter | undefined
125+ ) {
126+ const member = notification . resourceData ;
107127 switch ( notification . changeType ) {
108128 case 'created' :
109129 emitter ?. participantAdded ( member ) ;
@@ -116,8 +136,8 @@ export class GraphNotificationClient {
116136 }
117137 }
118138
119- private async processChatPropertiesNotification ( notification : Notification , emitter : ThreadEventEmitter | undefined ) {
120- const chat = await this . decryptMessage < Chat > ( notification . encryptedContent ) ;
139+ private processChatPropertiesNotification ( notification : Notification < Chat > , emitter : ThreadEventEmitter | undefined ) {
140+ const chat = notification . resourceData ;
121141 switch ( notification . changeType ) {
122142 case 'updated' :
123143 emitter ?. chatThreadPropertiesUpdated ( chat ) ;
@@ -135,7 +155,7 @@ export class GraphNotificationClient {
135155
136156 await this . subscriptionCache . cacheSubscription ( this . chatId , subscriptionRecord ) ;
137157
138- // only start timer once. -1 for renewaltimer is semaphore it has stopped.
158+ // only start timer once. -1 for renewalInterval is semaphore it has stopped.
139159 if ( this . renewalInterval === - 1 ) this . startRenewalTimer ( ) ;
140160 } ;
141161
@@ -150,8 +170,6 @@ export class GraphNotificationClient {
150170 resource : resourcePath ,
151171 expirationDateTime,
152172 includeResourceData : true ,
153- // encryptionCertificate: this._publicKey,
154- // encryptionCertificateId: 'not-a-cert-id',
155173 clientState : 'wsssecret'
156174 } ;
157175
0 commit comments