Blame Raw
· · · 151 lines (5.4 KB)
0 contributors
1import { moment } from '../../../lib.js';
2import { chat } from '../../../script.js';
3import { timestampToMoment } from '../../utils.js';
4import { MacroRegistry, MacroCategory, MacroValueType } from '../engine/MacroRegistry.js';
5
6/**
7 * Registers time/date related macros and utilities.
8 */
9export function registerTimeMacros() {
10 // Time and date macros
11 MacroRegistry.registerMacro('time', {
12 category: MacroCategory.TIME,
13 // Optional single list argument: UTC offset, e.g. {{time::UTC+2}}
14 unnamedArgs: [
15 {
16 name: 'offset',
17 optional: true,
18 defaultValue: 'null',
19 type: MacroValueType.STRING,
20 sampleValue: 'UTC+2',
21 description: 'UTC offset in the format UTC±(offset).',
22 },
23 ],
24 description: 'Current local time, or UTC offset when called as {{time::UTC±(offset)}}',
25 returns: 'A time string in the format HH:mm.',
26 displayOverride: '{{time::[UTC±(offset)]}}',
27 exampleUsage: ['{{time}}', '{{time::UTC+2}}', '{{time::UTC-7}}'],
28 handler: ({ unnamedArgs: [offsetSpec] }) => {
29 if (!offsetSpec) return moment().format('LT');
30
31 const match = /^UTC([+-]\d+)$/.exec(offsetSpec);
32 if (!match) return moment().format('LT');
33
34 const offset = Number.parseInt(match[1], 10);
35 if (Number.isNaN(offset)) return moment().format('LT');
36
37 return moment().utc().utcOffset(offset).format('LT');
38 },
39 });
40
41 MacroRegistry.registerMacro('date', {
42 category: MacroCategory.TIME,
43 description: 'Current local date as a string in the local short format.',
44 returns: 'Current local date in local short format.',
45 handler: () => moment().format('LL'),
46 });
47
48 MacroRegistry.registerMacro('weekday', {
49 category: MacroCategory.TIME,
50 description: 'Current weekday name.',
51 returns: 'Current weekday name.',
52 handler: () => moment().format('dddd'),
53 });
54
55 MacroRegistry.registerMacro('isotime', {
56 category: MacroCategory.TIME,
57 description: 'Current time in HH:mm format.',
58 returns: 'Current time in HH:mm format.',
59 handler: () => moment().format('HH:mm'),
60 });
61
62 MacroRegistry.registerMacro('isodate', {
63 category: MacroCategory.TIME,
64 description: 'Current date in YYYY-MM-DD format.',
65 returns: 'Current date in YYYY-MM-DD format.',
66 handler: () => moment().format('YYYY-MM-DD'),
67 });
68
69 MacroRegistry.registerMacro('datetimeformat', {
70 category: MacroCategory.TIME,
71 unnamedArgs: [
72 {
73 name: 'format',
74 sampleValue: 'YYYY-MM-DD HH:mm:ss',
75 description: 'Moment.js format string.',
76 type: 'string',
77 },
78 ],
79 description: 'Formats the current date/time using the given moment.js format string.',
80 returns: 'Formatted date/time string.',
81 exampleUsage: ['{{datetimeformat::YYYY-MM-DD HH:mm:ss}}', '{{datetimeformat::LLLL}}'],
82 handler: ({ unnamedArgs: [format] }) => moment().format(format),
83 });
84
85 MacroRegistry.registerMacro('idleDuration', {
86 aliases: [{ alias: 'idle_duration', visible: false }],
87 category: MacroCategory.TIME,
88 description: 'Human-readable duration since the last user message.',
89 returns: 'Human-readable duration since the last user message.',
90 handler: () => getTimeSinceLastMessage(),
91 });
92
93 // Time difference between two values
94 MacroRegistry.registerMacro('timeDiff', {
95 category: MacroCategory.TIME,
96 unnamedArgs: [
97 {
98 name: 'left',
99 sampleValue: '2023-01-01 12:00:00',
100 description: 'Left time value.',
101 type: 'string',
102 },
103 {
104 name: 'right',
105 sampleValue: '2023-01-01 15:00:00',
106 description: 'Right time value.',
107 type: 'string',
108 },
109 ],
110 description: 'Human-readable difference between two times. Order of times does not matter, it will return the absolute difference.',
111 returns: 'Human-readable difference between two times.',
112 displayOverride: '{{timeDiff::left::right}}', // Shorten this, otherwise it's too long. Full dates don't really help for understanding the macro.
113 exampleUsage: ['{{ timeDiff :: 2023-01-01 12:00:00 :: 2023-01-01 15:00:00 }}'],
114 handler: ({ unnamedArgs: [left, right] }) => {
115 const diff = moment.duration(moment(left).diff(moment(right)));
116 return diff.humanize(true);
117 },
118 });
119}
120
121function getTimeSinceLastMessage() {
122 const now = moment();
123
124 if (Array.isArray(chat) && chat.length > 0) {
125 let lastMessage;
126 let takeNext = false;
127
128 for (let i = chat.length - 1; i >= 0; i--) {
129 const message = chat[i];
130
131 if (message.is_system) {
132 continue;
133 }
134
135 if (message.is_user && takeNext) {
136 lastMessage = message;
137 break;
138 }
139
140 takeNext = true;
141 }
142
143 if (lastMessage?.send_date) {
144 const lastMessageDate = timestampToMoment(lastMessage.send_date);
145 const duration = moment.duration(now.diff(lastMessageDate));
146 return duration.humanize();
147 }
148 }
149
150 return 'just now';
151}