Files

152 lines
5.4 KiB
JavaScript

import { moment } from '../../../lib.js';
import { chat } from '../../../script.js';
import { timestampToMoment } from '../../utils.js';
import { MacroRegistry, MacroCategory, MacroValueType } from '../engine/MacroRegistry.js';
/**
* Registers time/date related macros and utilities.
*/
export function registerTimeMacros() {
// Time and date macros
MacroRegistry.registerMacro('time', {
category: MacroCategory.TIME,
// Optional single list argument: UTC offset, e.g. {{time::UTC+2}}
unnamedArgs: [
{
name: 'offset',
optional: true,
defaultValue: 'null',
type: MacroValueType.STRING,
sampleValue: 'UTC+2',
description: 'UTC offset in the format UTC±(offset).',
},
],
description: 'Current local time, or UTC offset when called as {{time::UTC±(offset)}}',
returns: 'A time string in the format HH:mm.',
displayOverride: '{{time::[UTC±(offset)]}}',
exampleUsage: ['{{time}}', '{{time::UTC+2}}', '{{time::UTC-7}}'],
handler: ({ unnamedArgs: [offsetSpec] }) => {
if (!offsetSpec) return moment().format('LT');
const match = /^UTC([+-]\d+)$/.exec(offsetSpec);
if (!match) return moment().format('LT');
const offset = Number.parseInt(match[1], 10);
if (Number.isNaN(offset)) return moment().format('LT');
return moment().utc().utcOffset(offset).format('LT');
},
});
MacroRegistry.registerMacro('date', {
category: MacroCategory.TIME,
description: 'Current local date as a string in the local short format.',
returns: 'Current local date in local short format.',
handler: () => moment().format('LL'),
});
MacroRegistry.registerMacro('weekday', {
category: MacroCategory.TIME,
description: 'Current weekday name.',
returns: 'Current weekday name.',
handler: () => moment().format('dddd'),
});
MacroRegistry.registerMacro('isotime', {
category: MacroCategory.TIME,
description: 'Current time in HH:mm format.',
returns: 'Current time in HH:mm format.',
handler: () => moment().format('HH:mm'),
});
MacroRegistry.registerMacro('isodate', {
category: MacroCategory.TIME,
description: 'Current date in YYYY-MM-DD format.',
returns: 'Current date in YYYY-MM-DD format.',
handler: () => moment().format('YYYY-MM-DD'),
});
MacroRegistry.registerMacro('datetimeformat', {
category: MacroCategory.TIME,
unnamedArgs: [
{
name: 'format',
sampleValue: 'YYYY-MM-DD HH:mm:ss',
description: 'Moment.js format string.',
type: 'string',
},
],
description: 'Formats the current date/time using the given moment.js format string.',
returns: 'Formatted date/time string.',
exampleUsage: ['{{datetimeformat::YYYY-MM-DD HH:mm:ss}}', '{{datetimeformat::LLLL}}'],
handler: ({ unnamedArgs: [format] }) => moment().format(format),
});
MacroRegistry.registerMacro('idleDuration', {
aliases: [{ alias: 'idle_duration', visible: false }],
category: MacroCategory.TIME,
description: 'Human-readable duration since the last user message.',
returns: 'Human-readable duration since the last user message.',
handler: () => getTimeSinceLastMessage(),
});
// Time difference between two values
MacroRegistry.registerMacro('timeDiff', {
category: MacroCategory.TIME,
unnamedArgs: [
{
name: 'left',
sampleValue: '2023-01-01 12:00:00',
description: 'Left time value.',
type: 'string',
},
{
name: 'right',
sampleValue: '2023-01-01 15:00:00',
description: 'Right time value.',
type: 'string',
},
],
description: 'Human-readable difference between two times. Order of times does not matter, it will return the absolute difference.',
returns: 'Human-readable difference between two times.',
displayOverride: '{{timeDiff::left::right}}', // Shorten this, otherwise it's too long. Full dates don't really help for understanding the macro.
exampleUsage: ['{{ timeDiff :: 2023-01-01 12:00:00 :: 2023-01-01 15:00:00 }}'],
handler: ({ unnamedArgs: [left, right] }) => {
const diff = moment.duration(moment(left).diff(moment(right)));
return diff.humanize(true);
},
});
}
function getTimeSinceLastMessage() {
const now = moment();
if (Array.isArray(chat) && chat.length > 0) {
let lastMessage;
let takeNext = false;
for (let i = chat.length - 1; i >= 0; i--) {
const message = chat[i];
if (message.is_system) {
continue;
}
if (message.is_user && takeNext) {
lastMessage = message;
break;
}
takeNext = true;
}
if (lastMessage?.send_date) {
const lastMessageDate = timestampToMoment(lastMessage.send_date);
const duration = moment.duration(now.diff(lastMessageDate));
return duration.humanize();
}
}
return 'just now';
}