feat!: updated to layer 169
breaking: - boost related methods re-done to allow for multiple boosts per user - `BotKeyboard.requestPeer` and `peer_chosen` changed
This commit is contained in:
parent
9ff6a628e5
commit
c175e41616
29 changed files with 558 additions and 250 deletions
|
@ -178,6 +178,12 @@ import { changeCloudPassword } from './methods/password/change-cloud-password.js
|
|||
import { enableCloudPassword } from './methods/password/enable-cloud-password.js'
|
||||
import { cancelPasswordEmail, resendPasswordEmail, verifyPasswordEmail } from './methods/password/password-email.js'
|
||||
import { removeCloudPassword } from './methods/password/remove-cloud-password.js'
|
||||
import { applyBoost } from './methods/premium/apply-boost.js'
|
||||
import { canApplyBoost, CanApplyBoostResult } from './methods/premium/can-apply-boost.js'
|
||||
import { getBoostStats } from './methods/premium/get-boost-stats.js'
|
||||
import { getBoosts } from './methods/premium/get-boosts.js'
|
||||
import { getMyBoostSlots } from './methods/premium/get-my-boost-slots.js'
|
||||
import { iterBoosters } from './methods/premium/iter-boosters.js'
|
||||
import { addStickerToSet } from './methods/stickers/add-sticker-to-set.js'
|
||||
import { createStickerSet } from './methods/stickers/create-sticker-set.js'
|
||||
import { deleteStickerFromSet } from './methods/stickers/delete-sticker-from-set.js'
|
||||
|
@ -187,14 +193,10 @@ import { getStickerSet } from './methods/stickers/get-sticker-set.js'
|
|||
import { moveStickerInSet } from './methods/stickers/move-sticker-in-set.js'
|
||||
import { setChatStickerSet } from './methods/stickers/set-chat-sticker-set.js'
|
||||
import { setStickerSetThumb } from './methods/stickers/set-sticker-set-thumb.js'
|
||||
import { applyBoost } from './methods/stories/apply-boost.js'
|
||||
import { canApplyBoost, CanApplyBoostResult } from './methods/stories/can-apply-boost.js'
|
||||
import { canSendStory, CanSendStoryResult } from './methods/stories/can-send-story.js'
|
||||
import { deleteStories } from './methods/stories/delete-stories.js'
|
||||
import { editStory } from './methods/stories/edit-story.js'
|
||||
import { getAllStories } from './methods/stories/get-all-stories.js'
|
||||
import { getBoostStats } from './methods/stories/get-boost-stats.js'
|
||||
import { getBoosters } from './methods/stories/get-boosters.js'
|
||||
import { getPeerStories } from './methods/stories/get-peer-stories.js'
|
||||
import { getProfileStories } from './methods/stories/get-profile-stories.js'
|
||||
import { getStoriesById } from './methods/stories/get-stories-by-id.js'
|
||||
|
@ -204,7 +206,6 @@ import { getStoryViewers } from './methods/stories/get-story-viewers.js'
|
|||
import { hideMyStoriesViews } from './methods/stories/hide-my-stories-views.js'
|
||||
import { incrementStoriesViews } from './methods/stories/increment-stories-views.js'
|
||||
import { iterAllStories } from './methods/stories/iter-all-stories.js'
|
||||
import { iterBoosters } from './methods/stories/iter-boosters.js'
|
||||
import { iterProfileStories } from './methods/stories/iter-profile-stories.js'
|
||||
import { iterStoryViewers } from './methods/stories/iter-story-viewers.js'
|
||||
import { readStories } from './methods/stories/read-stories.js'
|
||||
|
@ -254,7 +255,8 @@ import {
|
|||
AllStories,
|
||||
ArrayPaginated,
|
||||
ArrayWithTotal,
|
||||
Booster,
|
||||
Boost,
|
||||
BoostSlot,
|
||||
BoostStats,
|
||||
BotChatJoinRequestUpdate,
|
||||
BotCommands,
|
||||
|
@ -4145,6 +4147,96 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
* @param password 2FA password as plaintext
|
||||
*/
|
||||
removeCloudPassword(password: string): Promise<void>
|
||||
/**
|
||||
* Boost a given channel
|
||||
*
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
* @param peerId Peer ID to boost
|
||||
*/
|
||||
applyBoost(peerId: InputPeerLike): Promise<void>
|
||||
/**
|
||||
* Check if the current user can apply boost to some channel
|
||||
*
|
||||
* **Available**: ✅ both users and bots
|
||||
*
|
||||
* @returns
|
||||
* - `{ can: true }` if the user can apply boost
|
||||
* - `.replace` - {@link Chat}s that can be replaced with the current one.
|
||||
* If the user can apply boost without replacing any chats, this field will be `undefined`.
|
||||
* - `{ can: false }` if the user can't apply boost
|
||||
* - `.reason == "no_slots"` if the user has no available slots
|
||||
* - `.reason == "need_premium"` if the user needs Premium to boost
|
||||
* - In all cases, `slots` will contain all the current user's boost slots
|
||||
*/
|
||||
canApplyBoost(): Promise<CanApplyBoostResult>
|
||||
|
||||
/**
|
||||
* Get information about boosts in a channel
|
||||
*
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
* @returns IDs of stories that were removed
|
||||
*/
|
||||
getBoostStats(peerId: InputPeerLike): Promise<BoostStats>
|
||||
/**
|
||||
* Get boosts of a channel
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
*/
|
||||
getBoosts(
|
||||
peerId: InputPeerLike,
|
||||
params?: {
|
||||
/**
|
||||
* Offset for pagination
|
||||
*/
|
||||
offset?: string
|
||||
|
||||
/**
|
||||
* Maximum number of boosters to fetch
|
||||
*
|
||||
* @default 100
|
||||
*/
|
||||
limit?: number
|
||||
},
|
||||
): Promise<ArrayPaginated<Boost, string>>
|
||||
/**
|
||||
* Get boost slots information of the current user.
|
||||
*
|
||||
* Includes information about the currently boosted channels,
|
||||
* as well as the slots that can be used to boost other channels.
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
*/
|
||||
getMyBoostSlots(): Promise<BoostSlot[]>
|
||||
/**
|
||||
* Iterate over boosters of a channel.
|
||||
*
|
||||
* Wrapper over {@link getBoosters}
|
||||
*
|
||||
* **Available**: ✅ both users and bots
|
||||
*
|
||||
* @returns IDs of stories that were removed
|
||||
*/
|
||||
iterBoosters(
|
||||
peerId: InputPeerLike,
|
||||
params?: Parameters<typeof getBoosts>[2] & {
|
||||
/**
|
||||
* Total number of boosters to fetch
|
||||
*
|
||||
* @default Infinity, i.e. fetch all boosters
|
||||
*/
|
||||
limit?: number
|
||||
|
||||
/**
|
||||
* Number of boosters to fetch per request
|
||||
* Usually you don't need to change this
|
||||
*
|
||||
* @default 100
|
||||
*/
|
||||
chunkSize?: number
|
||||
},
|
||||
): AsyncIterableIterator<Boost>
|
||||
/**
|
||||
* Add a sticker to a sticker set.
|
||||
*
|
||||
|
@ -4356,30 +4448,6 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
progressCallback?: (uploaded: number, total: number) => void
|
||||
},
|
||||
): Promise<StickerSet>
|
||||
/**
|
||||
* Boost a given channel
|
||||
*
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
* @param peerId Peer ID to boost
|
||||
*/
|
||||
applyBoost(peerId: InputPeerLike): Promise<void>
|
||||
/**
|
||||
* Check if the current user can apply boost to a given channel
|
||||
*
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
* @param peerId Peer ID whose stories to fetch
|
||||
* @returns
|
||||
* - `{ can: true }` if the user can apply boost
|
||||
* - `.current` - {@link Chat} that the current user is currently boosting, if any
|
||||
* - `{ can: false }` if the user can't apply boost
|
||||
* - `.reason == "already_boosting"` if the user is already boosting this channel
|
||||
* - `.reason == "need_premium"` if the user needs Premium to boost this channel
|
||||
* - `.reason == "timeout"` if the user has recently boosted a channel and needs to wait
|
||||
* (`.until` contains the date until which the user needs to wait)
|
||||
*/
|
||||
canApplyBoost(peerId: InputPeerLike): Promise<CanApplyBoostResult>
|
||||
/**
|
||||
* Check if the current user can post stories as a given peer
|
||||
*
|
||||
|
@ -4470,38 +4538,6 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
*/
|
||||
archived?: boolean
|
||||
}): Promise<AllStories>
|
||||
|
||||
/**
|
||||
* Get information about boosts in a channel
|
||||
*
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
* @returns IDs of stories that were removed
|
||||
*/
|
||||
getBoostStats(peerId: InputPeerLike): Promise<BoostStats>
|
||||
/**
|
||||
* Get boosters of a channel
|
||||
*
|
||||
* **Available**: 👤 users only
|
||||
*
|
||||
* @returns IDs of stories that were removed
|
||||
*/
|
||||
getBoosters(
|
||||
peerId: InputPeerLike,
|
||||
params?: {
|
||||
/**
|
||||
* Offset for pagination
|
||||
*/
|
||||
offset?: string
|
||||
|
||||
/**
|
||||
* Maximum number of boosters to fetch
|
||||
*
|
||||
* @default 100
|
||||
*/
|
||||
limit?: number
|
||||
},
|
||||
): Promise<ArrayPaginated<Booster, string>>
|
||||
/**
|
||||
* Get stories of a given peer
|
||||
*
|
||||
|
@ -4660,34 +4696,6 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
limit?: number
|
||||
},
|
||||
): AsyncIterableIterator<PeerStories>
|
||||
/**
|
||||
* Iterate over boosters of a channel.
|
||||
*
|
||||
* Wrapper over {@link getBoosters}
|
||||
*
|
||||
* **Available**: ✅ both users and bots
|
||||
*
|
||||
* @returns IDs of stories that were removed
|
||||
*/
|
||||
iterBoosters(
|
||||
peerId: InputPeerLike,
|
||||
params?: Parameters<typeof getBoosters>[2] & {
|
||||
/**
|
||||
* Total number of boosters to fetch
|
||||
*
|
||||
* @default Infinity, i.e. fetch all boosters
|
||||
*/
|
||||
limit?: number
|
||||
|
||||
/**
|
||||
* Number of boosters to fetch per request
|
||||
* Usually you don't need to change this
|
||||
*
|
||||
* @default 100
|
||||
*/
|
||||
chunkSize?: number
|
||||
},
|
||||
): AsyncIterableIterator<Booster>
|
||||
/**
|
||||
* Iterate over profile stories. Wrapper over {@link getProfileStories}
|
||||
* **Available**: ✅ both users and bots
|
||||
|
@ -5999,6 +6007,30 @@ TelegramClient.prototype.removeCloudPassword = function (...args) {
|
|||
return removeCloudPassword(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.applyBoost = function (...args) {
|
||||
return applyBoost(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.canApplyBoost = function (...args) {
|
||||
return canApplyBoost(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.getBoostStats = function (...args) {
|
||||
return getBoostStats(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.getBoosts = function (...args) {
|
||||
return getBoosts(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.getMyBoostSlots = function (...args) {
|
||||
return getMyBoostSlots(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.iterBoosters = function (...args) {
|
||||
return iterBoosters(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.addStickerToSet = function (...args) {
|
||||
return addStickerToSet(this, ...args)
|
||||
}
|
||||
|
@ -6039,14 +6071,6 @@ TelegramClient.prototype.setStickerSetThumb = function (...args) {
|
|||
return setStickerSetThumb(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.applyBoost = function (...args) {
|
||||
return applyBoost(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.canApplyBoost = function (...args) {
|
||||
return canApplyBoost(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.canSendStory = function (...args) {
|
||||
return canSendStory(this, ...args)
|
||||
}
|
||||
|
@ -6063,14 +6087,6 @@ TelegramClient.prototype.getAllStories = function (...args) {
|
|||
return getAllStories(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.getBoostStats = function (...args) {
|
||||
return getBoostStats(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.getBoosters = function (...args) {
|
||||
return getBoosters(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.getPeerStories = function (...args) {
|
||||
return getPeerStories(this, ...args)
|
||||
}
|
||||
|
@ -6107,10 +6123,6 @@ TelegramClient.prototype.iterAllStories = function (...args) {
|
|||
return iterAllStories(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.iterBoosters = function (...args) {
|
||||
return iterBoosters(this, ...args)
|
||||
}
|
||||
|
||||
TelegramClient.prototype.iterProfileStories = function (...args) {
|
||||
return iterProfileStories(this, ...args)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import {
|
|||
AllStories,
|
||||
ArrayPaginated,
|
||||
ArrayWithTotal,
|
||||
Booster,
|
||||
Boost,
|
||||
BoostSlot,
|
||||
BoostStats,
|
||||
BotChatJoinRequestUpdate,
|
||||
BotCommands,
|
||||
|
|
|
@ -10,7 +10,7 @@ import { resolvePeer } from '../users/resolve-peer.js'
|
|||
*/
|
||||
export async function applyBoost(client: BaseTelegramClient, peerId: InputPeerLike): Promise<void> {
|
||||
await client.call({
|
||||
_: 'stories.applyBoost',
|
||||
_: 'premium.applyBoost',
|
||||
peer: await resolvePeer(client, peerId),
|
||||
})
|
||||
}
|
45
packages/client/src/methods/premium/can-apply-boost.ts
Normal file
45
packages/client/src/methods/premium/can-apply-boost.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { BaseTelegramClient } from '@mtcute/core'
|
||||
|
||||
import { Chat } from '../../types/index.js'
|
||||
import { BoostSlot } from '../../types/premium/boost-slot.js'
|
||||
import { getMyBoostSlots } from './get-my-boost-slots.js'
|
||||
|
||||
// @exported
|
||||
export type CanApplyBoostResult =
|
||||
| { can: true; replace?: Chat[]; slots: BoostSlot[] }
|
||||
| { can: false; reason: 'need_premium'; slots: BoostSlot[] }
|
||||
| { can: false; reason: 'no_slots'; slots: BoostSlot[] }
|
||||
|
||||
/**
|
||||
* Check if the current user can apply boost to some channel
|
||||
*
|
||||
* @returns
|
||||
* - `{ can: true }` if the user can apply boost
|
||||
* - `.replace` - {@link Chat}s that can be replaced with the current one.
|
||||
* If the user can apply boost without replacing any chats, this field will be `undefined`.
|
||||
* - `{ can: false }` if the user can't apply boost
|
||||
* - `.reason == "no_slots"` if the user has no available slots
|
||||
* - `.reason == "need_premium"` if the user needs Premium to boost
|
||||
* - In all cases, `slots` will contain all the current user's boost slots
|
||||
*/
|
||||
export async function canApplyBoost(client: BaseTelegramClient): Promise<CanApplyBoostResult> {
|
||||
const myBoosts = await getMyBoostSlots(client)
|
||||
|
||||
if (!myBoosts.length) {
|
||||
return { can: false, reason: 'need_premium', slots: myBoosts }
|
||||
}
|
||||
|
||||
const emptySlots = myBoosts.filter((it) => !it.occupied)
|
||||
|
||||
if (emptySlots.length > 0) {
|
||||
return { can: true, slots: myBoosts }
|
||||
}
|
||||
|
||||
const replaceableSlots = myBoosts.filter((it) => it.cooldownUntil === null)
|
||||
|
||||
if (replaceableSlots.length) {
|
||||
return { can: true, replace: replaceableSlots.map((it) => it.chat!), slots: myBoosts }
|
||||
}
|
||||
|
||||
return { can: false, reason: 'no_slots', slots: myBoosts }
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { BaseTelegramClient } from '@mtcute/core'
|
||||
|
||||
import { InputPeerLike } from '../../types/index.js'
|
||||
import { BoostStats } from '../../types/stories/boost-stats.js'
|
||||
import { BoostStats } from '../../types/premium/boost-stats.js'
|
||||
import { resolvePeer } from '../users/resolve-peer.js'
|
||||
|
||||
// @available=user
|
|
@ -1,16 +1,14 @@
|
|||
import { BaseTelegramClient } from '@mtcute/core'
|
||||
|
||||
import { ArrayPaginated, InputPeerLike, PeersIndex } from '../../types/index.js'
|
||||
import { Booster } from '../../types/stories/booster.js'
|
||||
import { Boost } from '../../types/premium/boost.js'
|
||||
import { makeArrayPaginated } from '../../utils/index.js'
|
||||
import { resolvePeer } from '../users/resolve-peer.js'
|
||||
|
||||
/**
|
||||
* Get boosters of a channel
|
||||
*
|
||||
* @returns IDs of stories that were removed
|
||||
* Get boosts of a channel
|
||||
*/
|
||||
export async function getBoosters(
|
||||
export async function getBoosts(
|
||||
client: BaseTelegramClient,
|
||||
peerId: InputPeerLike,
|
||||
params?: {
|
||||
|
@ -26,11 +24,11 @@ export async function getBoosters(
|
|||
*/
|
||||
limit?: number
|
||||
},
|
||||
): Promise<ArrayPaginated<Booster, string>> {
|
||||
): Promise<ArrayPaginated<Boost, string>> {
|
||||
const { offset = '', limit = 100 } = params ?? {}
|
||||
|
||||
const res = await client.call({
|
||||
_: 'stories.getBoostersList',
|
||||
_: 'premium.getBoostsList',
|
||||
peer: await resolvePeer(client, peerId),
|
||||
offset,
|
||||
limit,
|
||||
|
@ -39,7 +37,7 @@ export async function getBoosters(
|
|||
const peers = PeersIndex.from(res)
|
||||
|
||||
return makeArrayPaginated(
|
||||
res.boosters.map((it) => new Booster(it, peers)),
|
||||
res.boosts.map((it) => new Boost(it, peers)),
|
||||
res.count,
|
||||
res.nextOffset,
|
||||
)
|
20
packages/client/src/methods/premium/get-my-boost-slots.ts
Normal file
20
packages/client/src/methods/premium/get-my-boost-slots.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { BaseTelegramClient } from '@mtcute/core'
|
||||
|
||||
import { PeersIndex } from '../../types/index.js'
|
||||
import { BoostSlot } from '../../types/premium/boost-slot.js'
|
||||
|
||||
/**
|
||||
* Get boost slots information of the current user.
|
||||
*
|
||||
* Includes information about the currently boosted channels,
|
||||
* as well as the slots that can be used to boost other channels.
|
||||
*/
|
||||
export async function getMyBoostSlots(client: BaseTelegramClient): Promise<BoostSlot[]> {
|
||||
const res = await client.call({
|
||||
_: 'premium.getMyBoosts',
|
||||
})
|
||||
|
||||
const peers = PeersIndex.from(res)
|
||||
|
||||
return res.myBoosts.map((it) => new BoostSlot(it, peers))
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import { BaseTelegramClient } from '@mtcute/core'
|
||||
|
||||
import { InputPeerLike } from '../../types/index.js'
|
||||
import { Booster } from '../../types/stories/booster.js'
|
||||
import { Boost } from '../../types/premium/boost.js'
|
||||
import { resolvePeer } from '../users/resolve-peer.js'
|
||||
import { getBoosters } from './get-boosters.js'
|
||||
import { getBoosts } from './get-boosts.js'
|
||||
|
||||
/**
|
||||
* Iterate over boosters of a channel.
|
||||
|
@ -15,7 +15,7 @@ import { getBoosters } from './get-boosters.js'
|
|||
export async function* iterBoosters(
|
||||
client: BaseTelegramClient,
|
||||
peerId: InputPeerLike,
|
||||
params?: Parameters<typeof getBoosters>[2] & {
|
||||
params?: Parameters<typeof getBoosts>[2] & {
|
||||
/**
|
||||
* Total number of boosters to fetch
|
||||
*
|
||||
|
@ -31,7 +31,7 @@ export async function* iterBoosters(
|
|||
*/
|
||||
chunkSize?: number
|
||||
},
|
||||
): AsyncIterableIterator<Booster> {
|
||||
): AsyncIterableIterator<Boost> {
|
||||
if (!params) params = {}
|
||||
const { limit = Infinity, chunkSize = 100 } = params
|
||||
|
||||
|
@ -41,7 +41,7 @@ export async function* iterBoosters(
|
|||
const peer = await resolvePeer(client, peerId)
|
||||
|
||||
for (;;) {
|
||||
const res = await getBoosters(client, peer, {
|
||||
const res = await getBoosts(client, peer, {
|
||||
offset,
|
||||
limit: Math.min(limit - current, chunkSize),
|
||||
})
|
|
@ -1,62 +0,0 @@
|
|||
import { BaseTelegramClient, tl } from '@mtcute/core'
|
||||
|
||||
import { Chat, InputPeerLike, PeersIndex } from '../../types/index.js'
|
||||
import { resolvePeer } from '../users/resolve-peer.js'
|
||||
|
||||
// @exported
|
||||
export type CanApplyBoostResult =
|
||||
| { can: true; current?: Chat }
|
||||
| { can: false; reason: 'already_boosting' | 'need_premium' }
|
||||
| { can: false; reason: 'timeout'; until: Date }
|
||||
|
||||
/**
|
||||
* Check if the current user can apply boost to a given channel
|
||||
*
|
||||
* @param peerId Peer ID whose stories to fetch
|
||||
* @returns
|
||||
* - `{ can: true }` if the user can apply boost
|
||||
* - `.current` - {@link Chat} that the current user is currently boosting, if any
|
||||
* - `{ can: false }` if the user can't apply boost
|
||||
* - `.reason == "already_boosting"` if the user is already boosting this channel
|
||||
* - `.reason == "need_premium"` if the user needs Premium to boost this channel
|
||||
* - `.reason == "timeout"` if the user has recently boosted a channel and needs to wait
|
||||
* (`.until` contains the date until which the user needs to wait)
|
||||
*/
|
||||
export async function canApplyBoost(client: BaseTelegramClient, peerId: InputPeerLike): Promise<CanApplyBoostResult> {
|
||||
try {
|
||||
const res = await client.call(
|
||||
{
|
||||
_: 'stories.canApplyBoost',
|
||||
peer: await resolvePeer(client, peerId),
|
||||
},
|
||||
{ floodSleepThreshold: 0 },
|
||||
)
|
||||
|
||||
if (res._ === 'stories.canApplyBoostOk') return { can: true }
|
||||
|
||||
const peers = PeersIndex.from(res)
|
||||
const chat = new Chat(peers.get(res.currentBoost))
|
||||
|
||||
return { can: true, current: chat }
|
||||
} catch (e) {
|
||||
if (!tl.RpcError.is(e)) throw e
|
||||
|
||||
if (e.is('BOOST_NOT_MODIFIED')) {
|
||||
return { can: false, reason: 'already_boosting' }
|
||||
}
|
||||
|
||||
if (e.is('PREMIUM_ACCOUNT_REQUIRED')) {
|
||||
return { can: false, reason: 'need_premium' }
|
||||
}
|
||||
|
||||
if (e.is('FLOOD_WAIT_%d')) {
|
||||
return {
|
||||
can: false,
|
||||
reason: 'timeout',
|
||||
until: new Date(Date.now() + e.seconds * 1000),
|
||||
}
|
||||
}
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
|
@ -354,18 +354,30 @@ export namespace BotKeyboard {
|
|||
*
|
||||
* @param text Text of the button
|
||||
* @param buttonId ID of the button that will later be passed to the service message
|
||||
* @param peerType Peer type, along with filters
|
||||
*/
|
||||
export function requestPeer(
|
||||
text: string,
|
||||
buttonId: number,
|
||||
peerType: tl.TypeRequestPeerType,
|
||||
params: {
|
||||
/**
|
||||
* Peer type, along with filters
|
||||
*/
|
||||
peerType: tl.TypeRequestPeerType
|
||||
|
||||
/**
|
||||
* Maximum number of peers to be selected
|
||||
*
|
||||
* @default 1
|
||||
*/
|
||||
count?: number
|
||||
},
|
||||
): tl.RawKeyboardButtonRequestPeer {
|
||||
return {
|
||||
_: 'keyboardButtonRequestPeer',
|
||||
text,
|
||||
buttonId,
|
||||
peerType,
|
||||
peerType: params.peerType,
|
||||
maxQuantity: params.count ?? 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ export * from './media/index.js'
|
|||
export * from './messages/index.js'
|
||||
export * from './misc/index.js'
|
||||
export * from './peers/index.js'
|
||||
export * from './premium/index.js'
|
||||
export * from './reactions/index.js'
|
||||
export * from './stories/index.js'
|
||||
export * from './updates/index.js'
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { getMarkedPeerId, tl } from '@mtcute/core'
|
||||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { _callDiscardReasonFromTl, CallDiscardReason } from '../calls/index.js'
|
||||
import { Photo } from '../media/index.js'
|
||||
import { Photo } from '../media/photo.js'
|
||||
import { parsePeer, Peer } from '../peers/peer.js'
|
||||
import type { Message } from './message.js'
|
||||
|
||||
/** Group was created */
|
||||
|
@ -378,11 +379,8 @@ export interface ActionPeerChosen {
|
|||
/** ID of the button passed earlier by the bot */
|
||||
buttonId: number
|
||||
|
||||
/** Marked ID of the chosen peer */
|
||||
peerId: number
|
||||
|
||||
/** Input peer of the chosen peer */
|
||||
inputPeer?: tl.TypeInputPeer
|
||||
/** Chosen peers */
|
||||
peers: Peer[]
|
||||
}
|
||||
|
||||
/** A wallpaper of the chathas been changed */
|
||||
|
@ -659,8 +657,7 @@ export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction):
|
|||
return {
|
||||
type: 'peer_chosen',
|
||||
buttonId: act.buttonId,
|
||||
peerId: getMarkedPeerId(act.peer),
|
||||
// todo - pass the peer itself?
|
||||
peers: act.peers.map((it) => parsePeer(it, this._peers)),
|
||||
}
|
||||
case 'messageActionSetChatWallPaper':
|
||||
case 'messageActionSetSameChatWallPaper':
|
||||
|
|
|
@ -24,6 +24,7 @@ import { MaskPosition, Sticker, StickerSourceType, StickerType, Thumbnail } from
|
|||
* when reacting to messages using a normal emoji without a custom animation
|
||||
* - `"default_statuses"` - Default custom emoji status stickerset
|
||||
* - `"default_topic_icons"` - Default custom emoji stickerset for forum topic icons
|
||||
* - `"default_channel_statuses"` - Default custom emoji status stickerset for channels
|
||||
*/
|
||||
export type InputStickerSet =
|
||||
| tl.TypeInputStickerSet
|
||||
|
@ -36,6 +37,7 @@ export type InputStickerSet =
|
|||
| 'generic_animations'
|
||||
| 'default_statuses'
|
||||
| 'default_topic_icons'
|
||||
| 'default_channel_statuses'
|
||||
}
|
||||
| StickerSet
|
||||
| string
|
||||
|
@ -70,6 +72,8 @@ export function normalizeInputStickerSet(input: InputStickerSet): tl.TypeInputSt
|
|||
return { _: 'inputStickerSetEmojiDefaultStatuses' }
|
||||
case 'default_topic_icons':
|
||||
return { _: 'inputStickerSetEmojiDefaultTopicIcons' }
|
||||
case 'default_channel_statuses':
|
||||
return { _: 'inputStickerSetEmojiChannelDefaultStatuses' }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { tl } from '@mtcute/core'
|
|||
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Photo } from '../media/index.js'
|
||||
import { Photo } from '../media/photo.js'
|
||||
import { User } from './user.js'
|
||||
|
||||
/**
|
||||
|
|
70
packages/client/src/types/premium/boost-slot.ts
Normal file
70
packages/client/src/types/premium/boost-slot.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
import { assertTypeIs } from '@mtcute/core/utils.js'
|
||||
|
||||
import { makeInspectable } from '../../utils/inspectable.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Chat, PeersIndex } from '../peers/index.js'
|
||||
|
||||
/**
|
||||
* Information about a boost slot
|
||||
*/
|
||||
export class BoostSlot {
|
||||
constructor(
|
||||
readonly raw: tl.RawMyBoost,
|
||||
readonly _peers: PeersIndex,
|
||||
) {}
|
||||
|
||||
/** ID of this slot */
|
||||
get id(): number {
|
||||
return this.raw.slot
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this slot is occupied
|
||||
*/
|
||||
get occupied(): boolean {
|
||||
return this.raw.peer !== undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel that is occupying this slot, if any
|
||||
*/
|
||||
get chat(): Chat | null {
|
||||
if (!this.raw.peer) return null
|
||||
|
||||
assertTypeIs('BoostSlot.chat', this.raw.peer, 'peerChannel')
|
||||
|
||||
return new Chat(this._peers.chat(this.raw.peer.channelId))
|
||||
}
|
||||
|
||||
/**
|
||||
* Date when we started boosting this channel
|
||||
*
|
||||
* If this slot is not occupied, will be `0`
|
||||
*/
|
||||
get date(): Date {
|
||||
return new Date(this.raw.date * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Date when this boost will automatically expire.
|
||||
*/
|
||||
get expireDate(): Date {
|
||||
return new Date(this.raw.expires * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* If this slot is occupied, returns the date when
|
||||
* we can reassing this slot to another channel.
|
||||
*
|
||||
* If `null`, we can reassign it immediately.
|
||||
*/
|
||||
get cooldownUntil(): Date | null {
|
||||
if (!this.raw.cooldownUntilDate) return null
|
||||
|
||||
return new Date(this.raw.cooldownUntilDate * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
memoizeGetters(BoostSlot, ['chat'])
|
||||
makeInspectable(BoostSlot)
|
|
@ -28,6 +28,14 @@ export class BoostStats {
|
|||
return this.raw.nextLevelBoosts === undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of boosts acquired from created Telegram Premium
|
||||
* gift codes and giveaways, only available to channel admins
|
||||
*/
|
||||
get gifts(): number {
|
||||
return this.raw.giftBoosts ?? 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of boosts that were needed for the current level
|
||||
*/
|
||||
|
@ -80,6 +88,14 @@ export class BoostStats {
|
|||
get url(): string {
|
||||
return this.raw.boostUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link isBoosting}, IDs of the boost slots that are
|
||||
* currently occupied by this channel
|
||||
*/
|
||||
get boostSlots(): number[] {
|
||||
return this.raw.myBoostSlots ?? []
|
||||
}
|
||||
}
|
||||
|
||||
makeInspectable(BoostStats)
|
94
packages/client/src/types/premium/boost.ts
Normal file
94
packages/client/src/types/premium/boost.ts
Normal file
|
@ -0,0 +1,94 @@
|
|||
import { MtUnsupportedError, tl } from '@mtcute/core'
|
||||
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { PeersIndex, User } from '../peers/index.js'
|
||||
|
||||
/**
|
||||
* Origin of a boost
|
||||
*
|
||||
* - `gift` - boost applied because the channel gifted a subscription to some user
|
||||
* - `unclaimed_gift` - boost applied because the channel gifted a subscription to some user,
|
||||
* but the user hasn't yet claimed it
|
||||
* - `giveaway` - boost applied because the user was chosen in a giveaway
|
||||
* - `user` - boost applied because the user directly boosted the channel
|
||||
*/
|
||||
type BoostOrigin = 'gift' | 'unclaimed_gift' | 'giveaway' | 'user'
|
||||
|
||||
/**
|
||||
* Information about a boost (one or more)
|
||||
*/
|
||||
export class Boost {
|
||||
constructor(
|
||||
readonly raw: tl.RawBoost,
|
||||
readonly _peers: PeersIndex,
|
||||
) {}
|
||||
|
||||
/** Unique ID of this boost */
|
||||
get id(): string {
|
||||
return this.raw.id
|
||||
}
|
||||
|
||||
/** Number of boosts this boost is actually representing */
|
||||
get count(): number {
|
||||
return this.raw.multiplier ?? 1
|
||||
}
|
||||
|
||||
/** Date when this boost was applied */
|
||||
get date(): Date {
|
||||
return new Date(this.raw.date * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Date when this boost will automatically expire.
|
||||
*
|
||||
* > **Note**: User can still manually cancel the boost before that date
|
||||
*/
|
||||
get expireDate(): Date {
|
||||
return new Date(this.raw.expires * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this boost was applied because the channel
|
||||
* directly gifted a subscription to the user
|
||||
*/
|
||||
get origin(): BoostOrigin {
|
||||
if (this.raw.unclaimed) return 'unclaimed_gift'
|
||||
if (this.raw.gift) return 'gift'
|
||||
if (this.raw.giveaway) return 'giveaway'
|
||||
if (this.raw.userId) return 'user'
|
||||
|
||||
throw new MtUnsupportedError('Unknown boost origin')
|
||||
}
|
||||
|
||||
/**
|
||||
* User who is boosting the channel.
|
||||
*
|
||||
* Only available for some origins
|
||||
*/
|
||||
get user(): User | null {
|
||||
if (!this.raw.userId) return null
|
||||
|
||||
return new User(this._peers.user(this.raw.userId))
|
||||
}
|
||||
|
||||
/**
|
||||
* ID of the message containing the giveaway where this
|
||||
* user has won
|
||||
*/
|
||||
get giveawayMessageId(): number | null {
|
||||
return this.raw.giveawayMsgId ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* The created Telegram Premium gift code, only set if `origin` is not `user`,
|
||||
* AND it is either a gift code for the currently logged in user,
|
||||
* or if it was already claimed
|
||||
*/
|
||||
get usedGiftSlug(): string | null {
|
||||
return this.raw.usedGiftSlug ?? null
|
||||
}
|
||||
}
|
||||
|
||||
memoizeGetters(Boost, ['user'])
|
||||
makeInspectable(Boost)
|
3
packages/client/src/types/premium/index.ts
Normal file
3
packages/client/src/types/premium/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from './boost.js'
|
||||
export * from './boost-slot.js'
|
||||
export * from './boost-stats.js'
|
|
@ -1,34 +0,0 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { PeersIndex, User } from '../peers/index.js'
|
||||
|
||||
/**
|
||||
* Information about a user who is boosting a channel
|
||||
*/
|
||||
export class Booster {
|
||||
constructor(
|
||||
readonly raw: tl.RawBooster,
|
||||
readonly _peers: PeersIndex,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Date when this boost will automatically expire.
|
||||
*
|
||||
* > **Note**: User can still manually cancel the boost before that date
|
||||
*/
|
||||
get expireDate(): Date {
|
||||
return new Date(this.raw.expires * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* User who is boosting the channel
|
||||
*/
|
||||
get user(): User {
|
||||
return new User(this._peers.user(this.raw.userId))
|
||||
}
|
||||
}
|
||||
|
||||
memoizeGetters(Booster, ['user'])
|
||||
makeInspectable(Booster)
|
|
@ -1,6 +1,4 @@
|
|||
export * from './all-stories.js'
|
||||
export * from './boost-stats.js'
|
||||
export * from './booster.js'
|
||||
export * from './interactive/index.js'
|
||||
export * from './peer-stories.js'
|
||||
export * from './stealth-mode.js'
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { makeInspectable } from '../../../utils/index.js'
|
||||
import { memoizeGetters } from '../../../utils/memoize.js'
|
||||
import { Chat } from '../../peers/chat.js'
|
||||
import { PeersIndex } from '../../peers/peers-index.js'
|
||||
import { StoryInteractiveArea } from './base.js'
|
||||
|
||||
/**
|
||||
* Interactive element containing a channel post
|
||||
*/
|
||||
export class StoryInteractiveChannelPost extends StoryInteractiveArea {
|
||||
readonly type = 'channel_post' as const
|
||||
|
||||
constructor(
|
||||
readonly raw: tl.RawMediaAreaChannelPost,
|
||||
readonly _peers: PeersIndex,
|
||||
) {
|
||||
super(raw)
|
||||
}
|
||||
|
||||
/** Channel being mentioned */
|
||||
get chat(): Chat {
|
||||
return new Chat(this._peers.chat(this.raw.channelId))
|
||||
}
|
||||
|
||||
/** ID of the message being mentioned */
|
||||
get messageId(): number {
|
||||
return this.raw.msgId
|
||||
}
|
||||
}
|
||||
|
||||
memoizeGetters(StoryInteractiveChannelPost, ['chat'])
|
||||
makeInspectable(StoryInteractiveChannelPost)
|
|
@ -1,15 +1,21 @@
|
|||
import { MtTypeAssertionError, tl } from '@mtcute/core'
|
||||
|
||||
import { PeersIndex } from '../../peers/index.js'
|
||||
import { StoryInteractiveChannelPost } from './channel-post.js'
|
||||
import { StoryInteractiveLocation } from './location.js'
|
||||
import { StoryInteractiveReaction } from './reaction.js'
|
||||
import { StoryInteractiveVenue } from './venue.js'
|
||||
|
||||
export * from './input.js'
|
||||
export { StoryInteractiveLocation, StoryInteractiveReaction, StoryInteractiveVenue }
|
||||
export { StoryInteractiveChannelPost, StoryInteractiveLocation, StoryInteractiveReaction, StoryInteractiveVenue }
|
||||
|
||||
export type StoryInteractiveElement = StoryInteractiveReaction | StoryInteractiveLocation | StoryInteractiveVenue
|
||||
export type StoryInteractiveElement =
|
||||
| StoryInteractiveReaction
|
||||
| StoryInteractiveLocation
|
||||
| StoryInteractiveVenue
|
||||
| StoryInteractiveChannelPost
|
||||
|
||||
export function _storyInteractiveElementFromTl(raw: tl.TypeMediaArea): StoryInteractiveElement {
|
||||
export function _storyInteractiveElementFromTl(raw: tl.TypeMediaArea, peers: PeersIndex): StoryInteractiveElement {
|
||||
switch (raw._) {
|
||||
case 'mediaAreaSuggestedReaction':
|
||||
return new StoryInteractiveReaction(raw)
|
||||
|
@ -17,7 +23,10 @@ export function _storyInteractiveElementFromTl(raw: tl.TypeMediaArea): StoryInte
|
|||
return new StoryInteractiveLocation(raw)
|
||||
case 'mediaAreaVenue':
|
||||
return new StoryInteractiveVenue(raw)
|
||||
case 'mediaAreaChannelPost':
|
||||
return new StoryInteractiveChannelPost(raw, peers)
|
||||
case 'inputMediaAreaVenue':
|
||||
case 'inputMediaAreaChannelPost':
|
||||
throw new MtTypeAssertionError('StoryInteractiveElement', '!input*', raw._)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
import { MtTypeAssertionError, tl } from '@mtcute/core'
|
||||
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { PeersIndex, User } from '../peers/index.js'
|
||||
import { Message } from '../messages/index.js'
|
||||
import { parsePeer, Peer, PeersIndex, User } from '../peers/index.js'
|
||||
import { ReactionEmoji, toReactionEmoji } from '../reactions/index.js'
|
||||
import { Story } from './story.js'
|
||||
|
||||
/**
|
||||
* Information about a single user who has viewed a story.
|
||||
|
@ -45,6 +47,83 @@ export class StoryViewer {
|
|||
memoizeGetters(StoryViewer, ['user'])
|
||||
makeInspectable(StoryViewer)
|
||||
|
||||
/**
|
||||
* Kind of a story repost.
|
||||
* - `forward` - a story has been forwarded somewhere
|
||||
* - `repost` - a story has been reposted as a story
|
||||
*/
|
||||
export type StoryRepostKind = 'forward' | 'repost'
|
||||
|
||||
/**
|
||||
* Information about a single story repost.
|
||||
*/
|
||||
export class StoryRepost {
|
||||
constructor(
|
||||
readonly raw: tl.RawStoryViewPublicForward | tl.RawStoryViewPublicRepost,
|
||||
readonly _peers: PeersIndex,
|
||||
) {}
|
||||
|
||||
/** Whether this peer is in current user's global blacklist */
|
||||
get isBlocked(): boolean {
|
||||
return this.raw.blocked!
|
||||
}
|
||||
|
||||
/** Whether current user's stories are hidden from this peer */
|
||||
get isStoriesBlocked(): boolean {
|
||||
return this.raw.blockedMyStoriesFrom!
|
||||
}
|
||||
|
||||
/** Kind of the repost */
|
||||
get kind(): StoryRepostKind {
|
||||
return this.raw._ === 'storyViewPublicForward' ? 'forward' : 'repost'
|
||||
}
|
||||
|
||||
/** Date when the repost has happened */
|
||||
get date(): Date {
|
||||
if (this.raw._ === 'storyViewPublicForward' && this.raw.message._ === 'message') {
|
||||
return new Date(this.raw.message.date * 1000)
|
||||
}
|
||||
|
||||
if (this.raw._ === 'storyViewPublicRepost' && this.raw.story._ === 'storyItem') {
|
||||
return new Date(this.raw.story.date * 1000)
|
||||
}
|
||||
|
||||
throw new MtTypeAssertionError('StoryRepost', 'date', 'none')
|
||||
}
|
||||
|
||||
/**
|
||||
* Message that has been forwarded/reposted.
|
||||
*
|
||||
* Only available if {@link kind} is `forward`.
|
||||
*/
|
||||
get message(): Message | null {
|
||||
if (this.raw._ === 'storyViewPublicRepost') return null
|
||||
|
||||
return new Message(this.raw.message, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
* Story that has been reposted.
|
||||
*
|
||||
* Only available if {@link kind} is `repost`.
|
||||
*/
|
||||
get story(): Story | null {
|
||||
if (this.raw._ === 'storyViewPublicForward') return null
|
||||
if (this.raw.story._ !== 'storyItem') return null
|
||||
|
||||
return new Story(this.raw.story, this._peers)
|
||||
}
|
||||
|
||||
/** Information about the peer who has made the reposted */
|
||||
get peer(): Peer {
|
||||
if (this.raw._ === 'storyViewPublicForward') {
|
||||
return this.message!.sender
|
||||
}
|
||||
|
||||
return parsePeer(this.raw.peerId, this._peers)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of story viewers.
|
||||
*/
|
||||
|
@ -70,7 +149,15 @@ export class StoryViewersList {
|
|||
|
||||
/** List of viewers */
|
||||
get viewers(): StoryViewer[] {
|
||||
return this.raw.views.map((it) => new StoryViewer(it, this._peers))
|
||||
const res: StoryViewer[] = []
|
||||
|
||||
for (const view of this.raw.views) {
|
||||
if (view._ === 'storyView') {
|
||||
res.push(new StoryViewer(view, this._peers))
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,9 @@ export class Story {
|
|||
|
||||
return new Photo(this.raw.media.photo, this.raw.media)
|
||||
case 'messageMediaDocument': {
|
||||
if (this.raw.media.document?._ !== 'document') { throw new MtUnsupportedError('Unsupported story media type') }
|
||||
if (this.raw.media.document?._ !== 'document') {
|
||||
throw new MtUnsupportedError('Unsupported story media type')
|
||||
}
|
||||
|
||||
const doc = parseDocument(this.raw.media.document, this.raw.media)
|
||||
if (doc.type === 'video') return doc
|
||||
|
@ -138,7 +140,7 @@ export class Story {
|
|||
get interactiveElements(): StoryInteractiveElement[] {
|
||||
if (!this.raw.mediaAreas) return []
|
||||
|
||||
return this.raw.mediaAreas.map((it) => _storyInteractiveElementFromTl(it))
|
||||
return this.raw.mediaAreas.map((it) => _storyInteractiveElementFromTl(it, this._peers))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
TL schema and related utils used for mtcute.
|
||||
|
||||
Generated from TL layer **167** (last updated on 01.12.2023).
|
||||
Generated from TL layer **169** (last updated on 24.12.2023).
|
||||
|
||||
## About
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -10,7 +10,7 @@
|
|||
"attachMenuBot": ["bot_id"],
|
||||
"autoDownloadSettings": ["video_size_max", "file_size_max"],
|
||||
"botInfo": ["user_id"],
|
||||
"booster": ["user_id"],
|
||||
"boost": ["user_id"],
|
||||
"channel": ["id"],
|
||||
"channelAdminLogEvent": ["user_id"],
|
||||
"channelAdminLogEventActionChangeLinkedChat": ["prev_value", "new_value"],
|
||||
|
@ -56,6 +56,7 @@
|
|||
"inputUser": ["user_id"],
|
||||
"inputUserFromMessage": ["user_id"],
|
||||
"keyboardButtonUserProfile": ["user_id"],
|
||||
"mediaAreaChannelPost": ["channel_id"],
|
||||
"message": ["via_bot_id"],
|
||||
"messageActionChannelMigrateFrom": ["chat_id"],
|
||||
"messageActionChatAddUser": ["users"],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mtcute/tl",
|
||||
"version": "167.0.1",
|
||||
"version": "169.0.0",
|
||||
"description": "TL schema used for mtcute",
|
||||
"main": "index.js",
|
||||
"author": "Alina Sireneva <alina@tei.su>",
|
||||
|
|
Loading…
Reference in a new issue