UNPKG

@gramio/format

Version:

Library for formatting text for Telegram Bot API

493 lines (488 loc) 19.1 kB
'use strict'; class FormattableString { /** Text of FormattableString (auto covert to it if entities is unsupported)*/ text; /** Entities of FormattableString */ entities; /** Create new FormattableString */ constructor(text, entities) { this.text = text; this.entities = entities; } /** Create new FormattableString */ static from(text, entities) { return new FormattableString(text, entities); } toString() { return this.text; } toJSON() { return this.text; } // ![INFO] - https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html#instanceof-narrowing-through-symbolhasinstance static [Symbol.hasInstance](value) { return !!value && typeof value === "object" && "text" in value && "entities" in value; } } function getFormattable(str) { if (str instanceof FormattableString) return str; return new FormattableString(str.toString(), []); } const FormattableMap = { sendMessage: (params) => { if (params.text instanceof FormattableString) { params.entities = params.text.entities; params.text = params.text.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, copyMessage: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendPhoto: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendAudio: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendDocument: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendVideo: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendAnimation: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendVoice: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendVideoNote: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendMediaGroup: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } if (params.media.length) params.media = params.media.map( (x) => "caption" in x && x.caption instanceof FormattableString ? { ...x, caption: x.caption.text, caption_entities: x.caption.entities } : x ); return params; }, sendLocation: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendVenue: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendContact: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendPoll: (params) => { if (params.question instanceof FormattableString) { params.question_entities = params.question.entities; params.question = params.question.text; } if (params.explanation instanceof FormattableString) { params.explanation_entities = params.explanation.entities; params.explanation = params.explanation.text; } if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } if (params.options.length) params.options = params.options.map( (x) => "text" in x && x.text instanceof FormattableString ? { ...x, text: x.text.text, text_entities: x.text.entities } : x ); return params; }, sendDice: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, editMessageText: (params) => { if (params.text instanceof FormattableString) { params.entities = params.text.entities; params.text = params.text.text; } return params; }, editMessageCaption: (params) => { if (params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } return params; }, editMessageMedia: (params) => { if (params.media !== void 0 && "caption" in params.media && params.media.caption instanceof FormattableString) { params.media.caption_entities = params.media.caption.entities; params.media.caption = params.media.caption.text; } return params; }, sendSticker: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, // TODO: fix answerInlineQuery: (params) => { if (params.results?.length) params.results = params.results.map( (x) => "caption" in x && x.caption instanceof FormattableString ? { ...x, caption: x.caption.text, caption_entities: x.caption.entities } : x ); if (params.results?.length) params.results = params.results.map( (x) => "input_message_content" in x && x.input_message_content && "message_text" in x.input_message_content && x.input_message_content.message_text instanceof FormattableString ? { ...x, input_message_content: { ...x.input_message_content, message_text: x.input_message_content.message_text.text, entities: x.input_message_content.message_text.entities } } : x ); return params; }, savePreparedInlineMessage: (params) => { if ("caption" in params.result && params.result.caption instanceof FormattableString) { params.result.caption_entities = params.result.caption.entities; params.result.caption = params.result.caption.text; } if ("input_message_content" in params.result && params.result.input_message_content && "message_text" in params.result.input_message_content && params.result.input_message_content.message_text instanceof FormattableString) { params.result = { ...params.result, input_message_content: { ...params.result.input_message_content, message_text: params.result.input_message_content.message_text.text, entities: params.result.input_message_content.message_text.entities } }; } return params; }, sendGift: (params) => { if (params.text instanceof FormattableString) { params.text_entities = params.text.entities; params.text = params.text.text; } return params; }, answerWebAppQuery: (params) => { if (params.result !== void 0 && "caption" in params.result && params.result.caption instanceof FormattableString) { params.result.caption_entities = params.result.caption.entities; params.result.caption = params.result.caption.text; } if ("input_message_content" in params.result && params.result.input_message_content !== void 0 && "message_text" in params.result.input_message_content && params.result.input_message_content.message_text instanceof FormattableString) { params.result.input_message_content.entities = params.result.input_message_content.message_text.entities; params.result.input_message_content.message_text = params.result.input_message_content.message_text.text; } return params; }, sendInvoice: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, sendGame: (params) => { if (params.reply_parameters !== void 0 && "quote" in params.reply_parameters && params.reply_parameters.quote instanceof FormattableString) { params.reply_parameters.quote_entities = params.reply_parameters.quote.entities; params.reply_parameters.quote = params.reply_parameters.quote.text; } return params; }, giftPremiumSubscription: (params) => { if (params.text && params.text instanceof FormattableString) { params.text_entities = params.text.entities; params.text = params.text.text; } return params; }, postStory: (params) => { if (params.caption && params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } return params; }, editStory: (params) => { if (params.caption && params.caption instanceof FormattableString) { params.caption_entities = params.caption.entities; params.caption = params.caption.text; } return params; }, editMessageChecklist: (params) => { if (params.checklist.title instanceof FormattableString) { params.checklist.title_entities = params.checklist.title.entities; params.checklist.title = params.checklist.title.text; } if (params.checklist.tasks.length) { params.checklist.tasks = params.checklist.tasks.map((x) => { if (x.text instanceof FormattableString) { x.text_entities = x.text.entities; x.text = x.text.text; } return x; }); } return params; }, sendChecklist: (params) => { if (params.checklist.title instanceof FormattableString) { params.checklist.title_entities = params.checklist.title.entities; params.checklist.title = params.checklist.title.text; } if (params.checklist.tasks.length) { params.checklist.tasks = params.checklist.tasks.map((x) => { if (x.text instanceof FormattableString) { x.text_entities = x.text.entities; x.text = x.text.text; } return x; }); } return params; } }; function buildFormatter(type) { function formatter(first, ...rest) { if (Array.isArray(first) && Object.hasOwn(first, "raw")) { return formatter( format(first, ...rest) ); } const formattable = getFormattable(first); return new FormattableString(formattable.text, [ { type, offset: 0, length: formattable.text.length }, ...formattable.entities ]); } return formatter; } function buildFormatterWithArgs(type, ...keys) { return (str, ...args) => { const formattable = getFormattable(str); const formattableArgs = Object.fromEntries( keys.map((key, i) => [key, args[i]]) ); return new FormattableString(formattable.text, [ { type, offset: 0, length: formattable.text.length, ...formattableArgs }, ...formattable.entities ]); }; } const bold = buildFormatter("bold"); const italic = buildFormatter("italic"); const underline = buildFormatter("underline"); const strikethrough = buildFormatter("strikethrough"); const spoiler = buildFormatter("spoiler"); const blockquote = buildFormatter("blockquote"); const expandableBlockquote = buildFormatter("expandable_blockquote"); const code = buildFormatter("code"); const pre = buildFormatterWithArgs( "pre", "language" ); const link = buildFormatterWithArgs("text_link", "url"); const mention = buildFormatterWithArgs( "text_mention", // @ts-expect-error wrong typings.... but it's works fine "user" ); const customEmoji = buildFormatterWithArgs( "custom_emoji", "custom_emoji_id" ); function join(array, iterator, separator = ", ") { let text = ""; const entities = []; for (const [index, str] of array.map(iterator).entries()) { if (str instanceof FormattableString) entities.push( ...str.entities.map((e) => ({ ...e, offset: e.offset + text.length })) ); if (typeof str !== "undefined" && str !== null && str !== false) text += str.toString() + (index === array.length - 1 ? "" : separator); } return new FormattableString(text, entities); } function processDeeperFormat(offset, strings) { let text = ""; const entities = []; for (const str of strings) { if (Array.isArray(str)) { const [newText, newEntities] = processDeeperFormat(text.length, str); text += newText; entities.push(...newEntities); continue; } if (str instanceof FormattableString) entities.push( ...str.entities.map((e) => ({ ...e, offset: e.offset + text.length + offset })) ); text += str.toString(); } return [text, entities]; } function processRawFormat(stringParts, strings) { const entities = []; let text = ""; const length = Math.max(stringParts.length, strings.length); for (let index = 0; index < length; index++) { for (const str of [stringParts[index], strings[index]]) { if (Array.isArray(str)) { const [newText, newEntities] = processDeeperFormat(text.length, str); text += newText; entities.push(...newEntities); continue; } if (str instanceof FormattableString) entities.push( ...str.entities.map((e) => ({ ...e, offset: e.offset + text.length })) ); if (typeof str !== "undefined") text += str.toString(); } } return new FormattableString(text, entities); } function format(stringParts, ...strings) { return processRawFormat( stringParts.map((x) => x.replace(/(?!\n\s+\n)\n(?!\n)\s+/g, "\n")), strings ); } function formatSaveIndents(stringParts, ...strings) { return processRawFormat([...stringParts], strings); } exports.FormattableMap = FormattableMap; exports.FormattableString = FormattableString; exports.blockquote = blockquote; exports.bold = bold; exports.code = code; exports.customEmoji = customEmoji; exports.expandableBlockquote = expandableBlockquote; exports.format = format; exports.formatSaveIndents = formatSaveIndents; exports.getFormattable = getFormattable; exports.italic = italic; exports.join = join; exports.link = link; exports.mention = mention; exports.pre = pre; exports.spoiler = spoiler; exports.strikethrough = strikethrough; exports.underline = underline;