feat(client): sticker choosing typing event

also prettier fucked everything up, fixed that
This commit is contained in:
teidesu 2022-05-06 17:53:44 +03:00
parent 252f94a594
commit 9543f64558
20 changed files with 211 additions and 157 deletions

View file

@ -26,13 +26,15 @@ export async function _normalizeCommandScope(
const user = normalizeToInputUser(await this.resolvePeer(scope.user)) const user = normalizeToInputUser(await this.resolvePeer(scope.user))
if (!user) if (!user)
throw new MtInvalidPeerTypeError(scope.user, 'u"user" throw new MtInvalidPeerTypeError(scope.user, 'user')
; return {
_: 'b"botCommandScopePeerUser" peer: chat, return {
_: 'botCommandScopePeerUser',
peer: chat,
userId: user userId: user
} }
; } }
default: default:
assertNever(scope) assertNever(scope)
; } }
} }

View file

@ -5,7 +5,7 @@ import {
ChatEvent, PeersIndex, ChatEvent, PeersIndex,
} from '../../types' } from '../../types'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { assertNever, MaybeArray } from '@mtcute/core' import { assertNever, MaybeArray } from "@mtcute/core";
import { import {
normalizeToInputChannel, normalizeToInputChannel,
normalizeToInputUser, normalizeToInputUser,
@ -182,14 +182,17 @@ export async function* getChatEventLog(
case 'user_joined_invite': case 'user_joined_invite':
// not documented so idk, enable all // not documented so idk, enable all
serverFilter!.join = true serverFilter!.join = true
; serverFilter!.invite = true serverFilter!.invite = true
; serverFilter!.invites = true serverFilter!.invites = true
; break break
; case 'i"invite_deleted" case 'i"invite_edited" case 'i"invite_revoked" serverFilter!.invites = true case 'invite_deleted':
; break case 'invite_edited':
; default: case 'invite_revoked':
serverFilter!.invites = true
break
default:
assertNever(type) assertNever(type)
; } }
}) })
} else { } else {
serverFilter = params.filters serverFilter = params.filters

View file

@ -127,15 +127,18 @@ export async function getChatMembers(
case 'bots': case 'bots':
filter = { _: 'channelParticipantsBots' } filter = { _: 'channelParticipantsBots' }
break break
; case 'r"recent" filter = { _: 'c"channelParticipantsRecent" case 'recent':
; break filter = { _: 'channelParticipantsRecent' }
; case 'a"admins" filter = { _: 'c"channelParticipantsAdmins" break
; break case 'admins':
; case 'c"contacts" filter = { _: 'c"channelParticipantsContacts"q } filter = { _: 'channelParticipantsAdmins' }
; break break
; default: case 'contacts':
filter = { _: 'channelParticipantsContacts', q }
break
default:
assertNever(type) assertNever(type)
; } }
const res = await this.call({ const res = await this.call({
_: 'channels.getParticipants', _: 'channels.getParticipants',

View file

@ -80,11 +80,17 @@ export async function uploadMedia(
case 'inputMediaPhoto': case 'inputMediaPhoto':
case 'inputMediaPhotoExternal': case 'inputMediaPhotoExternal':
assertTypeIs('uploadMedia', res, 'messageMediaPhoto') assertTypeIs('uploadMedia', res, 'messageMediaPhoto')
assertTypeIs('u"uploadMedia"res.photo!, 'p"photo" assertTypeIs('uploadMedia', res.photo!, 'photo')
; return new Photo(this, res.photo)
; case 'i"inputMediaUploadedDocument" case 'i"inputMediaDocument" case 'i"inputMediaDocumentExternal" assertTypeIs('u"uploadMedia"res, 'm"messageMediaDocument" ; assertTypeIs('u"uploadMedia"res.document!, 'd"document" return new Photo(this, res.photo)
; return parseDocument(this, res.document) as any case 'inputMediaUploadedDocument':
; default: case 'inputMediaDocument':
case 'inputMediaDocumentExternal':
assertTypeIs('uploadMedia', res, 'messageMediaDocument')
assertTypeIs('uploadMedia', res.document!, 'document')
return parseDocument(this, res.document) as any
default:
assertNever(normMedia) assertNever(normMedia)
; } }
} }

View file

@ -71,15 +71,21 @@ export async function sendTyping(
case 'record_round': case 'record_round':
status = { _: 'sendMessageRecordRoundAction' } status = { _: 'sendMessageRecordRoundAction' }
break break
; case 'u"upload_round" status = { _: 's"sendMessageUploadRoundAction"progress } case 'upload_round':
; break status = { _: 'sendMessageUploadRoundAction', progress }
; case 's"speak_call" status = { _: 's"speakingInGroupCallAction" break
; break case 'speak_call':
; case 'h"history_import" status = { _: 's"sendMessageHistoryImportAction"progress } status = { _: 'speakingInGroupCallAction' }
; break break
; default: case 'history_import':
status = { _: 'sendMessageHistoryImportAction', progress }
break
case 'sticker':
status = { _: 'sendMessageChooseStickerAction' }
break
default:
assertNever(status) assertNever(status)
; } }
} }
await this.call({ await this.call({

View file

@ -218,19 +218,19 @@ export async function _fetchUpdatesState(this: TelegramClient): Promise<void> {
}) })
switch (diff._) { switch (diff._) {
case"updates.differenceEmpty"': case 'updates.differenceEmpty':
brea;k break
case"updates.differenceTooLong"': // shouldn't happen, but who knows? case 'updates.differenceTooLong': // shouldn't happen, but who knows?
;(state as tl.Mutable<tl.updates.TypeState>).pts = diff.pt;s ;(state as tl.Mutable<tl.updates.TypeState>).pts = diff.pts
brea;k break
case"updates.differenceSlice"': case 'updates.differenceSlice':
state = diff.intermediateStat;e state = diff.intermediateState
brea;k break
case"updates.difference"': case 'updates.difference':
state = diff.stat;e state = diff.state
brea;k break
default: default:
assertNever(diff;) assertNever(diff)
} }
this._qts = state.qts this._qts = state.qts
@ -1403,18 +1403,18 @@ export function _handleUpdate(
}) })
break break
case 'updates': case 'updates':
case "updatesCombined": case 'updatesCombined':
this._pendingUpdateContainers.add({ this._pendingUpdateContainers.add({
upd: update, upd: update,
seqStart: seqStart:
update._ === "updatesCombined" update._ === 'updatesCombined'
? update.seqStart ? update.seqStart
: update.seq, : update.seq,
seqEnd: update.seq seqEnd: update.seq,
}); })
break; break
default: default:
assertNever(update); assertNever(update)
} }
this._updatesLoopCv.notify() this._updatesLoopCv.notify()
@ -2259,17 +2259,17 @@ export async function _updatesLoop(this: TelegramClient): Promise<void> {
// first process pending containers // first process pending containers
while (this._pendingUpdateContainers.length) { while (this._pendingUpdateContainers.length) {
const { upd, seqStart, seqEnd } = const { upd, seqStart, seqEnd } =
this._pendingUpdateContainers.popFront()!; this._pendingUpdateContainers.popFront()!
switch (upd._) { switch (upd._) {
case "updatesTooLong": case 'updatesTooLong':
log.debug( log.debug(
"received updatesTooLong, fetching difference" 'received updatesTooLong, fetching difference'
); )
_fetchDifferenceLater.call(this, requestedDiff); _fetchDifferenceLater.call(this, requestedDiff)
break; break
case "updatesCombined": case 'updatesCombined':
case "updates": { case 'updates': {
if (seqStart !== 0) { if (seqStart !== 0) {
// https://t.me/tdlibchat/5843 // https://t.me/tdlibchat/5843
const nextLocalSeq = this._seq! + 1 const nextLocalSeq = this._seq! + 1
@ -2452,18 +2452,18 @@ export async function _updatesLoop(this: TelegramClient): Promise<void> {
this._pendingPtsUpdates.add({ this._pendingPtsUpdates.add({
update, update,
ptsBefore: upd.pts - upd.ptsCount, ptsBefore: upd.pts - upd.ptsCount,
pts: upd.pts pts: upd.pts,
}) })
break; break
} }
case "updateShortSentMessage": { case 'updateShortSentMessage': {
// should not happen // should not happen
log.warn("received updateShortSentMessage"); log.warn('received updateShortSentMessage')
break; break
} }
default: default:
assertNever(upd); assertNever(upd)
} }
} }

View file

@ -283,13 +283,17 @@ export namespace BotInlineMessage {
_: 'inputBotInlineMessageGame', _: 'inputBotInlineMessageGame',
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup), replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
} }
case 'c"contact" return { case 'contact':
_: 'i"inputBotInlineMessageMediaContact" phoneNumber: obj.phone, return {
_: 'inputBotInlineMessageMediaContact',
phoneNumber: obj.phone,
firstName: obj.firstName, firstName: obj.firstName,
lastName: obj.lastName ?? ''"" vcard: obj.vcard ?? ''"" replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup), lastName: obj.lastName ?? '',
} vcard: obj.vcard ?? '',
; default: replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
default:
assertNever(obj) assertNever(obj)
; } }
} }
} }

View file

@ -396,14 +396,17 @@ export namespace BotKeyboard {
} }
case 'force_reply': case 'force_reply':
return { return {
_: 'r"replyKeyboardForceReply" singleUse: obj.singleUse, _: 'replyKeyboardForceReply',
singleUse: obj.singleUse,
selective: obj.selective, selective: obj.selective,
} }
; case 'i"inline" return { case 'inline':
_: 'r"replyInlineMarkup" rows: _2dToRows(obj.buttons), return {
} _: 'replyInlineMarkup',
; default: rows: _2dToRows(obj.buttons),
}
default:
assertNever(obj) assertNever(obj)
; } }
} }
} }

View file

@ -15,9 +15,17 @@ export function _callDiscardReasonFromTl(
raw: tl.TypePhoneCallDiscardReason raw: tl.TypePhoneCallDiscardReason
): CallDiscardReason { ): CallDiscardReason {
switch (raw._) { switch (raw._) {
case 'p"phoneCallDiscardReasonMissed" return 'm"missed"; case 'p"phoneCallDiscardReasonDisconnect" return 'd"disconnect"; case 'p"phoneCallDiscardReasonHangup" return 'h"hangup"; case 'p"phoneCallDiscardReasonBusy" return 'b"busy"; default: case 'phoneCallDiscardReasonMissed':
return 'missed'
case 'phoneCallDiscardReasonDisconnect':
return 'disconnect'
case 'phoneCallDiscardReasonHangup':
return 'hangup'
case 'phoneCallDiscardReasonBusy':
return 'busy'
default:
assertNever(raw) assertNever(raw)
; } }
} }
/** @internal */ /** @internal */
@ -25,15 +33,15 @@ export function _callDiscardReasonToTl(
r: CallDiscardReason r: CallDiscardReason
): tl.TypePhoneCallDiscardReason { ): tl.TypePhoneCallDiscardReason {
switch (r) { switch (r) {
case "missed": case 'missed':
return { _: "phoneCallDiscardReasonMissed" }; return { _: 'phoneCallDiscardReasonMissed' }
case "disconnect": case 'disconnect':
return { _: "phoneCallDiscardReasonDisconnect" }; return { _: 'phoneCallDiscardReasonDisconnect' }
case "hangup": case 'hangup':
return { _: "phoneCallDiscardReasonHangup" }; return { _: 'phoneCallDiscardReasonHangup' }
case "busy": case 'busy':
return { _: "phoneCallDiscardReasonBusy" }; return { _: 'phoneCallDiscardReasonBusy' }
default: default:
assertNever(r); assertNever(r)
} }
} }

View file

@ -1,8 +1,11 @@
import { User, Chat, InputPeerLike, PeersIndex } from '../peers' import { User, Chat, InputPeerLike, PeersIndex } from '../peers'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { BotKeyboard, ReplyMarkup } from '../bots' import { BotKeyboard, ReplyMarkup } from '../bots'
import { assertNever, getMarkedPeerId, toggleChannelIdMark } from '@mtcute/core' import { assertNever, getMarkedPeerId, toggleChannelIdMark } from "@mtcute/core";
import { MtArgumentError, MtTypeAssertionError } from '../errors' import {
MtArgumentError,
MtTypeAssertionError,
} from '../errors'
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { MessageEntity } from './message-entity' import { MessageEntity } from './message-entity'
import { makeInspectable } from '../utils' import { makeInspectable } from '../utils'

View file

@ -9,7 +9,7 @@ import { ChatPermissions } from './chat-permissions'
import { ChatLocation } from './chat-location' import { ChatLocation } from './chat-location'
import { ChatInviteLink } from './chat-invite-link' import { ChatInviteLink } from './chat-invite-link'
import { PeersIndex } from './index' import { PeersIndex } from './index'
import { toggleChannelIdMark } from '@mtcute/core' import { toggleChannelIdMark } from "@mtcute/core"
export namespace ChatEvent { export namespace ChatEvent {

View file

@ -19,6 +19,7 @@
* - `upload_round`: User is uploading a round video message * - `upload_round`: User is uploading a round video message
* - `speak_call`: *undocumented* User is speaking in a group call * - `speak_call`: *undocumented* User is speaking in a group call
* - `history_import`: *undocumented* User is importing history * - `history_import`: *undocumented* User is importing history
* - `sticker`: User is choosing a sticker
*/ */
export type TypingStatus = export type TypingStatus =
| 'typing' | 'typing'
@ -36,3 +37,4 @@ export type TypingStatus =
| 'upload_round' | 'upload_round'
| 'speak_call' | 'speak_call'
| 'history_import' | 'history_import'
| 'sticker'

View file

@ -99,6 +99,8 @@ export class UserTypingUpdate {
return 'speak_call' return 'speak_call'
case 'sendMessageHistoryImportAction': case 'sendMessageHistoryImportAction':
return 'history_import' return 'history_import'
case 'sendMessageChooseStickerAction':
return 'sticker'
} }
throw new MtUnsupportedError() throw new MtUnsupportedError()

View file

@ -4,8 +4,8 @@ import {
encodeUrlSafeBase64, encodeUrlSafeBase64,
parseUrlSafeBase64, parseUrlSafeBase64,
TlBinaryReader, TlBinaryReader,
TlBinaryWriter, TlBinaryWriter
} from '@mtcute/core' } from "@mtcute/core";
export function parseInlineMessageId( export function parseInlineMessageId(
id: string id: string
@ -39,19 +39,19 @@ export function encodeInlineMessageId(
case 'inputBotInlineMessageID': case 'inputBotInlineMessageID':
writer = TlBinaryWriter.manualAlloc(20) writer = TlBinaryWriter.manualAlloc(20)
writer.int(id.dcId) writer.int(id.dcId)
; writer.long(id.id) writer.long(id.id)
; writer.long(id.accessHash) writer.long(id.accessHash)
; break break
; case '"inputBotInlineMessageID64" case 'inputBotInlineMessageID64':
writer = TlBinaryWriter.manualAlloc(24) writer = TlBinaryWriter.manualAlloc(24)
; writer.int(id.dcId) writer.int(id.dcId)
; writer.long(id.ownerId) writer.long(id.ownerId)
; writer.int(id.id) writer.int(id.id)
; writer.long(id.accessHash) writer.long(id.accessHash)
; break break
; default: default:
assertNever(id) assertNever(id)
; } }
return encodeUrlSafeBase64(writer.result()) return encodeUrlSafeBase64(writer.result())
} }

View file

@ -35,15 +35,17 @@ export function normalizeToInputPeer(
channelId: res.channelId, channelId: res.channelId,
msgId: res.msgId, msgId: res.msgId,
peer: res.peer, peer: res.peer,
} }
case 'i"inputUserFromMessage" return { case 'inputUserFromMessage':
_: 'i"inputPeerUserFromMessage" userId: res.userId, return {
_: 'inputPeerUserFromMessage',
userId: res.userId,
msgId: res.msgId, msgId: res.msgId,
peer: res.peer, peer: res.peer,
} }
; default: default:
assertNever(res) assertNever(res)
; } }
} }
export function normalizeToInputUser( export function normalizeToInputUser(

View file

@ -1,5 +1,5 @@
import { CallbackQuery, Message } from '@mtcute/client' import { CallbackQuery, Message } from '@mtcute/client'
import { assertNever, MaybeAsync } from '@mtcute/core' import { assertNever, MaybeAsync } from "@mtcute/core";
/** /**
* Function that determines how the state key is derived. * Function that determines how the state key is derived.
@ -29,10 +29,17 @@ export const defaultStateKeyDelegate: StateKeyDelegate = (
): string | null => { ): string | null => {
if (upd.constructor === Message) { if (upd.constructor === Message) {
switch (upd.chat.type) { switch (upd.chat.type) {
case 'p"private" case 'b"bot" case 'c"channel" return upd.chat.id + ''""; case 'g"group" case 's"supergroup" case 'g"gigagroup" return `${upd.chat.id}_${upd.sender.id}` case 'private':
; default: case 'bot':
case 'channel':
return upd.chat.id + ''
case 'group':
case 'supergroup':
case 'gigagroup':
return `${upd.chat.id}_${upd.sender.id}`
default:
assertNever(upd.chat.type) assertNever(upd.chat.type)
; } }
} }
if (upd.constructor === CallbackQuery) { if (upd.constructor === CallbackQuery) {

View file

@ -1,7 +1,7 @@
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { tdFileId, tdFileId as td } from './types' import { tdFileId, tdFileId as td } from './types'
import { parseFileId } from './parse' import { parseFileId } from './parse'
import { assertNever, getBasicPeerType, markedPeerIdToBare } from '@mtcute/core' import { assertNever, getBasicPeerType, markedPeerIdToBare } from "@mtcute/core";
import FileType = tdFileId.FileType import FileType = tdFileId.FileType
import Long from 'long' import Long from 'long'
@ -169,16 +169,19 @@ export function fileIdToInputFileLocation(
volumeId: loc.source.volumeId, volumeId: loc.source.volumeId,
localId: loc.source.localId, localId: loc.source.localId,
} }
case 's"stickerSetThumbnailVersion" return { case 'stickerSetThumbnailVersion':
_: 'i"inputStickerSetThumb" stickerset: { return {
_: 'i"inputStickerSetID" id: loc.source.id, _: 'inputStickerSetThumb',
stickerset: {
_: 'inputStickerSetID',
id: loc.source.id,
accessHash: loc.source.accessHash, accessHash: loc.source.accessHash,
}, },
thumbVersion: loc.source.version thumbVersion: loc.source.version
} }
; default: default:
assertNever(loc.source) assertNever(loc.source)
; } }
throw new td.ConversionError('inputFileLocation') throw new td.ConversionError('inputFileLocation')
} }
@ -205,16 +208,16 @@ export function fileIdToInputFileLocation(
} }
} else { } else {
return { return {
_: "inputDocumentFileLocation", _: 'inputDocumentFileLocation',
fileReference: fileId.fileReference, fileReference: fileId.fileReference,
id: loc.id, id: loc.id,
accessHash: loc.accessHash, accessHash: loc.accessHash,
thumbSize: "" thumbSize: '',
}; }
} }
} }
default: default:
assertNever(loc); assertNever(loc)
} }
} }

View file

@ -1,5 +1,5 @@
import { tdFileId, tdFileId as td } from './types' import { tdFileId, tdFileId as td } from './types'
import { assertNever, encodeUrlSafeBase64 } from '@mtcute/core' import { assertNever, encodeUrlSafeBase64 } from "@mtcute/core";
import { telegramRleEncode } from './utils' import { telegramRleEncode } from './utils'
import FileType = tdFileId.FileType import FileType = tdFileId.FileType
import { TlBinaryWriter } from '@mtcute/tl-runtime' import { TlBinaryWriter } from '@mtcute/tl-runtime'
@ -141,8 +141,7 @@ export function toUniqueFileId(
break break
} }
case 'web': case 'web':
writer = TlBinaryWriter.alloc( writer = TlBinaryWriter.alloc({},
{},
Buffer.byteLength(inputLocation.url, 'utf-8') + 8 Buffer.byteLength(inputLocation.url, 'utf-8') + 8
) )
writer.int(type) writer.int(type)

View file

@ -1,5 +1,5 @@
import { tdFileId as td } from './types' import { tdFileId as td } from './types'
import { assertNever, encodeUrlSafeBase64 } from '@mtcute/core' import { assertNever, encodeUrlSafeBase64 } from "@mtcute/core";
import { telegramRleEncode } from './utils' import { telegramRleEncode } from './utils'
import { TlBinaryWriter } from '@mtcute/tl-runtime' import { TlBinaryWriter } from '@mtcute/tl-runtime'
@ -86,25 +86,27 @@ export function toFileId(
writer.int(8) writer.int(8)
writer.long(loc.source.id) writer.long(loc.source.id)
writer.long(loc.source.accessHash) writer.long(loc.source.accessHash)
; writer.long(loc.source.volumeId) writer.long(loc.source.volumeId)
; writer.int(loc.source.localId) writer.int(loc.source.localId)
; break break
; case 'st"stickerSetThumbnailVersion" writer.int(9) case 'stickerSetThumbnailVersion':
; writer.long(loc.source.id) writer.int(9)
; writer.long(loc.source.accessHash) writer.long(loc.source.id)
; writer.int(loc.source.version) writer.long(loc.source.accessHash)
; break writer.int(loc.source.version)
; default: break
default:
assertNever(loc.source) assertNever(loc.source)
; } }
break break
; case 'co"common" writer.long(loc.id) case 'common':
; writer.long(loc.accessHash) writer.long(loc.id)
; break writer.long(loc.accessHash)
; default: break
default:
assertNever(loc) assertNever(loc)
; } }
return encodeUrlSafeBase64( return encodeUrlSafeBase64(
Buffer.concat([telegramRleEncode(writer.result()), SUFFIX]) Buffer.concat([telegramRleEncode(writer.result()), SUFFIX])

View file

@ -3,8 +3,8 @@ import {
BaseTcpTransport, BaseTcpTransport,
TransportState, TransportState,
tl, tl,
assertNever, assertNever
} from '@mtcute/core' } from "@mtcute/core";
import { connect } from 'net' import { connect } from 'net'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
@ -439,18 +439,17 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport {
code in SOCKS5_ERRORS code in SOCKS5_ERRORS
? SOCKS5_ERRORS[code] ? SOCKS5_ERRORS[code]
: `Unknown error code: 0x${code.toString( : `Unknown error code: 0x${code.toString(
16 16
)}` )}`
this._socket!.emit( this._socket!.emit(
'"error" 'error',
new SocksProxyConnectionError(this._proxy, msg) new SocksProxyConnectionError(this._proxy, msg)
) )
; } }
break break
; } }
default: default: assertNever(state)
assertNever(state) }
; }
} }
this.log.debug( this.log.debug(