cool color and format utilities
This commit is contained in:
parent
2b027d57ad
commit
d11a983319
@ -1,4 +1,8 @@
|
||||
import { IRCBot } from '../bot';
|
||||
import {
|
||||
applyTextColor,
|
||||
wrapFormattedText,
|
||||
} from '../utility/message-formatting';
|
||||
import { NickServValidator } from '../utility/nickserv-validator';
|
||||
|
||||
const bot = new IRCBot({
|
||||
@ -29,7 +33,7 @@ bot.on('supported-modes', (supported) => {
|
||||
// bot.on('line', console.log);
|
||||
|
||||
bot.on('message', ({ message, to, nickname }) => {
|
||||
console.log(`[${to}] ${nickname}: ${message}`);
|
||||
console.log(`[${to}] ${nickname}: ${wrapFormattedText(message)}`);
|
||||
|
||||
if (message.startsWith('!test')) {
|
||||
nickserv
|
||||
@ -46,6 +50,11 @@ bot.on('message', ({ message, to, nickname }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.startsWith('!colors')) {
|
||||
bot.send(to, `${applyTextColor('blue', 'cool blue text!')}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.startsWith('!whois')) {
|
||||
bot.whois(nickname).then(console.log);
|
||||
return;
|
||||
|
@ -5,6 +5,7 @@ export * from './types/impl.interface';
|
||||
export * from './utility/collector';
|
||||
export * from './utility/estimate-prefix';
|
||||
export * from './utility/formatstr';
|
||||
export * from './utility/message-formatting';
|
||||
export * from './utility/mode-from-prefix';
|
||||
export * from './utility/nickserv-validator';
|
||||
export * from './utility/parser';
|
||||
|
@ -14,7 +14,7 @@ export type IRCCommunicatorEvents = {
|
||||
/**
|
||||
* Supported channel user modes from the server (e.g. `ohv: @%+`)
|
||||
*/
|
||||
'supported-modes': (modes: Record<string, unknown>) => void;
|
||||
'supported-modes': (modes: Record<string, string>) => void;
|
||||
/**
|
||||
* Everything this server supports. See IRC documentation for command `005` or `RPL_ISUPPORT` for more info.
|
||||
*/
|
||||
|
216
src/utility/message-formatting.ts
Normal file
216
src/utility/message-formatting.ts
Normal file
@ -0,0 +1,216 @@
|
||||
export const IRC_FMT_COLOR_MAP = {
|
||||
/**
|
||||
* IRC white `rgb(255,255,255)`
|
||||
*/
|
||||
white: '\u00030',
|
||||
/**
|
||||
* IRC black `rgb(0,0,0)`
|
||||
*/
|
||||
black: '\u00031',
|
||||
/**
|
||||
* IRC blue `rgb(0,0,127)`
|
||||
*/
|
||||
blue: '\u00032',
|
||||
/**
|
||||
* IRC green `rgb(0,147,0)`
|
||||
*/
|
||||
green: '\u00033',
|
||||
/**
|
||||
* IRC red `rgb(255,0,0)`
|
||||
*/
|
||||
red: '\u00034',
|
||||
/**
|
||||
* IRC brown `rgb(127,0,0)`
|
||||
*/
|
||||
brown: '\u00035',
|
||||
/**
|
||||
* IRC purple `rgb(156,0,156)`
|
||||
*/
|
||||
purple: '\u00036',
|
||||
/**
|
||||
* IRC orange `rgb(252,127,0)`
|
||||
*/
|
||||
orange: '\u00037',
|
||||
/**
|
||||
* IRC yellow `rgb(255,255,0)`
|
||||
*/
|
||||
yellow: '\u00038',
|
||||
/**
|
||||
* IRC light green `rgb(0,252,0)`
|
||||
*/
|
||||
lightgreen: '\u00039',
|
||||
/**
|
||||
* IRC cyan `rgb(0,147,147)`
|
||||
*/
|
||||
cyan: '\u000310',
|
||||
/**
|
||||
* IRC light cyan `rgb(0,255,255)`
|
||||
*/
|
||||
lightcyan: '\u000311',
|
||||
/**
|
||||
* IRC light blue `rgb(0,0,252)`
|
||||
*/
|
||||
lightblue: '\u000312',
|
||||
/**
|
||||
* IRC pink `rgb(255,0,255)`
|
||||
*/
|
||||
pink: '\u000313',
|
||||
/**
|
||||
* IRC grey `rgb(127,127,127)`
|
||||
*/
|
||||
grey: '\u000314',
|
||||
/**
|
||||
* IRC light grey `rgb(210,210,210)`
|
||||
*/
|
||||
lightgrey: '\u000315',
|
||||
};
|
||||
|
||||
/**
|
||||
* ^O character, color reset character
|
||||
*/
|
||||
export const IRC_FMT_RESET = '\u000F';
|
||||
|
||||
export const IRC_FMT_FORMAT_MAP = {
|
||||
/**
|
||||
* Normal text
|
||||
*/
|
||||
normal: '\u0000',
|
||||
/**
|
||||
* <ins>underline text</ins>, `^_`
|
||||
*/
|
||||
underline: '\u001F',
|
||||
/**
|
||||
* **bold text**, `^B`
|
||||
*/
|
||||
bold: '\u0002',
|
||||
/**
|
||||
* *italic text*, `^I`
|
||||
*/
|
||||
italics: '\u001D',
|
||||
/**
|
||||
* reverse color text, `^V`
|
||||
*/
|
||||
reverse: '\u0016',
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove color and format characters from a string.
|
||||
* @param str Text
|
||||
* @returns Stripped text
|
||||
*/
|
||||
export const stripFormatting = (str: string): string =>
|
||||
str.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x00-\x1F]/g, '');
|
||||
|
||||
/**
|
||||
* Colorize a string for sending.
|
||||
* @param color IRC color key
|
||||
* @param str Text to colorize
|
||||
* @returns Text with control characters
|
||||
*/
|
||||
export const applyTextColor = (
|
||||
color: keyof typeof IRC_FMT_COLOR_MAP,
|
||||
str: string,
|
||||
): string =>
|
||||
!IRC_FMT_COLOR_MAP[color]
|
||||
? str
|
||||
: `${IRC_FMT_COLOR_MAP[color]}${str}${IRC_FMT_RESET}`;
|
||||
|
||||
/**
|
||||
* Apply text formatting to a string for sending.
|
||||
* @param format IRC format key
|
||||
* @param str Text to format
|
||||
* @returns Text with control characters
|
||||
*/
|
||||
export const applyTextFormat = (
|
||||
format: keyof typeof IRC_FMT_FORMAT_MAP,
|
||||
str: string,
|
||||
): string =>
|
||||
!IRC_FMT_FORMAT_MAP[format]
|
||||
? str
|
||||
: `${IRC_FMT_FORMAT_MAP[format]}${str}${IRC_FMT_RESET}`;
|
||||
|
||||
const styleCheckRe = /[\x00-\x1F]/;
|
||||
const backRe = /^(\d{1,2})(,(\d{1,2}))?/;
|
||||
const colourKey = '\x03';
|
||||
const colourRe = /\x03/g;
|
||||
const colorKeys = Object.keys(IRC_FMT_COLOR_MAP);
|
||||
const fmtRegex: [string, RegExp][] = Object.keys(IRC_FMT_FORMAT_MAP).map(
|
||||
(key) => {
|
||||
const escaped = encodeURI(
|
||||
(IRC_FMT_FORMAT_MAP as Record<string, string>)[key],
|
||||
).replace('%', '\\x');
|
||||
return [key, new RegExp(escaped + '(.*?)(' + escaped + '|$)')];
|
||||
},
|
||||
);
|
||||
|
||||
export type IRCTextFormatWrapperFn = (
|
||||
text: string,
|
||||
foregroundColor?: string,
|
||||
backgroundColor?: string,
|
||||
textFormat?: string,
|
||||
) => string;
|
||||
|
||||
const wrap: IRCTextFormatWrapperFn = (text, fg, bg, fmt) =>
|
||||
`<format${fg ? ` color="${fg}"` : ''}${bg ? ` background="${bg}"` : ''}${
|
||||
fmt ? ` text="${fmt}"` : ''
|
||||
}>${text}</format>`;
|
||||
|
||||
/**
|
||||
* Wrap regions of text that have formatting or colors with a custom wrapper, e.g. HTML.
|
||||
* Defaults to a psuedo-XML style wrapper `<format color background text />`
|
||||
* @param line Text with control characters
|
||||
* @param wrapperFn Wrapper function to use
|
||||
* @returns Text with applied wrappers
|
||||
*/
|
||||
export function wrapFormattedText(line: string, wrapperFn = wrap): string {
|
||||
// Recheck
|
||||
if (!styleCheckRe.test(line)) return line;
|
||||
|
||||
// split up by the irc style break character ^O
|
||||
if (line.indexOf(IRC_FMT_RESET) >= 0) {
|
||||
return line
|
||||
.split(IRC_FMT_RESET)
|
||||
.map((value) => wrapFormattedText(value, wrapperFn))
|
||||
.join('');
|
||||
}
|
||||
|
||||
let result = line;
|
||||
const parseArr = result.split(colourKey);
|
||||
|
||||
for (let i = 0; i < parseArr.length; i++) {
|
||||
const text = parseArr[i];
|
||||
const match = text.match(backRe);
|
||||
const colour = match && colorKeys[+match[1]];
|
||||
let background = '';
|
||||
|
||||
if (!match || !colour) {
|
||||
// ^C (no colour) ending. Escape current colour and carry on
|
||||
background = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// set the background colour
|
||||
// we don't override the background local var to support nesting
|
||||
if (colorKeys[+match[3]]) {
|
||||
background = colorKeys[+match[3]];
|
||||
}
|
||||
|
||||
// update the parsed text result
|
||||
result = result.replace(
|
||||
colourKey + text,
|
||||
wrapperFn(text.slice(match[0].length), colour, background),
|
||||
);
|
||||
}
|
||||
|
||||
// Matching styles (italics/bold/underline)
|
||||
// if only colors were this easy...
|
||||
fmtRegex.forEach(function ([style, keyregex]) {
|
||||
if (result.indexOf(style) < 0) return;
|
||||
result = result.replace(keyregex, (match, text) =>
|
||||
wrapperFn(text, undefined, undefined, style),
|
||||
);
|
||||
});
|
||||
|
||||
// replace the reminent colour terminations and be done with it
|
||||
return result.replace(colourRe, '');
|
||||
}
|
Loading…
Reference in New Issue
Block a user