UNPKG

regraf

Version:

Continuation of best modern Telegram Bot Framework

307 lines (261 loc) 7.68 kB
class Markup { forceReply (value = true) { this.force_reply = value return this } removeKeyboard (value = true) { this.remove_keyboard = value return this } inputFieldPlaceholder (placeholder) { this.input_field_placeholder = placeholder return this } selective (value = true) { this.selective = value return this } extra (options) { return { reply_markup: { ...this }, ...options } } keyboard (buttons, options) { const keyboard = buildKeyboard(buttons, { columns: 1, ...options }) if (keyboard && keyboard.length > 0) { this.keyboard = keyboard } return this } resize (value = true) { this.resize_keyboard = value return this } oneTime (value = true) { this.one_time_keyboard = value return this } inlineKeyboard (buttons, options) { const keyboard = buildKeyboard(buttons, { columns: buttons.length, ...options }) if (keyboard && keyboard.length > 0) { this.inline_keyboard = keyboard } return this } button (text, hide) { return Markup.button(text, hide) } contactRequestButton (text, hide) { return Markup.contactRequestButton(text, hide) } locationRequestButton (text, hide) { return Markup.locationRequestButton(text, hide) } pollRequestButton (text, type, hide) { return Markup.pollRequestButton(text, type, hide) } urlButton (text, url, hide) { return Markup.urlButton(text, url, hide) } callbackButton (text, data, hide) { return Markup.callbackButton(text, data, hide) } switchToChatButton (text, value, hide) { return Markup.switchToChatButton(text, value, hide) } switchToCurrentChatButton (text, value, hide) { return Markup.switchToCurrentChatButton(text, value, hide) } gameButton (text, hide) { return Markup.gameButton(text, hide) } payButton (text, hide) { return Markup.payButton(text, hide) } loginButton (text, url, opts, hide) { return Markup.loginButton(text, url, opts, hide) } static removeKeyboard (value) { return new Markup().removeKeyboard(value) } static forceReply (value) { return new Markup().forceReply(value) } static keyboard (buttons, options) { return new Markup().keyboard(buttons, options) } static inlineKeyboard (buttons, options) { return new Markup().inlineKeyboard(buttons, options) } static resize (value = true) { return new Markup().resize(value) } static inputFieldPlaceholder (placeholder) { return new Markup().inputFieldPlaceholder(placeholder) } static selective (value = true) { return new Markup().selective(value) } static oneTime (value = true) { return new Markup().oneTime(value) } static button (text, hide = false) { return { text: text, hide: hide } } static contactRequestButton (text, hide = false) { return { text: text, request_contact: true, hide: hide } } static locationRequestButton (text, hide = false) { return { text: text, request_location: true, hide: hide } } static pollRequestButton (text, type, hide = false) { return { text: text, request_poll: { type }, hide: hide } } static urlButton (text, url, hide = false) { return { text: text, url: url, hide: hide } } static callbackButton (text, data, hide = false) { return { text: text, callback_data: data, hide: hide } } static switchToChatButton (text, value, hide = false) { return { text: text, switch_inline_query: value, hide: hide } } static switchToCurrentChatButton (text, value, hide = false) { return { text: text, switch_inline_query_current_chat: value, hide: hide } } static gameButton (text, hide = false) { return { text: text, callback_game: {}, hide: hide } } static payButton (text, hide = false) { return { text: text, pay: true, hide: hide } } static loginButton (text, url, opts = {}, hide = false) { return { text: text, login_url: { ...opts, url: url }, hide: hide } } static formatHTML (text = '', entities = []) { const available = [...entities] const opened = [] const result = [] for (let offset = 0; offset < text.length; offset++) { while (true) { const index = available.findIndex((entity) => entity.offset === offset) if (index === -1) { break } const entity = available[index] switch (entity.type) { case 'bold': result.push('<b>') break case 'italic': result.push('<i>') break case 'code': result.push('<code>') break case 'pre': if (entity.language) { result.push(`<pre><code class="language-${entity.language}">`) } else { result.push('<pre>') } break case 'strikethrough': result.push('<s>') break case 'underline': result.push('<u>') break case 'text_mention': result.push(`<a href="tg://user?id=${entity.user.id}">`) break case 'text_link': result.push(`<a href="${entity.url}">`) break } opened.unshift(entity) available.splice(index, 1) } result.push(escapeHTML(text[offset])) while (true) { const index = opened.findIndex((entity) => entity.offset + entity.length - 1 === offset) if (index === -1) { break } const entity = opened[index] switch (entity.type) { case 'bold': result.push('</b>') break case 'italic': result.push('</i>') break case 'code': result.push('</code>') break case 'pre': if (entity.language) { result.push('</code></pre>') } else { result.push('</pre>') } break case 'strikethrough': result.push('</s>') break case 'underline': result.push('</u>') break case 'text_mention': case 'text_link': result.push('</a>') break } opened.splice(index, 1) } } return result.join('') } } const escapedChars = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' } function escapeHTML (string) { const chars = [...string] return chars.map(char => escapedChars[char] || char).join('') } function buildKeyboard (buttons, options) { const result = [] if (!Array.isArray(buttons)) { return result } if (buttons.find(Array.isArray)) { return buttons.map(row => row.filter((button) => !button.hide)) } const wrapFn = options.wrap ? options.wrap : (btn, index, currentRow) => currentRow.length >= options.columns let currentRow = [] let index = 0 for (const btn of buttons.filter((button) => !button.hide)) { if (wrapFn(btn, index, currentRow) && currentRow.length > 0) { result.push(currentRow) currentRow = [] } currentRow.push(btn) index++ } if (currentRow.length > 0) { result.push(currentRow) } return result } module.exports = Markup