@@ -158,6 +158,9 @@ document
158158 if ( webhook && webhook . customPayload ) {
159159 try {
160160 // Create variable replacements map
161+ const now = new Date ( ) ;
162+ const nowLocal = new Date ( now . getTime ( ) - now . getTimezoneOffset ( ) * 60000 ) ;
163+
161164 const replacements = {
162165 "{{tab.title}}" : activeTab . title ,
163166 "{{tab.url}}" : currentUrl ,
@@ -172,30 +175,48 @@ document
172175 "{{platform.arch}}" : platformInfo . arch || "unknown" ,
173176 "{{platform.os}}" : platformInfo . os || "unknown" ,
174177 "{{platform.version}}" : platformInfo . version ,
175- "{{triggeredAt}}" : new Date ( ) . toISOString ( ) ,
176- "{{identifier}}" : webhook . identifier || ""
178+ "{{identifier}}" : webhook . identifier || "" ,
179+ // Legacy variable
180+ "{{triggeredAt}}" : now . toISOString ( ) ,
181+ // New DateTime variables (UTC)
182+ "{{now.iso}}" : now . toISOString ( ) ,
183+ "{{now.date}}" : now . toISOString ( ) . slice ( 0 , 10 ) ,
184+ "{{now.time}}" : now . toISOString ( ) . slice ( 11 , 19 ) ,
185+ "{{now.unix}}" : Math . floor ( now . getTime ( ) / 1000 ) ,
186+ "{{now.unix_ms}}" : now . getTime ( ) ,
187+ "{{now.year}}" : now . getUTCFullYear ( ) ,
188+ "{{now.month}}" : now . getUTCMonth ( ) + 1 ,
189+ "{{now.day}}" : now . getUTCDate ( ) ,
190+ "{{now.hour}}" : now . getUTCHours ( ) ,
191+ "{{now.minute}}" : now . getUTCMinutes ( ) ,
192+ "{{now.second}}" : now . getUTCSeconds ( ) ,
193+ "{{now.millisecond}}" : now . getUTCMilliseconds ( ) ,
194+ // New DateTime variables (local)
195+ "{{now.local.iso}}" : nowLocal . toISOString ( ) . slice ( 0 , - 1 ) + ( now . getTimezoneOffset ( ) > 0 ? "-" : "+" ) + ( "0" + Math . abs ( now . getTimezoneOffset ( ) / 60 ) ) . slice ( - 2 ) + ":" + ( "0" + Math . abs ( now . getTimezoneOffset ( ) % 60 ) ) . slice ( - 2 ) ,
196+ "{{now.local.date}}" : nowLocal . toISOString ( ) . slice ( 0 , 10 ) ,
197+ "{{now.local.time}}" : nowLocal . toISOString ( ) . slice ( 11 , 19 ) ,
177198 } ;
178199
179- // Replace placeholders in custom payload
180- let customPayloadStr = webhook . customPayload ;
181- Object . entries ( replacements ) . forEach ( ( [ placeholder , value ] ) => {
182- // Handle different types of values
183- // For string values in JSON, we need to handle them differently based on context
184- // If the placeholder is inside quotes in the JSON, we should not add quotes again
185- const isPlaceholderInQuotes = customPayloadStr . match ( new RegExp ( `"[^"]*${ placeholder . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) } [^"]*"` , 'g' ) ) ;
186-
187- const replaceValue = typeof value === 'string'
188- ? ( isPlaceholderInQuotes ? value . replace ( / " / g, '\\"' ) : `"${ value . replace ( / " / g, '\\"' ) } "` )
189- : ( value === undefined ? 'null' : JSON . stringify ( value ) ) ;
200+ // Parse the custom payload as JSON
201+ let customPayload = JSON . parse ( webhook . customPayload ) ;
190202
191- customPayloadStr = customPayloadStr . replace (
192- new RegExp ( placeholder . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) , 'g' ) ,
193- replaceValue
194- ) ;
195- } ) ;
203+ // Recursively replace placeholders
204+ const replacePlaceholders = ( obj ) => {
205+ for ( const key in obj ) {
206+ if ( obj . hasOwnProperty ( key ) ) {
207+ if ( typeof obj [ key ] === 'string' ) {
208+ const placeholder = obj [ key ] ;
209+ if ( replacements . hasOwnProperty ( placeholder ) ) {
210+ obj [ key ] = replacements [ placeholder ] ;
211+ }
212+ } else if ( typeof obj [ key ] === 'object' && obj [ key ] !== null ) {
213+ replacePlaceholders ( obj [ key ] ) ;
214+ }
215+ }
216+ }
217+ } ;
196218
197- // Parse the resulting JSON
198- const customPayload = JSON . parse ( customPayloadStr ) ;
219+ replacePlaceholders ( customPayload ) ;
199220
200221 // Use the custom payload instead of the default one
201222 payload = customPayload ;
0 commit comments