Created
November 23, 2021 23:44
-
-
Save watzon/60b475ed5c0f427f29775bc9d4164cb2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Api, TelegramClient } from 'telegram' | |
import { EditMessageParams, SendMessageParams } from 'telegram/client/messages'; | |
import { Entity, EntityLike } from 'telegram/define' | |
import { EventBuilder, EventCommon } from "telegram/events/common"; | |
import { toSignedLittleBuffer } from 'telegram/Helpers'; | |
import { getInputPeer, _getEntityPair } from 'telegram/Utils'; | |
import { escapeRegExp } from '../utils'; | |
export interface NewCallbackQueryInterface { | |
chats: EntityLike[]; | |
func?: { (event: NewCallbackQueryEvent): boolean }; | |
fromUsers: EntityLike[]; | |
blacklistUsers: EntityLike[]; | |
pattern?: RegExp | string | ((data: string) => void); | |
} | |
export const NewCallbackQueryDefaults: NewCallbackQueryInterface = { | |
chats: [], | |
fromUsers: [], | |
blacklistUsers: [], | |
} | |
/** | |
* Occurs whenever you sign in as a bot and a user | |
* clicks one of the inline buttons on your messages. | |
* Note that the `chats` parameter will **not** work with normal | |
* IDs or peers if the clicked inline button comes from a "via bot" | |
* message. The `chats` parameter also supports checking against the | |
* `chat_instance` which should be used for inline callbacks. | |
* | |
* @example | |
* ```ts | |
* async function printQuery(event: NewCallbackQueryEvent) { | |
* // TODO | |
* } | |
* ``` | |
*/ | |
export class CallbackQueryEvent extends EventBuilder { | |
match?: RegExp | |
private _noCheck: boolean | |
constructor(inlineQueryParams: Partial<NewCallbackQueryInterface> = {}) { | |
const { chats, func, pattern } = inlineQueryParams; | |
super({ chats, func, blacklistChats: false }) | |
if (typeof pattern === 'string') { | |
this.match = new RegExp(`^${escapeRegExp(pattern)}$`) | |
} else if (pattern instanceof RegExp) { | |
this.match = pattern | |
} | |
this._noCheck = [ | |
this.chats, | |
this.func, | |
this.match | |
].every((i) => i === null || i === undefined) | |
} | |
build(update: Api.TypeUpdate | Api.TypeUpdates, others: any = null) { | |
if (update instanceof Api.UpdateBotCallbackQuery) { | |
return new NewCallbackQueryEvent(update, update.peer, update.msgId); | |
} else if (update instanceof Api.UpdateInlineBotCallbackQuery) { | |
const b = toSignedLittleBuffer(update.msgId.id, 8) | |
const msgId = b.readInt32LE() | |
const peerId = b.readInt32LE(4) | |
const peer = peerId < 0 | |
? new Api.PeerChannel({ channelId: -peerId }) | |
: new Api.PeerUser({ userId: peerId }) | |
return new NewCallbackQueryEvent(update, peer, msgId) | |
} | |
} | |
filter(event: NewCallbackQueryEvent) { | |
if (this._noCheck) return event; | |
if (this.chats) { | |
let inside = this.chats.includes(event.query.chatInstance as unknown as EntityLike) | |
if (event.chatId) { | |
inside = inside || this.chats.includes(event.chatId) | |
} | |
if (inside === this.blacklistChats) { | |
return | |
} | |
} | |
if (this.match) { | |
const data = new TextDecoder().decode(event.query.data) | |
const result = this.match.exec(data) | |
if (result) { | |
event.patternMatch = result | |
} else { | |
return | |
} | |
} | |
if (this.func) { | |
return this.func(event) | |
} | |
return true | |
} | |
} | |
export interface AnswerCallbackQueryParams { | |
message: string; | |
cacheTime: number; | |
url: string; | |
alert: boolean; | |
} | |
export class NewCallbackQueryEvent extends EventCommon { | |
/** | |
* The original {@link Api.UpdateBotCallbackQuery} or {@link Api.UpdateInlineBotCallbackQuery} object. | |
*/ | |
query: Api.UpdateBotCallbackQuery | Api.UpdateInlineBotCallbackQuery; | |
/** | |
* The regex match object returned from successfully matching the | |
* query `data` with the provided pattern in your event handler. | |
*/ | |
patternMatch: RegExpMatchArray | undefined; | |
private _message: Api.Message | undefined; | |
private _answered: boolean; | |
private _senderId: number | undefined; | |
private _sender: Entity | undefined; | |
private _inputSender: Api.TypeInputPeer | undefined; | |
constructor(query: Api.UpdateBotCallbackQuery | Api.UpdateInlineBotCallbackQuery, peer: Api.TypePeer, msgId: number) { | |
super({ | |
msgId, | |
chatPeer: peer, | |
broadcast: false, | |
}); | |
this.query = query; | |
this.patternMatch = undefined; | |
this._senderId = query.userId; | |
this._message = undefined; | |
this._answered = false; | |
} | |
_setClient(client: TelegramClient) { | |
super._setClient(client); | |
const [sender, inputSender] = _getEntityPair(this._senderId, this._entities, client._entityCache); | |
this._sender = sender; | |
this._inputSender = inputSender; | |
} | |
get id() { | |
return this.query.queryId; | |
} | |
get messageId() { | |
return this._messageId; | |
} | |
get data() { | |
return this.query.data; | |
} | |
get chatInstance() { | |
return this.query.chatInstance; | |
} | |
async getMessage() { | |
if (this._message) { | |
return this._message; | |
} | |
const chat = this.isChannel ? await this.getInputChat() : undefined; | |
if (!chat) return; | |
const messages = await this._client.getMessages(chat, { ids: this._messageId }) | |
this._message = messages[0]; | |
return this._message; | |
} | |
async _refetchSender() { | |
if (this._entities.has(this._senderId)) { | |
this._sender = this._entities.get(this._senderId); | |
} | |
if (!this._sender) return; | |
this._inputSender = getInputPeer(this._chat) | |
if (!(this._inputSender.hasOwnProperty('accessHash'))) { | |
try { | |
this._inputSender = this._client._entityCache.get(this._senderId); | |
} catch (e) { | |
const m = await this.getMessage(); | |
if (m) { | |
this._sender = m._sender; | |
this._inputSender = m._inputSender; | |
} | |
} | |
} | |
} | |
async answer({ message, cacheTime, url, alert }: Partial<AnswerCallbackQueryParams> = {}) { | |
if (this._answered) return; | |
return await this._client.invoke(new Api.messages.SetBotCallbackAnswer({ | |
queryId: this.query.queryId, | |
cacheTime, | |
alert, | |
message, | |
url, | |
})).then((res) => { | |
this._answered = true; | |
return res; | |
}) | |
} | |
get viaInline() { | |
return this.query instanceof Api.UpdateInlineBotCallbackQuery | |
} | |
async respond(params: SendMessageParams = {}) { | |
await this.answer() | |
await this._client.sendMessage(await this.getInputChat(), params) | |
} | |
async reply(params: SendMessageParams = {}) { | |
await this.answer() | |
params.replyTo = this.messageId | |
await this._client.sendMessage(await this.getInputChat(), params) | |
} | |
async edit(params: EditMessageParams) { | |
if ((this.query.msgId as any) instanceof Api.InputBotInlineMessageID) { | |
return await this._client.editMessage(this.messageId, params).then(async (res) => { | |
await this.answer(); | |
return res; | |
}) | |
} else { | |
return await this._client.editMessage(await this.getInputChat(), params).then(async (res) => { | |
await this.answer(); | |
return res; | |
}) | |
} | |
} | |
async delete({ revoke } = { revoke: false }) { | |
if (this._client) { | |
return this._client.deleteMessages( | |
await this.getInputChat(), | |
[this.messageId as any], | |
{ revoke }) | |
} | |
} | |
get sender() { | |
return this._sender; | |
} | |
async getSender() { | |
if ( | |
this._client && | |
(!this._sender || | |
(this._sender instanceof Api.Channel && this._sender.min)) && | |
(await this.getInputSender()) | |
) { | |
try { | |
this._sender = await this._client.getEntity(this._inputSender!); | |
} catch (e) { | |
await this._refetchSender(); | |
} | |
} | |
return this._sender; | |
} | |
get inputSender() { | |
if (!this._inputSender && this._senderId && this._client) { | |
try { | |
this._inputSender = this._client._entityCache.get( | |
this._senderId | |
); | |
} catch (e) {} | |
} | |
return this._inputSender; | |
} | |
async getInputSender() { | |
if (!this.inputSender && this._senderId && this._client) { | |
await this._refetchSender(); | |
} | |
return this._inputSender; | |
} | |
get senderId() { | |
return this._senderId; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment