@@ -56,32 +56,40 @@ export default class HubspotCalendarService implements CRM {
5656 } )
5757 . join ( "<br><br>" ) ;
5858
59- return `<b>${ event . organizer . language . translate ( "invitee_timezone" ) } :</b> ${
60- event . attendees [ 0 ] . timeZone
61- } <br><br>${
62- event . additionalNotes
63- ? `<b>${ event . organizer . language . translate ( "share_additional_notes" ) } </b><br>${
64- event . additionalNotes
65- } <br><br>`
59+ const organizerName = event . organizer . name || event . organizer . email ;
60+ const organizerInfo = `<b>${ event . organizer . language . translate ( "organizer" ) } :</b> ${ organizerName } (${ event . organizer . email
61+ } )`;
62+
63+ return `${ organizerInfo } <br><br><b>${ event . organizer . language . translate ( "invitee_timezone" ) } :</b> ${ event . attendees [ 0 ] . timeZone
64+ } <br><br>${ event . additionalNotes
65+ ? `<b>${ event . organizer . language . translate ( "share_additional_notes" ) } </b><br>${ event . additionalNotes
66+ } <br><br>`
6667 : ""
67- }
68+ }
6869 ${ userFieldsHtml } <br><br>
6970 <b>${ event . organizer . language . translate ( "where" ) } :</b> ${ location } <br><br>
7071 ${ plainText ? `<b>${ event . organizer . language . translate ( "description" ) } </b><br>${ plainText } ` : "" }
7172 ` ;
7273 } ;
7374
74- private hubspotCreateMeeting = async ( event : CalendarEvent ) => {
75+ private hubspotCreateMeeting = async ( event : CalendarEvent , hubspotOwnerId ?: string ) => {
76+ const properties : Record < string , string > = {
77+ hs_timestamp : Date . now ( ) . toString ( ) ,
78+ hs_meeting_title : event . title ,
79+ hs_meeting_body : this . getHubspotMeetingBody ( event ) ,
80+ hs_meeting_location : getLocation ( event ) ,
81+ hs_meeting_start_time : new Date ( event . startTime ) . toISOString ( ) ,
82+ hs_meeting_end_time : new Date ( event . endTime ) . toISOString ( ) ,
83+ hs_meeting_outcome : "SCHEDULED" ,
84+ } ;
85+
86+ if ( hubspotOwnerId ) {
87+ properties . hubspot_owner_id = hubspotOwnerId ;
88+ this . log . debug ( "hubspot:meeting:setting_owner" , { hubspotOwnerId } ) ;
89+ }
90+
7591 const simplePublicObjectInput : SimplePublicObjectInput = {
76- properties : {
77- hs_timestamp : Date . now ( ) . toString ( ) ,
78- hs_meeting_title : event . title ,
79- hs_meeting_body : this . getHubspotMeetingBody ( event ) ,
80- hs_meeting_location : getLocation ( event ) ,
81- hs_meeting_start_time : new Date ( event . startTime ) . toISOString ( ) ,
82- hs_meeting_end_time : new Date ( event . endTime ) . toISOString ( ) ,
83- hs_meeting_outcome : "SCHEDULED" ,
84- } ,
92+ properties,
8593 } ;
8694
8795 return this . hubspotClient . crm . objects . meetings . basicApi . create ( simplePublicObjectInput ) ;
@@ -132,20 +140,49 @@ export default class HubspotCalendarService implements CRM {
132140 return this . hubspotClient . crm . objects . meetings . basicApi . archive ( uid ) ;
133141 } ;
134142
143+ private getHubspotOwnerIdByEmail = async ( email : string ) : Promise < string | undefined > => {
144+ try {
145+ const ownersResponse = await this . hubspotClient . crm . owners . ownersApi . getPage (
146+ email ,
147+ undefined ,
148+ 100 ,
149+ false
150+ ) ;
151+
152+ if ( ownersResponse . results && ownersResponse . results . length > 0 ) {
153+ const matchingOwner = ownersResponse . results . find (
154+ ( owner ) => owner . email ?. toLowerCase ( ) === email . toLowerCase ( )
155+ ) ;
156+
157+ if ( matchingOwner ) {
158+ this . log . debug ( "hubspot:owner:found" , { ownerId : matchingOwner . id } ) ;
159+ return matchingOwner . id ;
160+ }
161+ }
162+
163+ this . log . debug ( "hubspot:owner:not_found" ) ;
164+ return undefined ;
165+ } catch ( error ) {
166+ this . log . error ( "hubspot:owner:lookup_error" , { error } ) ;
167+ return undefined ;
168+ }
169+ } ;
170+
135171 private hubspotAuth = async ( credential : CredentialPayload ) => {
136172 const appKeys = await getAppKeysFromSlug ( "hubspot" ) ;
137173 if ( typeof appKeys . client_id === "string" ) this . client_id = appKeys . client_id ;
138174 if ( typeof appKeys . client_secret === "string" ) this . client_secret = appKeys . client_secret ;
139175 if ( ! this . client_id ) throw new HttpError ( { statusCode : 400 , message : "Hubspot client_id missing." } ) ;
140176 if ( ! this . client_secret )
141177 throw new HttpError ( { statusCode : 400 , message : "Hubspot client_secret missing." } ) ;
142- const credentialKey = credential . key as unknown as HubspotToken ;
178+ let currentToken = credential . key as unknown as HubspotToken ;
179+
143180 const isTokenValid = ( token : HubspotToken ) =>
144181 token &&
145182 token . tokenType &&
146183 token . accessToken &&
147184 token . expiryDate &&
148- ( token . expiresIn || token . expiryDate ) < Date . now ( ) ;
185+ token . expiryDate > Date . now ( ) ;
149186
150187 const refreshAccessToken = async ( refreshToken : string ) => {
151188 try {
@@ -162,7 +199,6 @@ export default class HubspotCalendarService implements CRM {
162199 "hubspot" ,
163200 credential . userId
164201 ) ;
165- // set expiry date as offset from current time.
166202 hubspotRefreshToken . expiryDate = Math . round ( Date . now ( ) + hubspotRefreshToken . expiresIn * 1000 ) ;
167203 await prisma . credential . update ( {
168204 where : {
@@ -174,22 +210,34 @@ export default class HubspotCalendarService implements CRM {
174210 } ) ;
175211
176212 this . hubspotClient . setAccessToken ( hubspotRefreshToken . accessToken ) ;
213+ currentToken = { ...currentToken , ...hubspotRefreshToken } ;
177214 } catch ( e : unknown ) {
178215 this . log . error ( e ) ;
179216 }
180217 } ;
181218
182219 return {
183- getToken : ( ) =>
184- ! isTokenValid ( credentialKey ) ? Promise . resolve ( [ ] ) : refreshAccessToken ( credentialKey . refreshToken ) ,
220+ getToken : async ( ) => {
221+ if ( ! isTokenValid ( currentToken ) ) {
222+ await refreshAccessToken ( currentToken . refreshToken ) ;
223+ } else {
224+ this . hubspotClient . setAccessToken ( currentToken . accessToken ) ;
225+ }
226+ } ,
185227 } ;
186228 } ;
187229
188230 async handleMeetingCreation ( event : CalendarEvent , contacts : Contact [ ] ) {
189231 const contactIds : { id ?: string } [ ] = contacts . map ( ( contact ) => ( { id : contact . id } ) ) ;
190- const meetingEvent = await this . hubspotCreateMeeting ( event ) ;
232+
233+ const organizerEmail = event . organizer . email ;
234+ this . log . debug ( "hubspot:meeting:fetching_owner" ) ;
235+
236+ const hubspotOwnerId = await this . getHubspotOwnerIdByEmail ( organizerEmail ) ;
237+
238+ const meetingEvent = await this . hubspotCreateMeeting ( event , hubspotOwnerId ) ;
191239 if ( meetingEvent ) {
192- this . log . debug ( "meeting:creation:ok" , { meetingEvent } ) ;
240+ this . log . debug ( "meeting:creation:ok" , { meetingId : meetingEvent . id , hubspotOwnerId } ) ;
193241 const associatedMeeting = await this . hubspotAssociate ( meetingEvent , contactIds as any ) ;
194242 if ( associatedMeeting ) {
195243 this . log . debug ( "association:creation:ok" , { associatedMeeting } ) ;
0 commit comments