11import { escapeHTML , formatText , toRoomID } from 'ps-client/tools' ;
2+ import { Temporal } from '@js-temporal/polyfill' ;
23
34import { PSQuoteRoomPrefs } from '@/cache' ;
45import { isGlobalBot , prefix } from '@/config/ps' ;
@@ -20,7 +21,6 @@ import type { PSMessage } from '@/types/ps';
2021import type { CSSProperties , ReactElement , ReactNode } from 'react' ;
2122
2223type IndexedQuoteModel = [ index : number , quote : QuoteModel ] ;
23- type QuoteCollection = [ index : number , quote : string ] [ ] ;
2424
2525const PAGE_SIZE = 50 ;
2626const MAX_QUOTE_LENGTH = ( MAX_CHAT_HTML_LENGTH / PAGE_SIZE ) * 2 ; // Leniency margin of 2x
@@ -157,16 +157,20 @@ function FormatQuote({
157157 quote,
158158 psUsernameTag = true ,
159159 header,
160+ addedBy,
161+ dateAdded,
160162} : {
161163 quote : string ;
162164 psUsernameTag ?: boolean ;
165+ addedBy ?: string ;
166+ dateAdded ?: string ;
163167 header ?: ReactNode ;
164168 children ?: ReactElement [ ] ;
165169} ) : ReactElement {
166170 const quoteLines = quote . split ( '\n' ) ;
167171 return (
168172 < >
169- { header }
173+ < div style = { { opacity : 0.78 } } > { header } </ div >
170174 < div style = { { marginLeft : 12 } } >
171175 { quoteLines . length > 5 ? (
172176 < details className = "readmore" >
@@ -188,6 +192,13 @@ function FormatQuote({
188192 quoteLines . map ( line => < FormatQuoteLine line = { line } psUsernameTag = { psUsernameTag } /> )
189193 ) }
190194 </ div >
195+ { addedBy && dateAdded && (
196+ < >
197+ < span style = { { fontSize : 10 , opacity : 0.6 , marginTop : 6 } } > Added by </ span >
198+ < UsernamePS name = { addedBy } style = { { fontSize : 10 } } clickable />
199+ < span style = { { fontSize : 10 , opacity : 0.6 , marginTop : 6 } } > on { dateAdded } </ span >
200+ </ >
201+ ) }
191202 </ >
192203 ) ;
193204}
@@ -213,7 +224,7 @@ function MultiQuotes({
213224 title : baseTitle ,
214225 showAll = false ,
215226} : {
216- list : QuoteCollection ;
227+ list : IndexedQuoteModel [ ] ;
217228 pageNum : number | null ;
218229 total : number ;
219230 command : string | null ;
@@ -227,7 +238,16 @@ function MultiQuotes({
227238 plural : 'quotes' ,
228239 } ) } ${ total > list . length ? ` of ${ total } total` : '' } )`;
229240 const title = baseTitle ? `${ baseTitle } ${ suffix } ` : pageNum ? `Page ${ pageNum } of ${ pageCount } ${ suffix } ` : `All Quotes` ;
230- const quotes = list . map ( ( [ header , quote ] ) => < FormatQuote quote = { quote } header = { `#${ header } ` } /> ) . space ( < hr /> , ! useDropdown ) ;
241+ const quotes = list
242+ . map ( ( [ index , quote ] ) => {
243+ const dateAdded = Temporal . Instant . fromEpochMilliseconds ( quote . at . getTime ( ) )
244+ . toZonedDateTimeISO ( 'UTC' )
245+ . toPlainDate ( )
246+ . toLocaleString ( 'en-GB' ) ;
247+
248+ return < FormatQuote quote = { quote . quote } header = { `#${ index } ` } addedBy = { quote . addedBy } dateAdded = { dateAdded } /> ;
249+ } )
250+ . space ( < hr /> , ! useDropdown ) ;
231251
232252 const content = useDropdown ? (
233253 < >
@@ -237,7 +257,7 @@ function MultiQuotes({
237257 < h3 style = { { display : 'inline-block' } } > { title } </ h3 >
238258 </ summary >
239259 < hr />
240- { quotes }
260+ < > { quotes } </ >
241261 </ details >
242262 < hr />
243263 </ >
@@ -306,10 +326,15 @@ export const command: PSCommand = {
306326 ) ;
307327 if ( ! matchingQuotes . length ) return broadcast ( $T ( 'COMMANDS.QUOTES.NO_QUOTES_FOUND_MATCHING' , { search : arg } ) ) ;
308328 const [ index , randQuote ] = matchingQuotes . random ( ) ! ;
329+ const dateAdded = Temporal . Instant . fromEpochMilliseconds ( randQuote . at . getTime ( ) )
330+ . toZonedDateTimeISO ( 'UTC' )
331+ . toPlainDate ( )
332+ . toLocaleString ( 'en-GB' ) ;
333+
309334 broadcastHTML (
310335 < >
311336 < hr />
312- < FormatQuote quote = { randQuote . quote } header = { `#${ + index + 1 } ` } />
337+ < FormatQuote quote = { randQuote . quote } header = { `#${ + index + 1 } ` } addedBy = { randQuote . addedBy } dateAdded = { dateAdded } />
313338 < hr />
314339 </ > ,
315340 { name : `viewquote-${ message . parent . status . userid } ` }
@@ -326,17 +351,20 @@ export const command: PSCommand = {
326351 'wrapping the username in ``[]`` (eg: ``[14:20:21] • #PartMan hugs Hydro`` would be formatted ' +
327352 'as ``[14:20:21] • #[PartMan] hugs Hydro``).' ,
328353 syntax : 'CMD [new quote]' ,
329- async run ( { message, arg, broadcastHTML } ) {
354+ async run ( { message, arg, broadcastHTML, $T } ) {
330355 const parsedQuote = parseQuote ( arg ) ;
331- const rendered = jsxToHTML ( < FormatQuote quote = { parsedQuote } /> ) ;
356+ const addedBy = message . author . name ;
357+ const at = Temporal . Now . plainDateISO ( 'UTC' ) . toLocaleString ( 'en-GB' ) ;
358+
359+ const rendered = jsxToHTML ( < FormatQuote quote = { parsedQuote } addedBy = { addedBy } dateAdded = { at } /> ) ;
332360
333361 if ( rendered . length > MAX_QUOTE_LENGTH ) throw new ChatError ( 'Quote is too long.' as ToTranslate ) ;
334- await addQuote ( parsedQuote , message . target . id , message . author . name ) ;
362+ await addQuote ( parsedQuote , message . target . id , addedBy ) ;
335363 const { length } = await getAllQuotes ( message . target . id ) ;
336364 broadcastHTML (
337365 < >
338366 < hr />
339- < FormatQuote quote = { parsedQuote } header = { `Quote #${ length } added.` } />
367+ < FormatQuote quote = { parsedQuote } header = { `Quote #${ length } added.` } addedBy = { addedBy } dateAdded = { at } />
340368 < hr />
341369 </ > ,
342370 { name : `viewquote-${ message . parent . status . userid } ` }
@@ -349,7 +377,7 @@ export const command: PSCommand = {
349377 perms : ( message , check ) => ( message . type === 'pm' ? true : check ( 'driver' ) ) ,
350378 help : 'Previews the given quote. Syntax is the same as add.' ,
351379 syntax : 'CMD [new quote]' ,
352- async run ( { message, arg, broadcastHTML } ) {
380+ async run ( { message, arg, broadcastHTML, $T } ) {
353381 const parsedQuote = parseQuote ( arg ) ;
354382 const { length } = await getAllQuotes ( message . target . id ) ;
355383 broadcastHTML (
@@ -372,10 +400,10 @@ export const command: PSCommand = {
372400 const room : string = await getRoom ( givenRoom , message , $T ) ;
373401 const quotes = await getAllQuotes ( room ) ;
374402
375- const foundQuotes : QuoteCollection = searchQuotes (
403+ const foundQuotes : IndexedQuoteModel [ ] = searchQuotes (
376404 quotes . map < IndexedQuoteModel > ( ( quote , index ) => [ index + 1 , quote ] ) ,
377405 arg
378- ) . map ( ( [ index , quote ] ) => [ index , quote . quote ] ) ;
406+ ) ;
379407
380408 if ( ! foundQuotes . length ) return broadcast ( $T ( 'COMMANDS.QUOTES.NO_QUOTES_FOUND' ) ) ;
381409
@@ -402,10 +430,15 @@ export const command: PSCommand = {
402430 const quotes = await getAllQuotes ( room ) ;
403431 if ( ! quotes . length ) return broadcast ( $T ( 'COMMANDS.QUOTES.NO_QUOTES_FOUND' ) ) ;
404432 const lastQuote = quotes [ quotes . length - 1 ] ;
433+ const dateAdded = Temporal . Instant . fromEpochMilliseconds ( lastQuote . at . getTime ( ) )
434+ . toZonedDateTimeISO ( 'UTC' )
435+ . toPlainDate ( )
436+ . toLocaleString ( 'en-GB' ) ;
437+
405438 broadcastHTML (
406439 < >
407440 < hr />
408- < FormatQuote quote = { lastQuote . quote } header = { `#${ quotes . length } ` } />
441+ < FormatQuote quote = { lastQuote . quote } header = { `#${ quotes . length } ` } addedBy = { lastQuote . addedBy } dateAdded = { dateAdded } />
409442 < hr />
410443 </ > ,
411444 { name : `viewquote-${ message . parent . status . userid } ` }
@@ -426,9 +459,9 @@ export const command: PSCommand = {
426459 const pageNum = arg ? parseInt ( arg ) || 1 : 1 ;
427460 const startIndex = ( pageNum - 1 ) * PAGE_SIZE ;
428461 const endIndex = startIndex + PAGE_SIZE ;
429- const pagedQuotes : QuoteCollection = quotes
462+ const pagedQuotes : IndexedQuoteModel [ ] = quotes
430463 . slice ( startIndex , endIndex )
431- . map ( ( quote , index ) => [ startIndex + index + 1 , quote . quote ] ) ;
464+ . map ( ( quote , index ) => [ startIndex + index + 1 , quote ] ) ;
432465
433466 if ( ! pagedQuotes . length ) throw new ChatError ( 'Invalid page number.' as ToTranslate ) ;
434467
@@ -457,9 +490,9 @@ export const command: PSCommand = {
457490 const pageNum = arg ? parseInt ( arg ) || 1 : 1 ;
458491 const startIndex = ( pageNum - 1 ) * PAGE_SIZE ;
459492 const endIndex = startIndex + PAGE_SIZE ;
460- const pageQuotes : QuoteCollection = quotes
493+ const pageQuotes : IndexedQuoteModel [ ] = quotes
461494 . slice ( startIndex , endIndex )
462- . map ( ( quote , index ) => [ startIndex + index + 1 , quote . quote ] ) ;
495+ . map ( ( quote , index ) => [ startIndex + index + 1 , quote ] ) ;
463496
464497 if ( ! pageQuotes . length ) throw new ChatError ( 'Invalid page number.' as ToTranslate ) ;
465498
@@ -527,11 +560,20 @@ export const command: PSCommand = {
527560 toDelete = matching [ 0 ] ;
528561 indexToDelete = quotes . indexOf ( toDelete ) ;
529562 }
563+ const dateAdded = Temporal . Instant . fromEpochMilliseconds ( quotes [ indexToDelete ] . at . getTime ( ) )
564+ . toZonedDateTimeISO ( 'UTC' )
565+ . toPlainDate ( )
566+ . toLocaleString ( 'en-GB' ) ;
530567
531568 broadcastHTML (
532569 < >
533570 < hr />
534- < FormatQuote quote = { quotes [ indexToDelete ] . quote } header = { `Deleting #${ indexToDelete + 1 } :` } />
571+ < FormatQuote
572+ quote = { quotes [ indexToDelete ] . quote }
573+ header = { `Deleting #${ indexToDelete + 1 } :` }
574+ addedBy = { quotes [ indexToDelete ] . addedBy }
575+ dateAdded = { dateAdded }
576+ />
535577 < hr />
536578 </ >
537579 ) ;
@@ -580,10 +622,15 @@ export const command: PSCommand = {
580622 throw new ChatError ( 'Invalid quote index.' as ToTranslate ) ;
581623 }
582624 const quote = quotes [ index - 1 ] ;
625+ const dateAdded = Temporal . Instant . fromEpochMilliseconds ( quote . at . getTime ( ) )
626+ . toZonedDateTimeISO ( 'UTC' )
627+ . toPlainDate ( )
628+ . toLocaleString ( 'en-GB' ) ;
629+
583630 return broadcastHTML (
584631 < >
585632 < hr />
586- < FormatQuote quote = { quote . quote } header = { `#${ index } ` } />
633+ < FormatQuote quote = { quote . quote } header = { `#${ index } ` } addedBy = { quote . addedBy } dateAdded = { dateAdded } />
587634 < hr />
588635 </ > ,
589636 { name : `viewquote-${ message . parent . status . userid } ` }
0 commit comments