import { thousandsSeparator, toHHMMSS, timeSince } from '@squeebot/core/lib/common'; import { approximateB16Color, Formatter } from '@squeebot/core/lib/types'; export class IRCFormatter extends Formatter { public formatting = { bold: {start: '\u0002', end: '\u000F'}, italics: {start: '\u0016', end: '\u000F'}, emphasis: {start: '\u0016', end: '\u000F'}, underline: {start: '\u001F', end: '\u000F'}, action: {start: '\x01ACTION ', end: '\x01'}, }; public colorEscape = '\u000F'; public colors: {[key: string]: string} = { black: '\u00031', darkblue: '\u00032', green: '\u00033', red: '\u00034', brown: '\u00035', purple: '\u00036', gold: '\u00037', yellow: '\u00038', limegreen: '\u00039', cyan: '\u000310', lightblue: '\u000311', blue: '\u000312', pink: '\u000313', darkgray: '\u000314', gray: '\u000315', grey: '\u000315', white: '\u00030', }; public color(color: string, msg: string): string { // Approximate a hex color to one of IRC colors if (color.indexOf('#') === 0) { color = approximateB16Color(color); } if (!this.supportColors) { return msg; } if (!this.colors[color]) { return msg; } return this.colors[color] + msg + this.colorEscape; } public strip(msg: string): string { return msg.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x0F\x02\x16\x1F]/g, ''); } compose(objs: any): any { const str = []; for (const i in objs) { const elem = objs[i]; const elemType = elem[0]; let elemValue = elem[1]; const elemParams = elem[2]; if (!elemValue) { continue; } let valueColor = null; // Special types if (elemParams && elemParams.type) { switch (elemParams.type) { case 'time': elemValue = new Date(elemValue).toString(); break; case 'metric': elemValue = thousandsSeparator(elemValue); break; case 'timesince': elemValue = timeSince(elemValue); break; case 'duration': elemValue = toHHMMSS(elemValue); break; case 'description': valueColor = 'blue'; elemValue = `"${elemValue}"`; break; } } // Currently, disregard image fields. if (elemType === 'image') { continue; } // Bold value if (elemType === 'bold' || elemType === 'b' || elemType === 'strong') { elemValue = this.format('bold', elemValue); } // Italic value if (elemType === 'italic' || elemType === 'i' || elemType === 'em' || elemType === 'emphasis') { elemValue = this.format('italic', elemValue); } // Underlined value if (elemType === 'underline' || elemType === 'ul') { elemValue = this.format('underline', elemValue); } // Colorize the value if (elemParams && elemParams.color) { valueColor = elemParams.color; } // Add the label, if present if (elemParams && elemParams.label) { // Set label color to default let labelColor = 'green'; if (elemParams.color) { labelColor = elemParams.color; } if (!valueColor) { valueColor = 'blue'; } // Handle array label // Prefer the icon over the text version. let label = elemParams.label; if (typeof label === 'object') { label = label[0]; } else { label = label + ':'; } if (valueColor && valueColor === labelColor) { str.push(this.color(valueColor, label + ' ' + elemValue)); } else { str.push(this.color(labelColor, label) + ' ' + (valueColor ? this.color(valueColor, elemValue) : elemValue)); } } else { str.push(valueColor ? this.color(valueColor, elemValue) : elemValue); } } // May return an object, but your protocol must support it. return str.join(' '); } }