refactor: prefer switches over ifs when possible

This commit is contained in:
teidesu 2021-05-16 14:32:36 +03:00
parent f9336841ab
commit e6e28399b0
28 changed files with 546 additions and 574 deletions

View file

@ -1,4 +1,4 @@
import { MtCuteError, User, TermsOfService } from '../../types'
import { User, TermsOfService } from '../../types'
import { TelegramClient } from '../../client'
import { assertTypeIs } from '../../utils/type-assertion'
import { normalizePhoneNumber } from '../../utils/misc-utils'

View file

@ -1,5 +1,6 @@
import { TelegramClient } from '../../client'
import { Chat, MtCuteTypeAssertionError } from '../../types'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Create a new broadcast channel
@ -21,13 +22,7 @@ export async function createChannel(
broadcast: true,
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'channels.createChannel',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('channels.createChannel', res)
this._handleUpdate(res)

View file

@ -3,6 +3,7 @@ import { MaybeArray } from '@mtcute/core'
import { Chat, InputPeerLike, MtCuteTypeAssertionError } from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Create a legacy group chat
@ -34,13 +35,7 @@ export async function createGroup(
users: peers
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'messages.createChat',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('messages.createChat', res)
this._handleUpdate(res)

View file

@ -1,5 +1,6 @@
import { TelegramClient } from '../../client'
import { Chat, MtCuteTypeAssertionError } from '../../types'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Create a new supergroup
@ -20,13 +21,7 @@ export async function createSupergroup(
megagroup: true
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'channels.createChannel',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('channels.createChannel', res)
this._handleUpdate(res)

View file

@ -3,6 +3,7 @@ import { Chat, MtCuteTypeAssertionError } from '../../types'
import { assertTypeIs } from '../../utils/type-assertion'
import { getMarkedPeerId } from '@mtcute/core'
import { tl } from 'packages/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Get nearby chats
@ -25,13 +26,7 @@ export async function getNearbyChats(
},
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'contacts.getLocated',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('contacts.getLocated', res)
if (!res.updates.length) return []

View file

@ -1,5 +1,6 @@
import { TelegramClient } from '../../client'
import { ChatMember, InputPeerLike } from '../../types'
import { isInputPeerChat } from '../../utils/peer-utils'
/**
* Iterate through chat members
@ -45,7 +46,7 @@ export async function* iterChatMembers(
if (!members.length) break
if (chat._ === 'inputPeerChat') {
if (isInputPeerChat(chat)) {
total = members.length
}

View file

@ -9,6 +9,7 @@ import {
INVITE_LINK_REGEX,
normalizeToInputChannel,
} from '../../utils/peer-utils'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Join a channel or supergroup
@ -29,13 +30,7 @@ export async function joinChat(
_: 'messages.importChatInvite',
hash: m[1],
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'messages.importChatInvite',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('messages.importChatInvite', res)
this._handleUpdate(res)
@ -50,13 +45,8 @@ export async function joinChat(
_: 'channels.joinChannel',
channel: peer,
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'channels.joinChannel',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('channels.joinChannel', res)
this._handleUpdate(res)

View file

@ -1,6 +1,7 @@
import { TelegramClient } from '../../client'
import { Chat, InputPeerLike, MtCuteTypeAssertionError } from '../../types'
import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Change default chat permissions for all members.
@ -32,13 +33,7 @@ export async function setChatDefaultPermissions(
}
})
if (!(res._ === 'updates' || res._ === 'updatesCombined')) {
throw new MtCuteTypeAssertionError(
'messages.editChatDefaultBannedRights',
'updates | updatesCombined',
res._
)
}
assertIsUpdatesGroup('messages.editChatDefaultBannedRights', res)
this._handleUpdate(res)

View file

@ -2,6 +2,7 @@ import { TelegramClient } from '../../client'
import { InputPeerLike, MtCuteInvalidPeerTypeError, MtCuteTypeAssertionError, User } from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Add an existing Telegram user as a contact
@ -48,12 +49,7 @@ export async function addContact(
addPhonePrivacyException: !!params.sharePhone
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'addContact',
'updates | updatesCombined',
res._
)
assertIsUpdatesGroup('contacts.addContact', res)
this._handleUpdate(res)

View file

@ -3,6 +3,7 @@ import { MaybeArray } from '@mtcute/core'
import { InputPeerLike, MtCuteInvalidPeerTypeError, MtCuteTypeAssertionError, User } from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Delete a single contact from your Telegram contacts list
@ -56,12 +57,7 @@ export async function deleteContacts(
id: inputPeers
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'addContact',
'updates | updatesCombined',
res._
)
assertIsUpdatesGroup('contacts.deleteContacts', res)
if (single && !res.updates.length) return null

View file

@ -3,6 +3,7 @@ import { InputPeerLike, MtCuteTypeAssertionError, Poll } from '../../types'
import { createUsersChatsIndex } from '../../utils/peer-utils'
import bigInt from 'big-integer'
import { assertTypeIs } from '../../utils/type-assertion'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Close a poll sent by you.
@ -35,12 +36,7 @@ export async function closePoll(
},
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'messages.editMessage',
'updates | updatesCombined',
res._
)
assertIsUpdatesGroup('messages.editMessage', res)
this._handleUpdate(res, true)

View file

@ -2,6 +2,7 @@ import { TelegramClient } from '../../client'
import { tl } from '@mtcute/tl'
import { Message, MtCuteTypeAssertionError } from '../../types'
import { createUsersChatsIndex } from '../../utils/peer-utils'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/** @internal */
export function _findMessageInUpdate(
@ -9,12 +10,7 @@ export function _findMessageInUpdate(
res: tl.TypeUpdates,
isEdit = false
): Message {
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'_findMessageInUpdate',
'updates | updatesCombined',
res._
)
assertIsUpdatesGroup('_findMessageInUpdate', res)
this._handleUpdate(res, true)

View file

@ -12,6 +12,7 @@ import {
createUsersChatsIndex,
} from '../../utils/peer-utils'
import { normalizeDate, randomUlong } from '../../utils/misc-utils'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Forward a single message.
@ -229,12 +230,7 @@ export async function forwardMessages(
),
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'messages.forwardMessages',
'updates | updatesCombined',
res._
)
assertIsUpdatesGroup('messages.forwardMessages', res)
this._handleUpdate(res, true)
@ -242,12 +238,12 @@ export async function forwardMessages(
const forwarded: Message[] = []
res.updates.forEach((upd) => {
if (
upd._ === 'updateNewMessage' ||
upd._ == 'updateNewChannelMessage' ||
upd._ === 'updateNewScheduledMessage'
) {
switch (upd._) {
case 'updateNewMessage':
case 'updateNewChannelMessage':
case 'updateNewScheduledMessage':
forwarded.push(new Message(this, upd.message, users, chats))
break
}
})

View file

@ -8,6 +8,7 @@ import {
import { MaybeArray } from '@mtcute/core'
import { createUsersChatsIndex } from '../../utils/peer-utils'
import { assertTypeIs } from '../../utils/type-assertion'
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
/**
* Send or retract a vote in a poll.
@ -56,12 +57,7 @@ export async function sendVote(
options: options as Buffer[],
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'messages.sendVote',
'updates | updatesCombined',
res._
)
assertIsUpdatesGroup('messages.sendVote', res)
this._handleUpdate(res, true)

View file

@ -160,15 +160,17 @@ function _createNoDispatchIndex(
pts: {},
}
if (updates._ === 'updates' || updates._ === 'updatesCombined') {
switch (updates._) {
case 'updates':
case 'updatesCombined':
updates.updates.forEach((upd) => {
const cid = extractChannelIdFromUpdate(upd) ?? 0
if (
upd._ === 'updateNewMessage' ||
upd._ === 'updateNewChannelMessage'
) {
switch (upd._) {
case 'updateNewMessage':
case 'updateNewChannelMessage':
if (!ret.msg[cid]) ret.msg[cid] = {}
ret.msg[cid][upd.message.id] = true
break
}
const pts = 'pts' in upd ? upd.pts : undefined
@ -178,19 +180,17 @@ function _createNoDispatchIndex(
ret.msg[cid][pts] = true
}
})
}
if (
updates._ === 'updateShortMessage' ||
updates._ === 'updateShortChatMessage' ||
updates._ === 'updateShortSentMessage'
) {
break
case 'updateShortMessage':
case 'updateShortChatMessage':
case 'updateShortSentMessage':
// these updates are only used for non-channel messages, so we use 0
if (!ret.msg[0]) ret.msg[0] = {}
if (!ret.pts[0]) ret.pts[0] = {}
ret.msg[0][updates.id] = true
ret.pts[0][updates.pts] = true
break
}
return ret
@ -208,9 +208,10 @@ async function _loadDifference(
qts: 0,
})
if (diff._ === 'updates.differenceEmpty') return
if (diff._ === 'updates.differenceTooLong') {
switch (diff._) {
case 'updates.differenceEmpty':
return
case 'updates.differenceTooLong':
this._pts = diff.pts
return
}

View file

@ -231,7 +231,8 @@ export namespace BotInlineMessage {
obj: InputInlineMessage,
parseMode?: string | null
): Promise<tl.TypeInputBotInlineMessage> {
if (obj.type === 'text') {
switch (obj.type) {
case 'text': {
const [message, entities] = await client['_parseEntities'](
obj.text,
parseMode,
@ -245,8 +246,7 @@ export namespace BotInlineMessage {
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
}
if (obj.type === 'media') {
case 'media': {
const [message, entities] = await client['_parseEntities'](
obj.text,
parseMode,
@ -260,8 +260,8 @@ export namespace BotInlineMessage {
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
}
if (obj.type === 'geo' || obj.type === 'geo_live') {
case 'geo':
case 'geo_live':
return {
_: 'inputBotInlineMessageMediaGeo',
geoPoint: {
@ -276,9 +276,7 @@ export namespace BotInlineMessage {
.proximityNotificationRadius,
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
}
if (obj.type === 'venue') {
case 'venue':
return {
_: 'inputBotInlineMessageMediaVenue',
geoPoint: {
@ -293,16 +291,12 @@ export namespace BotInlineMessage {
venueType: obj.source?.type ?? '',
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
}
if (obj.type === 'game') {
case 'game':
return {
_: 'inputBotInlineMessageGame',
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
}
if (obj.type === 'contact') {
case 'contact':
return {
_: 'inputBotInlineMessageMediaContact',
phoneNumber: obj.phone,
@ -312,7 +306,5 @@ export namespace BotInlineMessage {
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup),
}
}
return obj as never
}
}

View file

@ -332,7 +332,8 @@ export namespace BotKeyboard {
): tl.TypeReplyMarkup | undefined {
if (!obj) return obj
if (obj.type === 'reply') {
switch (obj.type) {
case 'reply':
return {
_: 'replyKeyboardMarkup',
resize: obj.resize,
@ -340,30 +341,22 @@ export namespace BotKeyboard {
selective: obj.selective,
rows: _2dToRows(obj.buttons),
}
}
if (obj.type === 'reply_hide') {
case 'reply_hide':
return {
_: 'replyKeyboardHide',
selective: obj.selective,
}
}
if (obj.type === 'force_reply') {
case 'force_reply':
return {
_: 'replyKeyboardForceReply',
singleUse: obj.singleUse,
selective: obj.selective,
}
}
if (obj.type === 'inline') {
case 'inline':
return {
_: 'replyInlineMarkup',
rows: _2dToRows(obj.buttons),
}
}
return undefined
}
}

View file

@ -12,28 +12,26 @@ export function parseDocument(
doc: tl.RawDocument
): RawDocument {
for (const attr of doc.attributes) {
if (attr._ === 'documentAttributeAudio') {
switch (attr._) {
case 'documentAttributeAudio':
if (attr.voice) {
return new Voice(client, doc, attr)
} else {
return new Audio(client, doc, attr)
}
}
if (attr._ === 'documentAttributeSticker') {
case 'documentAttributeSticker': {
const sz = doc.attributes.find(
(it) => it._ === 'documentAttributeImageSize'
)! as tl.RawDocumentAttributeImageSize
return new Sticker(client, doc, attr, sz)
}
if (
attr._ === 'documentAttributeVideo' ||
// legacy gif
(attr._ === 'documentAttributeImageSize' &&
doc.mimeType === 'image/gif')
) {
case 'documentAttributeVideo':
return new Video(client, doc, attr)
case 'documentAttributeImageSize':
// legacy gif
if (doc.mimeType === 'image/gif') {
return new Video(client, doc, attr)
}
}
}

View file

@ -62,12 +62,15 @@ export class Thumbnail extends FileLocation {
media: tl.RawPhoto | tl.RawDocument,
sz: tl.TypePhotoSize
) {
if (sz._ === 'photoSizeEmpty' || sz._ === 'photoCachedSize')
switch (sz._) {
case 'photoSizeEmpty':
case 'photoCachedSize':
throw new MtCuteTypeAssertionError(
'sz',
'not (photoSizeEmpty | photoCachedSize)',
sz._
)
}
let location:
| tl.TypeInputFileLocation

View file

@ -170,12 +170,16 @@ export class Dialog {
const peer = this.raw.peer
let chat
if (peer._ === 'peerChannel' || peer._ === 'peerChat') {
switch (peer._) {
case 'peerChannel':
case 'peerChat':
chat = this._chats[
peer._ === 'peerChannel' ? peer.channelId : peer.chatId
]
} else {
break
default:
chat = this._users[peer.userId]
break
}
this._chat = new Chat(this.client, chat)

View file

@ -184,21 +184,28 @@ export class Message {
if (!from) {
// anon admin, return the chat
this._sender = this.chat
} else if (from._ === 'peerChannel') {
// forwarded channel post
} else
switch (from._) {
case 'peerChannel': // forwarded channel post
this._sender = new Chat(
this.client,
this._chats[from.channelId]
)
} else if (from._ === 'peerUser') {
this._sender = new User(this.client, this._users[from.userId])
} else
break
case 'peerUser':
this._sender = new User(
this.client,
this._users[from.userId]
)
break
default:
throw new MtCuteTypeAssertionError(
'raw.fromId',
'peerUser | peerChannel',
from._
)
}
}
return this._sender
}

View file

@ -38,7 +38,7 @@ export class ChatMember {
constructor(
client: TelegramClient,
raw: tl.TypeChatParticipant | tl.TypeChannelParticipant,
users: UsersIndex,
users: UsersIndex
) {
this.client = client
this.raw = raw
@ -51,10 +51,9 @@ export class ChatMember {
*/
get user(): User {
if (this._user === undefined) {
if (
this.raw._ === 'channelParticipantBanned' ||
this.raw._ === 'channelParticipantLeft'
) {
switch (this.raw._) {
case 'channelParticipantBanned':
case 'channelParticipantLeft':
assertTypeIs(
'ChatMember#user (raw.peer)',
this.raw.peer,
@ -64,11 +63,13 @@ export class ChatMember {
this.client,
this._users[this.raw.peer.userId]
)
} else {
break
default:
this._user = new User(
this.client,
this._users[this.raw.userId]
)
break
}
}
@ -79,34 +80,23 @@ export class ChatMember {
* Get the chat member status
*/
get status(): ChatMember.Status {
if (
this.raw._ === 'channelParticipant' ||
this.raw._ === 'channelParticipantSelf' ||
this.raw._ === 'chatParticipant'
) {
switch (this.raw._) {
case 'channelParticipant':
case 'channelParticipantSelf':
case 'chatParticipant':
return 'member'
}
if (
this.raw._ === 'channelParticipantCreator' ||
this.raw._ === 'chatParticipantCreator'
) {
case 'channelParticipantCreator':
case 'chatParticipantCreator':
return 'creator'
}
if (
this.raw._ === 'channelParticipantAdmin' ||
this.raw._ === 'chatParticipantAdmin'
) {
case 'channelParticipantAdmin':
case 'chatParticipantAdmin':
return 'admin'
}
if (this.raw._ === 'channelParticipantLeft') {
case 'channelParticipantLeft':
return 'left'
}
if (this.raw._ === 'channelParticipantBanned') {
return this.raw.bannedRights.viewMessages ? 'banned' : 'restricted'
case 'channelParticipantBanned':
return this.raw.bannedRights.viewMessages
? 'banned'
: 'restricted'
}
// fallback
@ -119,10 +109,13 @@ export class ChatMember {
* `null` for non-admins and in case custom title is not set.
*/
get title(): string | null {
return this.raw._ === 'channelParticipantCreator' ||
this.raw._ === 'channelParticipantAdmin'
? this.raw.rank ?? null
: null
switch (this.raw._) {
case 'channelParticipantCreator':
case 'channelParticipantAdmin':
return this.raw.rank ?? null
default:
return null
}
}
/**
@ -131,11 +124,14 @@ export class ChatMember {
* Not available for creators and left members
*/
get joinedDate(): Date | null {
return this.raw._ === 'channelParticipantCreator' ||
this.raw._ === 'chatParticipantCreator' ||
this.raw._ === 'channelParticipantLeft'
? null
: new Date(this.raw.date * 1000)
switch (this.raw._) {
case 'channelParticipantCreator':
case 'chatParticipantCreator':
case 'channelParticipantLeft':
return null
default:
return new Date(this.raw.date * 1000)
}
}
private _invitedBy?: User | null
@ -149,14 +145,7 @@ export class ChatMember {
*/
get invitedBy(): User | null {
if (this._invitedBy === undefined) {
if (
this.raw._ !== 'chatParticipantCreator' &&
this.raw._ !== 'channelParticipantCreator' &&
this.raw._ !== 'channelParticipant' &&
this.raw._ !== 'channelParticipantBanned' &&
this.raw._ !== 'channelParticipantLeft' &&
this.raw.inviterId
) {
if ('inviterId' in this.raw && this.raw.inviterId) {
this._invitedBy = new User(
this.client,
this._users[this.raw.inviterId]
@ -244,10 +233,13 @@ export class ChatMember {
* Also contains whether this admin is anonymous.
*/
get permissions(): tl.RawChatAdminRights | null {
return this.raw._ === 'channelParticipantAdmin' ||
this.raw._ === 'channelParticipantCreator'
? this.raw.adminRights
: null
switch (this.raw._) {
case 'channelParticipantAdmin':
case 'channelParticipantCreator':
return this.raw.adminRights
default:
return null
}
}
}

View file

@ -56,20 +56,20 @@ export class Chat {
) {
if (!peer) throw new MtCuteArgumentError('peer is not available')
if (
!(
peer._ === 'user' ||
peer._ === 'chat' ||
peer._ === 'channel' ||
peer._ === 'chatForbidden' ||
peer._ === 'channelForbidden'
)
)
switch (peer._) {
case 'user':
case 'chat':
case 'channel':
case 'chatForbidden':
case 'channelForbidden':
break
default:
throw new MtCuteTypeAssertionError(
'peer',
'user | chat | channel',
peer._
)
}
this.client = client
this.peer = peer
@ -87,7 +87,8 @@ export class Chat {
*/
get inputPeer(): tl.TypeInputPeer {
if (!this._inputPeer) {
if (this.peer._ === 'user') {
switch (this.peer._) {
case 'user':
if (!this.peer.accessHash) {
throw new MtCuteArgumentError(
"Peer's access hash is not available!"
@ -99,18 +100,16 @@ export class Chat {
userId: this.peer.id,
accessHash: this.peer.accessHash,
}
} else if (
this.peer._ === 'chat' ||
this.peer._ === 'chatForbidden'
) {
break
case 'chat':
case 'chatForbidden':
this._inputPeer = {
_: 'inputPeerChat',
chatId: this.peer.id,
}
} else if (
this.peer._ === 'channel' ||
this.peer._ === 'channelForbidden'
) {
break
case 'channel':
case 'channelForbidden':
if (!this.peer.accessHash) {
throw new MtCuteArgumentError(
"Peer's access hash is not available!"
@ -122,6 +121,7 @@ export class Chat {
channelId: this.peer.id,
accessHash: this.peer.accessHash,
}
break
}
}
@ -132,23 +132,23 @@ export class Chat {
/** Type of chat */
get type(): Chat.Type {
if (!this._type) {
if (this.peer._ === 'user') {
switch (this.peer._) {
case 'user':
this._type = this.peer.bot ? 'bot' : 'private'
} else if (
this.peer._ === 'chat' ||
this.peer._ === 'chatForbidden'
) {
break
case 'chat':
case 'chatForbidden':
this._type = 'group'
} else if (
this.peer._ === 'channel' ||
this.peer._ === 'channelForbidden'
) {
break
case 'channel':
case 'channelForbidden':
this._type =
this.peer._ === 'channel' && this.peer.gigagroup
? 'gigagroup'
: this.peer.broadcast
? 'channel'
: 'supergroup'
break
}
}
@ -467,11 +467,10 @@ export class Chat {
users: UsersIndex,
chats: ChatsIndex
): Chat {
if (peer._ === 'peerUser') {
switch (peer._) {
case 'peerUser':
return new Chat(client, users[peer.userId])
}
if (peer._ === 'peerChat') {
case 'peerChat':
return new Chat(client, chats[peer.chatId])
}
@ -508,8 +507,6 @@ export class Chat {
}
}
// todo: bound methods https://github.com/pyrogram/pyrogram/blob/a86656aefcc93cc3d2f5c98227d5da28fcddb136/pyrogram/types/user_and_chats/chat.py#L319
/**
* Join this chat.
*/

View file

@ -1,4 +1,5 @@
import { tl } from '@mtcute/tl'
import { MtCuteTypeAssertionError } from '../types'
// dummy updates which are used for methods that return messages.affectedHistory.
// that is not an update, but it carries info about pts, and we need to handle it
@ -34,3 +35,13 @@ export function isDummyUpdate(upd: tl.TypeUpdate): boolean {
export function isDummyUpdates(upd: tl.TypeUpdates): boolean {
return upd._ === 'updates' && upd.updates.length === 1 && isDummyUpdate(upd.updates[0])
}
/** @internal */
export function assertIsUpdatesGroup(ctx: string, upd: tl.TypeUpdates): asserts upd is tl.RawUpdates | tl.RawUpdatesCombined {
switch (upd._) {
case 'updates':
case 'updatesCombined':
return
}
throw new MtCuteTypeAssertionError(ctx, 'updates | updatesCombined', upd._)
}

View file

@ -10,11 +10,14 @@ export const MAX_USER_ID = 2147483647
* Get the bare (non-marked) ID from a {@link tl.TypePeer}
*/
export function getBarePeerId(peer: tl.TypePeer): number {
if (peer._ === 'peerUser') return peer.userId
if (peer._ === 'peerChat') return peer.chatId
if (peer._ === 'peerChannel') return peer.channelId
throw new Error('Invalid peer')
switch (peer._) {
case 'peerUser':
return peer.userId
case 'peerChat':
return peer.chatId
case 'peerChannel':
return peer.channelId
}
}
/**
@ -35,17 +38,31 @@ export function getMarkedPeerId(
peerType?: BasicPeerType | PeerType
): number {
if (typeof peer === 'number') {
if (peerType === 'user' || peerType === 'bot') return peer
if (peerType === 'chat' || peerType === 'group') return -peer
if (peerType === 'channel' || peerType === 'supergroup')
switch (peerType) {
case 'user':
case 'bot':
return peer
case 'chat':
case 'group':
return -peer
case 'channel':
case 'supergroup':
return MAX_CHANNEL_ID - peer
}
throw new Error('Invalid peer type')
}
if (peer._ === 'peerUser' || peer._ === 'inputPeerUser') return peer.userId
if (peer._ === 'peerChat' || peer._ === 'inputPeerChat') return -peer.chatId
if (peer._ === 'peerChannel' || peer._ === 'inputPeerChannel')
switch (peer._) {
case 'peerUser':
case 'inputPeerUser':
return peer.userId
case 'peerChat':
case 'inputPeerChat':
return -peer.chatId
case 'peerChannel':
case 'inputPeerChannel':
return MAX_CHANNEL_ID - peer.channelId
}
throw new Error('Invalid peer')
}
@ -55,11 +72,14 @@ export function getMarkedPeerId(
*/
export function getBasicPeerType(peer: tl.TypePeer | number): BasicPeerType {
if (typeof peer !== 'number') {
if (peer._ === 'peerUser') return 'user'
if (peer._ === 'peerChat') return 'chat'
if (peer._ === 'peerChannel') return 'channel'
throw new Error('Invalid peer')
switch (peer._) {
case 'peerUser':
return 'user'
case 'peerChat':
return 'chat'
case 'peerChannel':
return 'channel'
}
}
if (peer < 0) {
@ -90,11 +110,16 @@ export function markedPeerIdToBare(peerId: number): number {
* Convert {@link PeerType} to {@link BasicPeerType}
*/
export function peerTypeToBasic(type: PeerType): BasicPeerType {
if (type === 'bot' || type === 'user') return 'user'
if (type === 'group') return 'chat'
if (type === 'channel' || type === 'supergroup') return 'channel'
throw new Error('Invalid peer type')
switch (type) {
case 'bot':
case 'user':
return 'user'
case 'group':
return 'chat'
case 'channel':
case 'supergroup':
return 'channel'
}
}
function comparePeers(
@ -105,23 +130,29 @@ function comparePeers(
if ('userId' in first) {
if ('userId' in second) return first.userId === second.userId
if (second._ === 'user' || second._ === 'userEmpty')
switch (second._) {
case 'user':
case 'userEmpty':
return first.userId === second.id
}
}
if ('chatId' in first) {
if ('chatId' in second) return first.chatId === second.chatId
if (
second._ === 'chat' ||
second._ === 'chatForbidden' ||
second._ === 'chatEmpty'
)
switch (second._) {
case 'chat':
case 'chatForbidden':
case 'chatEmpty':
return first.chatId === second.id
}
}
if ('channelId' in first) {
if ('channelId' in second) return first.channelId === second.channelId
if (second._ === 'channel' || second._ === 'channelForbidden')
switch (second._) {
case 'channel':
case 'channelForbidden':
return first.channelId === second.id
}
}
return false
}
@ -141,30 +172,31 @@ function isRefMessage(msg: tl.TypeMessage, peer: any): boolean | undefined {
function findContext(obj: any, peer: any): [number, number] | undefined {
if (!peer.min) return undefined
if (
obj._ === 'updates' ||
obj._ === 'updatesCombined' ||
obj._ === 'updates.difference' ||
obj._ === 'updates.differenceSlice'
) {
for (const upd of (obj.updates || obj.otherUpdates) as tl.TypeUpdate[]) {
if (
(upd._ === 'updateNewMessage' ||
upd._ === 'updateNewChannelMessage' ||
upd._ === 'updateEditMessage' ||
upd._ === 'updateEditChannelMessage') &&
isRefMessage(upd.message, peer)
) {
return [getMarkedPeerId(upd.message.peerId!), upd.message.id]
switch (obj._) {
case 'updates':
case 'updatesCombined':
case 'updates.difference':
case 'updates.differenceSlice':
for (const upd of (obj.updates ||
obj.otherUpdates) as tl.TypeUpdate[]) {
switch (upd._) {
case 'updateNewMessage':
case 'updateNewChannelMessage':
case 'updateEditMessage':
case 'updateEditChannelMessage':
if (isRefMessage(upd.message, peer)) {
return [
getMarkedPeerId(upd.message.peerId!),
upd.message.id,
]
}
break
}
}
}
if (obj._ === 'updateShortMessage') {
break
case 'updateShortMessage':
return [obj.userId, obj.id]
}
if (obj._ === 'updateShortChatMessage') {
case 'updateShortChatMessage':
return [-obj.chatId, obj.id]
}
@ -193,17 +225,15 @@ export function* getAllPeersFrom(
> {
if (typeof obj !== 'object') return
if (
obj._ === 'user' ||
obj._ === 'chat' ||
obj._ === 'channel' ||
obj._ === 'chatForbidden' ||
obj._ === 'channelForbidden'
) {
switch (obj._) {
case 'user':
case 'chat':
case 'channel':
case 'chatForbidden':
case 'channelForbidden':
yield obj
return
}
if (obj._ === 'userFull') {
case 'userFull':
yield obj.user
return
}
@ -216,26 +246,26 @@ export function* getAllPeersFrom(
yield obj.user
}
if (
'chat' in obj &&
typeof obj.chat === 'object' &&
(obj.chat._ === 'chat' ||
obj.chat._ === 'channel' ||
obj.chat._ === 'chatForbidden' ||
obj.chat._ === 'channelForbidden')
) {
if ('chat' in obj && typeof obj.chat === 'object') {
switch (obj.chat._) {
case 'chat':
case 'channel':
case 'chatForbidden':
case 'channelForbidden':
yield obj.chat
break
}
}
if (
'channel' in obj &&
typeof obj.channel === 'object' &&
(obj.channel._ === 'chat' ||
obj.channel._ === 'channel' ||
obj.channel._ === 'chatForbidden' ||
obj.channel._ === 'channelForbidden')
) {
if ('channel' in obj && typeof obj.channel === 'object') {
switch (obj.channel._) {
case 'chat':
case 'channel':
case 'chatForbidden':
case 'channelForbidden':
yield obj.channel
break
}
}
if ('users' in obj && Array.isArray(obj.users) && obj.users.length) {
@ -257,18 +287,19 @@ export function* getAllPeersFrom(
if ('chats' in obj && Array.isArray(obj.chats) && obj.chats.length) {
for (const chat of obj.chats) {
// .chats is sometimes number[]
if (
typeof chat === 'object' &&
(chat._ === 'chat' ||
chat._ === 'channel' ||
chat._ === 'chatForbidden' ||
chat._ === 'channelForbidden')
) {
if (typeof chat === 'object') {
switch (chat._) {
case 'chat':
case 'channel':
case 'chatForbidden':
case 'channelForbidden':
if (chat.min) {
chat.fromMessage = findContext(obj, chat)
}
yield chat
break
}
}
}
}

View file

@ -38,14 +38,16 @@ export function jsonToTlJson(obj: any): tl.TypeJSONValue {
* @param obj TL JSON object to convert
*/
export function tlJsonToJson(obj: tl.TypeJSONValue): any {
if (obj._ === 'jsonNull') return null
if (
obj._ === 'jsonBool' ||
obj._ === 'jsonNumber' ||
obj._ === 'jsonString'
)
switch (obj._) {
case 'jsonNull':
return null
case 'jsonBool':
case 'jsonNumber':
case 'jsonString':
return obj.value
if (obj._ === 'jsonArray') return obj.value.map(tlJsonToJson)
case 'jsonArray':
return obj.value.map(tlJsonToJson)
}
const ret: any = {}

View file

@ -127,20 +127,29 @@ export class ChatMemberUpdate {
// in this case OR is the same as AND, but AND doesn't work well with typescript :shrug:
if (!old || !cur) return (this._type = 'other')
if (old._ === 'chatParticipant' || old._ === 'channelParticipant') {
if (
cur._ === 'chatParticipantAdmin' ||
cur._ === 'channelParticipantAdmin'
) {
switch (old._) {
case 'chatParticipant':
case 'channelParticipant':
switch (cur._) {
case 'chatParticipantAdmin':
case 'channelParticipantAdmin':
return (this._type = 'promoted')
}
if (cur._ === 'channelParticipantBanned') {
case 'channelParticipantBanned':
// kicked or restricted
if (cur.left) return (this._type = 'kicked')
return (this._type = 'restricted')
}
break
case 'chatParticipantCreator':
case 'channelParticipantCreator':
return (this._type = 'old_owner')
}
switch (cur._) {
case 'chatParticipantCreator':
case 'channelParticipantCreator':
return (this._type = 'new_owner')
}
if (
@ -157,20 +166,6 @@ export class ChatMemberUpdate {
return (this._type = 'demoted')
}
if (
old._ === 'chatParticipantCreator' ||
old._ === 'channelParticipantCreator'
) {
return (this._type = 'old_owner')
}
if (
cur._ === 'chatParticipantCreator' ||
cur._ === 'channelParticipantCreator'
) {
return (this._type = 'new_owner')
}
return (this._type = 'other')
}

View file

@ -75,22 +75,26 @@ export function toUniqueFileId(
}
let writer: BinaryWriter
if (inputLocation._ === 'photo') {
switch (inputLocation._) {
case 'photo':
writer = BinaryWriter.alloc(16)
writer.int32(type)
writer.long(inputLocation.volumeId)
writer.int32(inputLocation.localId)
} else if (inputLocation._ === 'web') {
break
case 'web':
writer = BinaryWriter.alloc(
Buffer.byteLength(inputLocation.url, 'utf-8') + 8
)
writer.int32(type)
writer.string(inputLocation.url)
} else if (inputLocation._ === 'common') {
break
case 'common':
writer = BinaryWriter.alloc(12)
writer.int32(type)
writer.long(inputLocation.id)
} else {
break
default:
throw new td.UnsupportedError(
`Unique IDs are not supported for ${(inputLocation as any)._}`
)