chore: various surface api improvements & fixes

This commit is contained in:
alina 🌸 2023-10-24 11:49:17 +03:00
parent 21d7488788
commit c061581abb
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
10 changed files with 45 additions and 21 deletions

View file

@ -1587,15 +1587,17 @@ export interface TelegramClient extends BaseTelegramClient {
* Kick a user from a chat. * Kick a user from a chat.
* *
* This effectively bans a user and immediately unbans them. * This effectively bans a user and immediately unbans them.
*
* **Available**: both users and bots * **Available**: both users and bots
* *
* @returns Service message about removed user, if one was generated.
*/ */
kickChatMember(params: { kickChatMember(params: {
/** Chat ID */ /** Chat ID */
chatId: InputPeerLike chatId: InputPeerLike
/** User ID */ /** User ID */
userId: InputPeerLike userId: InputPeerLike
}): Promise<void> }): Promise<Message | null>
/** /**
* Leave a group chat, supergroup or channel * Leave a group chat, supergroup or channel
* *

View file

@ -1,7 +1,7 @@
import { BaseTelegramClient } from '@mtcute/core' import { BaseTelegramClient } from '@mtcute/core'
import { sleep } from '@mtcute/core/utils.js' import { sleep } from '@mtcute/core/utils.js'
import { InputPeerLike } from '../../types/index.js' import { InputPeerLike, Message } from '../../types/index.js'
import { isInputPeerChannel } from '../../utils/peer-utils.js' import { isInputPeerChannel } from '../../utils/peer-utils.js'
import { resolvePeer } from '../users/resolve-peer.js' import { resolvePeer } from '../users/resolve-peer.js'
import { banChatMember } from './ban-chat-member.js' import { banChatMember } from './ban-chat-member.js'
@ -11,6 +11,8 @@ import { unbanChatMember } from './unban-chat-member.js'
* Kick a user from a chat. * Kick a user from a chat.
* *
* This effectively bans a user and immediately unbans them. * This effectively bans a user and immediately unbans them.
*
* @returns Service message about removed user, if one was generated.
*/ */
export async function kickChatMember( export async function kickChatMember(
client: BaseTelegramClient, client: BaseTelegramClient,
@ -20,13 +22,13 @@ export async function kickChatMember(
/** User ID */ /** User ID */
userId: InputPeerLike userId: InputPeerLike
}, },
): Promise<void> { ): Promise<Message | null> {
const { chatId, userId } = params const { chatId, userId } = params
const chat = await resolvePeer(client, chatId) const chat = await resolvePeer(client, chatId)
const user = await resolvePeer(client, userId) const user = await resolvePeer(client, userId)
await banChatMember(client, { chatId: chat, participantId: user }) const msg = await banChatMember(client, { chatId: chat, participantId: user })
// not needed in case this is a legacy group // not needed in case this is a legacy group
if (isInputPeerChannel(chat)) { if (isInputPeerChannel(chat)) {
@ -34,4 +36,6 @@ export async function kickChatMember(
await sleep(1000) await sleep(1000)
await unbanChatMember(client, { chatId: chat, participantId: user }) await unbanChatMember(client, { chatId: chat, participantId: user })
} }
return msg
} }

View file

@ -29,7 +29,7 @@ export async function resolvePeer(
if (typeof peerId === 'object') { if (typeof peerId === 'object') {
if (tl.isAnyPeer(peerId)) { if (tl.isAnyPeer(peerId)) {
peerId = getMarkedPeerId(peerId) peerId = getMarkedPeerId(peerId)
} else if ('type' in peerId) { } else if ('inputPeer' in peerId) {
// User | Chat // User | Chat
return peerId.inputPeer return peerId.inputPeer
} else { } else {

View file

@ -1,8 +1,5 @@
import { tl } from '@mtcute/core' import { tl } from '@mtcute/core'
import { Chat } from './chat.js'
import { User } from './user.js'
export * from './chat.js' export * from './chat.js'
export * from './chat-event/index.js' export * from './chat-event/index.js'
export * from './chat-invite-link.js' export * from './chat-invite-link.js'
@ -29,7 +26,7 @@ export type PeerType = 'user' | 'bot' | 'group' | 'channel' | 'supergroup'
* - `string`, representing peer's username (without preceding `@`) * - `string`, representing peer's username (without preceding `@`)
* - `string`, representing user's phone number * - `string`, representing user's phone number
* - `"me"` and `"self"` which will be replaced with the current user/bot * - `"me"` and `"self"` which will be replaced with the current user/bot
* - `Chat` or `User` object * - Any object with `inputPeer: tl.TypeInputPeer` property
* - Raw TL object * - Raw TL object
* *
* > * Telegram has moved to int64 IDs. Though, Levin [has confirmed](https://t.me/tdlibchat/25071) * > * Telegram has moved to int64 IDs. Though, Levin [has confirmed](https://t.me/tdlibchat/25071)
@ -42,5 +39,4 @@ export type InputPeerLike =
| tl.TypeInputPeer | tl.TypeInputPeer
| tl.TypeInputUser | tl.TypeInputUser
| tl.TypeInputChannel | tl.TypeInputChannel
| Chat | { inputPeer: tl.TypeInputPeer }
| User

View file

@ -162,6 +162,13 @@ export interface BaseTelegramClientOptions {
*/ */
network?: NetworkManagerExtraParams network?: NetworkManagerExtraParams
/**
* Set logging level for the client.
*
* See static members of {@link LogManager} for possible values.
*/
logLevel?: number
/** /**
* **EXPERT USE ONLY!** * **EXPERT USE ONLY!**
* *
@ -247,6 +254,8 @@ export class BaseTelegramClient extends EventEmitter {
throw new Error('apiId must be a number or a numeric string!') throw new Error('apiId must be a number or a numeric string!')
} }
if (opts.logLevel) this.log.level = opts.logLevel
this.crypto = (opts.crypto ?? defaultCryptoProviderFactory)() this.crypto = (opts.crypto ?? defaultCryptoProviderFactory)()
this.storage = opts.storage ?? new MemoryStorage() this.storage = opts.storage ?? new MemoryStorage()
this._apiHash = opts.apiHash this._apiHash = opts.apiHash

View file

@ -564,7 +564,7 @@ export class SessionConnection extends PersistentConnection {
} }
if (this._session.recentIncomingMsgIds.has(messageId)) { if (this._session.recentIncomingMsgIds.has(messageId)) {
this.log.warn('warn: ignoring duplicate message %s', messageId) this.log.debug('ignoring duplicate message %s', messageId)
return return
} }

View file

@ -2,7 +2,7 @@ import { hexEncode } from '@mtcute/tl-runtime'
import { _defaultLoggingHandler } from './platform/logging.js' import { _defaultLoggingHandler } from './platform/logging.js'
let defaultLogLevel = 2 let defaultLogLevel = 3
if (typeof process !== 'undefined') { if (typeof process !== 'undefined') {
const envLogLevel = parseInt(process.env.MTCUTE_LOG_LEVEL ?? '') const envLogLevel = parseInt(process.env.MTCUTE_LOG_LEVEL ?? '')

View file

@ -2,7 +2,7 @@ import { MaybeArray, MaybeAsync, Message } from '@mtcute/client'
import { MessageContext } from '../context/message.js' import { MessageContext } from '../context/message.js'
import { chat } from './chat.js' import { chat } from './chat.js'
import { and } from './logic.js' import { and, or } from './logic.js'
import { UpdateFilter } from './types.js' import { UpdateFilter } from './types.js'
/** /**
@ -92,6 +92,12 @@ export const command = (
*/ */
export const start = and(chat('private'), command('start')) export const start = and(chat('private'), command('start'))
/**
* Shorthand filter that matches /start commands
* sent in groups (i.e. using `?startgroup` parameter).
*/
export const startGroup = and(or(chat('supergroup'), chat('group')), command('start'))
/** /**
* Filter for deep links (i.e. `/start <deeplink_parameter>`). * Filter for deep links (i.e. `/start <deeplink_parameter>`).
* *

View file

@ -12,20 +12,25 @@ import {
} from '@mtcute/client' } from '@mtcute/client'
import { UpdateContextDistributed } from '../context/base.js' import { UpdateContextDistributed } from '../context/base.js'
import { Modify, UpdateFilter } from './types.js' import { EmptyObject, Modify, UpdateFilter } from './types.js'
/** /**
* Filter messages by chat type * Filter updates by type of the chat where they happened
*/ */
export const chat = export const chat =
<T extends ChatType>( <T extends ChatType, Obj extends { chat: Chat }>(
type: T, type: T,
): UpdateFilter< ): UpdateFilter<
Message, Obj,
{ {
chat: Modify<Chat, { type: T }> chat: Modify<Chat, { chatType: T }>
sender: T extends 'private' | 'bot' | 'group' ? User : User | Chat } & (Obj extends Message
} ? T extends 'private' | 'bot' | 'group'
? {
sender: User
}
: EmptyObject
: EmptyObject)
> => > =>
(msg) => (msg) =>
msg.chat.chatType === type msg.chat.chatType === type

View file

@ -100,3 +100,5 @@ export type WrapBase<T extends any[]> = {
export type Values<T> = T[keyof T] export type Values<T> = T[keyof T]
export type UnwrapBase<T> = T extends { base: any } ? T['base'] : never export type UnwrapBase<T> = T extends { base: any } ? T['base'] : never
export type ExtractBaseMany<Filters extends any[]> = UnwrapBase<UnionToIntersection<Values<WrapBase<Filters>>>> export type ExtractBaseMany<Filters extends any[]> = UnwrapBase<UnionToIntersection<Values<WrapBase<Filters>>>>
export type EmptyObject = Record<never, never>