fix: made .mention() work with tagged templates
This commit is contained in:
parent
733a1ab84f
commit
9ed51fd996
13 changed files with 63 additions and 22 deletions
|
@ -157,7 +157,6 @@ import { setProfilePhoto } from './methods/users/set-profile-photo'
|
||||||
import { unblockUser } from './methods/users/unblock-user'
|
import { unblockUser } from './methods/users/unblock-user'
|
||||||
import { updateProfile } from './methods/users/update-profile'
|
import { updateProfile } from './methods/users/update-profile'
|
||||||
import { updateUsername } from './methods/users/update-username'
|
import { updateUsername } from './methods/users/update-username'
|
||||||
import { IMessageEntityParser } from './parser'
|
|
||||||
import { Readable } from 'stream'
|
import { Readable } from 'stream'
|
||||||
import {
|
import {
|
||||||
ArrayWithTotal,
|
ArrayWithTotal,
|
||||||
|
@ -171,6 +170,7 @@ import {
|
||||||
Dialog,
|
Dialog,
|
||||||
FileDownloadParameters,
|
FileDownloadParameters,
|
||||||
GameHighScore,
|
GameHighScore,
|
||||||
|
IMessageEntityParser,
|
||||||
InputFileLike,
|
InputFileLike,
|
||||||
InputInlineResult,
|
InputInlineResult,
|
||||||
InputMediaLike,
|
InputMediaLike,
|
||||||
|
|
|
@ -6,7 +6,6 @@ export {
|
||||||
} from '@mtcute/core'
|
} from '@mtcute/core'
|
||||||
export * from '@mtcute/tl/errors'
|
export * from '@mtcute/tl/errors'
|
||||||
|
|
||||||
export * from './parser'
|
|
||||||
export * from './types'
|
export * from './types'
|
||||||
export * from './client'
|
export * from './client'
|
||||||
export * from './utils/peer-utils'
|
export * from './utils/peer-utils'
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
|
||||||
// @copy
|
|
||||||
import { IMessageEntityParser } from '../parser'
|
|
||||||
|
|
||||||
// @copy
|
// @copy
|
||||||
import { Readable } from 'stream'
|
import { Readable } from 'stream'
|
||||||
|
|
||||||
|
@ -41,7 +38,8 @@ import {
|
||||||
ArrayWithTotal,
|
ArrayWithTotal,
|
||||||
BotCommands,
|
BotCommands,
|
||||||
MessageMedia,
|
MessageMedia,
|
||||||
RawDocument
|
RawDocument,
|
||||||
|
IMessageEntityParser
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
|
||||||
// @copy
|
// @copy
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IMessageEntityParser } from '../../parser'
|
import { IMessageEntityParser } from '../../types'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
|
|
||||||
// @extension
|
// @extension
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { IMessageEntityParser } from '../../parser'
|
import { MtCuteError, IMessageEntityParser } from '../../types'
|
||||||
import { MtCuteError } from '../../types'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a given {@link IMessageEntityParser} as a parse mode
|
* Register a given {@link IMessageEntityParser} as a parse mode
|
||||||
|
|
|
@ -7,5 +7,6 @@ export * from './peers'
|
||||||
export * from './misc'
|
export * from './misc'
|
||||||
|
|
||||||
export * from './errors'
|
export * from './errors'
|
||||||
|
export * from './parser'
|
||||||
export { MaybeDynamic, ArrayWithTotal } from './utils'
|
export { MaybeDynamic, ArrayWithTotal } from './utils'
|
||||||
export { MaybeAsync, PartialExcept, PartialOnly } from '@mtcute/core'
|
export { MaybeAsync, PartialExcept, PartialOnly } from '@mtcute/core'
|
||||||
|
|
|
@ -38,3 +38,19 @@ export interface IMessageEntityParser {
|
||||||
*/
|
*/
|
||||||
unparse(text: string, entities: ReadonlyArray<MessageEntity>): string
|
unparse(text: string, entities: ReadonlyArray<MessageEntity>): string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw string that will not be escaped when passing
|
||||||
|
* to tagged template helpers (like `html` and `md`)
|
||||||
|
*/
|
||||||
|
export class RawString {
|
||||||
|
raw!: true
|
||||||
|
|
||||||
|
constructor (readonly value: string) {}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
return this.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RawString.prototype.raw = true
|
|
@ -8,6 +8,7 @@ import { makeInspectable } from '../utils'
|
||||||
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
||||||
import { ChatLocation } from './chat-location'
|
import { ChatLocation } from './chat-location'
|
||||||
import { InputMediaLike } from '../media'
|
import { InputMediaLike } from '../media'
|
||||||
|
import { RawString } from '../parser'
|
||||||
|
|
||||||
export namespace Chat {
|
export namespace Chat {
|
||||||
/**
|
/**
|
||||||
|
@ -548,7 +549,7 @@ export class Chat {
|
||||||
* msg.replyText(`Hello, ${msg.chat.mention()`)
|
* msg.replyText(`Hello, ${msg.chat.mention()`)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
mention(text?: string | null, parseMode?: string | null): string {
|
mention(text?: string | null, parseMode?: string | null): string | RawString {
|
||||||
if (this.user) return this.user.mention(text, parseMode)
|
if (this.user) return this.user.mention(text, parseMode)
|
||||||
|
|
||||||
if (!text && this.username) {
|
if (!text && this.username) {
|
||||||
|
@ -560,7 +561,7 @@ export class Chat {
|
||||||
|
|
||||||
if (!parseMode) parseMode = this.client['_defaultParseMode']
|
if (!parseMode) parseMode = this.client['_defaultParseMode']
|
||||||
|
|
||||||
return this.client.getParseMode(parseMode).unparse(text, [
|
return new RawString(this.client.getParseMode(parseMode).unparse(text, [
|
||||||
{
|
{
|
||||||
raw: undefined as any,
|
raw: undefined as any,
|
||||||
type: 'text_link',
|
type: 'text_link',
|
||||||
|
@ -568,7 +569,7 @@ export class Chat {
|
||||||
length: text.length,
|
length: text.length,
|
||||||
url: `https://t.me/${this.username}`
|
url: `https://t.me/${this.username}`
|
||||||
},
|
},
|
||||||
])
|
]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { MtCuteArgumentError } from '../errors'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { InputMediaLike } from '../media'
|
import { InputMediaLike } from '../media'
|
||||||
|
import { RawString } from '../parser'
|
||||||
|
|
||||||
export namespace User {
|
export namespace User {
|
||||||
/**
|
/**
|
||||||
|
@ -290,7 +291,7 @@ export class User {
|
||||||
* msg.replyText(`Hello, ${msg.sender.mention()`)
|
* msg.replyText(`Hello, ${msg.sender.mention()`)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
mention(text?: string | null, parseMode?: string | null): string {
|
mention(text?: string | null, parseMode?: string | null): string | RawString {
|
||||||
if (!text && this.username) {
|
if (!text && this.username) {
|
||||||
return `@${this.username}`
|
return `@${this.username}`
|
||||||
}
|
}
|
||||||
|
@ -298,7 +299,7 @@ export class User {
|
||||||
if (!text) text = this.displayName
|
if (!text) text = this.displayName
|
||||||
if (!parseMode) parseMode = this.client['_defaultParseMode']
|
if (!parseMode) parseMode = this.client['_defaultParseMode']
|
||||||
|
|
||||||
return this.client.getParseMode(parseMode).unparse(text, [
|
return new RawString(this.client.getParseMode(parseMode).unparse(text, [
|
||||||
{
|
{
|
||||||
raw: undefined as any,
|
raw: undefined as any,
|
||||||
type: 'text_mention',
|
type: 'text_mention',
|
||||||
|
@ -306,7 +307,7 @@ export class User {
|
||||||
length: text.length,
|
length: text.length,
|
||||||
userId: this.id,
|
userId: this.id,
|
||||||
},
|
},
|
||||||
])
|
]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { IMessageEntityParser, MessageEntity } from '@mtcute/client'
|
import type { IMessageEntityParser, MessageEntity, RawString } from '@mtcute/client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { Parser } from 'htmlparser2'
|
import { Parser } from 'htmlparser2'
|
||||||
import bigInt from 'big-integer'
|
import bigInt from 'big-integer'
|
||||||
|
@ -13,10 +13,11 @@ const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|
|
||||||
* const escaped = html`<b>${user.displayName}</b>`
|
* const escaped = html`<b>${user.displayName}</b>`
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function html(strings: TemplateStringsArray, ...sub: string[]): string {
|
export function html(strings: TemplateStringsArray, ...sub: (string | RawString)[]): string {
|
||||||
let str = ''
|
let str = ''
|
||||||
sub.forEach((it, idx) => {
|
sub.forEach((it, idx) => {
|
||||||
str += strings[idx] + HtmlMessageEntityParser.escape(it)
|
if (typeof it === 'string') it = HtmlMessageEntityParser.escape(it)
|
||||||
|
str += strings[idx] + it
|
||||||
})
|
})
|
||||||
return str + strings[strings.length - 1]
|
return str + strings[strings.length - 1]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { describe, it } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { HtmlMessageEntityParser, html } from '../src'
|
import { HtmlMessageEntityParser, html } from '../src'
|
||||||
import { MessageEntity } from '@mtcute/client'
|
import { MessageEntity, RawString } from '@mtcute/client'
|
||||||
import bigInt from 'big-integer'
|
import bigInt from 'big-integer'
|
||||||
|
|
||||||
const createEntity = <T extends tl.TypeMessageEntity['_']>(
|
const createEntity = <T extends tl.TypeMessageEntity['_']>(
|
||||||
|
@ -460,5 +460,17 @@ describe('HtmlMessageEntityParser', () => {
|
||||||
expect(html`<b>text</b> ${unsafeString}`).eq('<b>text</b> <&>')
|
expect(html`<b>text</b> ${unsafeString}`).eq('<b>text</b> <&>')
|
||||||
expect(html`<b>${unsafeString}</b>`).eq('<b><&></b>')
|
expect(html`<b>${unsafeString}</b>`).eq('<b><&></b>')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should skip with RawString', () => {
|
||||||
|
const unsafeString2 = '<&>'
|
||||||
|
const unsafeString = new RawString('<&>')
|
||||||
|
|
||||||
|
expect(html`${unsafeString}`).eq('<&>')
|
||||||
|
expect(html`${unsafeString} ${unsafeString2}`).eq('<&> <&>')
|
||||||
|
expect(html`${unsafeString} <b>text</b>`).eq('<&> <b>text</b>')
|
||||||
|
expect(html`<b>text</b> ${unsafeString}`).eq('<b>text</b> <&>')
|
||||||
|
expect(html`<b>${unsafeString}</b>`).eq('<b><&></b>')
|
||||||
|
expect(html`<b>${unsafeString} ${unsafeString2}</b>`).eq('<b><&> <&></b>')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { IMessageEntityParser, MessageEntity } from '@mtcute/client'
|
import type { IMessageEntityParser, MessageEntity } from '@mtcute/client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import bigInt from 'big-integer'
|
import bigInt from 'big-integer'
|
||||||
|
import { RawString } from '@mtcute/client'
|
||||||
|
|
||||||
const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/
|
const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/
|
||||||
|
|
||||||
|
@ -21,10 +22,11 @@ const TO_BE_ESCAPED = /[*_\-~`[\\\]]/g
|
||||||
* const escaped = md`**${user.displayName}**`
|
* const escaped = md`**${user.displayName}**`
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function md(strings: TemplateStringsArray, ...sub: string[]): string {
|
export function md(strings: TemplateStringsArray, ...sub: (string | RawString)[]): string {
|
||||||
let str = ''
|
let str = ''
|
||||||
sub.forEach((it, idx) => {
|
sub.forEach((it, idx) => {
|
||||||
str += strings[idx] + MarkdownMessageEntityParser.escape(it)
|
if (typeof it === 'string') it = MarkdownMessageEntityParser.escape(it as string)
|
||||||
|
str += strings[idx] + it
|
||||||
})
|
})
|
||||||
return str + strings[strings.length - 1]
|
return str + strings[strings.length - 1]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { describe, it } from 'mocha'
|
import { describe, it } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { MessageEntity } from '@mtcute/client'
|
import { MessageEntity, RawString } from '@mtcute/client'
|
||||||
import { MarkdownMessageEntityParser, md } from '../src'
|
import { MarkdownMessageEntityParser, md } from '../src'
|
||||||
import bigInt from 'big-integer'
|
import bigInt from 'big-integer'
|
||||||
|
|
||||||
|
@ -657,5 +657,16 @@ describe('MarkdownMessageEntityParser', () => {
|
||||||
expect(md`**text** ${unsafeString}`).eq('**text** \\_\\_\\[\\]\\_\\_')
|
expect(md`**text** ${unsafeString}`).eq('**text** \\_\\_\\[\\]\\_\\_')
|
||||||
expect(md`**${unsafeString}**`).eq('**\\_\\_\\[\\]\\_\\_**')
|
expect(md`**${unsafeString}**`).eq('**\\_\\_\\[\\]\\_\\_**')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should skip with RawString', () => {
|
||||||
|
const unsafeString2 = '__[]__'
|
||||||
|
const unsafeString = new RawString('__[]__')
|
||||||
|
|
||||||
|
expect(md`${unsafeString}`).eq('__[]__')
|
||||||
|
expect(md`${unsafeString} ${unsafeString2}`).eq('__[]__ \\_\\_\\[\\]\\_\\_')
|
||||||
|
expect(md`${unsafeString} **text**`).eq('__[]__ **text**')
|
||||||
|
expect(md`**text** ${unsafeString}`).eq('**text** __[]__')
|
||||||
|
expect(md`**${unsafeString} ${unsafeString2}**`).eq('**__[]__ \\_\\_\\[\\]\\_\\_**')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue