feat: more stories-related stuff
i forgor 💀
This commit is contained in:
parent
c13cb93b97
commit
15b76aab60
12 changed files with 224 additions and 2 deletions
|
@ -229,6 +229,7 @@ import {
|
||||||
} from './methods/updates'
|
} from './methods/updates'
|
||||||
import { blockUser } from './methods/users/block-user'
|
import { blockUser } from './methods/users/block-user'
|
||||||
import { deleteProfilePhotos } from './methods/users/delete-profile-photos'
|
import { deleteProfilePhotos } from './methods/users/delete-profile-photos'
|
||||||
|
import { editCloseFriends, editCloseFriendsRaw } from './methods/users/edit-close-friends'
|
||||||
import { getCommonChats } from './methods/users/get-common-chats'
|
import { getCommonChats } from './methods/users/get-common-chats'
|
||||||
import { getGlobalTtl } from './methods/users/get-global-ttl'
|
import { getGlobalTtl } from './methods/users/get-global-ttl'
|
||||||
import { getMe } from './methods/users/get-me'
|
import { getMe } from './methods/users/get-me'
|
||||||
|
@ -266,6 +267,7 @@ import {
|
||||||
ChosenInlineResult,
|
ChosenInlineResult,
|
||||||
Conversation,
|
Conversation,
|
||||||
DeleteMessageUpdate,
|
DeleteMessageUpdate,
|
||||||
|
DeleteStoryUpdate,
|
||||||
Dialog,
|
Dialog,
|
||||||
FileDownloadParameters,
|
FileDownloadParameters,
|
||||||
FormattedString,
|
FormattedString,
|
||||||
|
@ -307,6 +309,7 @@ import {
|
||||||
StoriesStealthMode,
|
StoriesStealthMode,
|
||||||
Story,
|
Story,
|
||||||
StoryInteractions,
|
StoryInteractions,
|
||||||
|
StoryUpdate,
|
||||||
StoryViewer,
|
StoryViewer,
|
||||||
StoryViewersList,
|
StoryViewersList,
|
||||||
TakeoutSession,
|
TakeoutSession,
|
||||||
|
@ -464,6 +467,20 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
* @param handler Pre checkout query handler
|
* @param handler Pre checkout query handler
|
||||||
*/
|
*/
|
||||||
on(name: 'pre_checkout_query', handler: (upd: PreCheckoutQuery) => void): this
|
on(name: 'pre_checkout_query', handler: (upd: PreCheckoutQuery) => void): this
|
||||||
|
/**
|
||||||
|
* Register a story update handler
|
||||||
|
*
|
||||||
|
* @param name Event name
|
||||||
|
* @param handler Story update handler
|
||||||
|
*/
|
||||||
|
on(name: 'story', handler: (upd: StoryUpdate) => void): this
|
||||||
|
/**
|
||||||
|
* Register a delete story handler
|
||||||
|
*
|
||||||
|
* @param name Event name
|
||||||
|
* @param handler Delete story handler
|
||||||
|
*/
|
||||||
|
on(name: 'delete_story', handler: (upd: DeleteStoryUpdate) => void): this
|
||||||
/**
|
/**
|
||||||
* Accept the given TOS
|
* Accept the given TOS
|
||||||
*
|
*
|
||||||
|
@ -4139,6 +4156,8 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
* - `{ can: false }` if the user can't apply boost
|
* - `{ can: false }` if the user can't apply boost
|
||||||
* - `.reason == "already_boosting"` if the user is already boosting this channel
|
* - `.reason == "already_boosting"` if the user is already boosting this channel
|
||||||
* - `.reason == "need_premium"` if the user needs Premium to boost 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>
|
canApplyBoost(peerId: InputPeerLike): Promise<CanApplyBoostResult>
|
||||||
/**
|
/**
|
||||||
|
@ -4730,6 +4749,18 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
* @param ids ID(s) of the photos. Can be file IDs or raw TL objects
|
* @param ids ID(s) of the photos. Can be file IDs or raw TL objects
|
||||||
*/
|
*/
|
||||||
deleteProfilePhotos(ids: MaybeArray<string | tl.TypeInputPhoto>): Promise<void>
|
deleteProfilePhotos(ids: MaybeArray<string | tl.TypeInputPhoto>): Promise<void>
|
||||||
|
/**
|
||||||
|
* Edit "close friends" list directly using user IDs
|
||||||
|
*
|
||||||
|
* @param ids User IDs
|
||||||
|
*/
|
||||||
|
editCloseFriendsRaw(ids: number[]): Promise<void>
|
||||||
|
/**
|
||||||
|
* Edit "close friends" list using `InputPeerLike`s
|
||||||
|
*
|
||||||
|
* @param ids User IDs
|
||||||
|
*/
|
||||||
|
editCloseFriends(ids: InputPeerLike[]): Promise<void>
|
||||||
/**
|
/**
|
||||||
* Get a list of common chats you have with a given user
|
* Get a list of common chats you have with a given user
|
||||||
*
|
*
|
||||||
|
@ -5211,6 +5242,8 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
_keepAliveAction = _keepAliveAction
|
_keepAliveAction = _keepAliveAction
|
||||||
blockUser = blockUser
|
blockUser = blockUser
|
||||||
deleteProfilePhotos = deleteProfilePhotos
|
deleteProfilePhotos = deleteProfilePhotos
|
||||||
|
editCloseFriendsRaw = editCloseFriendsRaw
|
||||||
|
editCloseFriends = editCloseFriends
|
||||||
getCommonChats = getCommonChats
|
getCommonChats = getCommonChats
|
||||||
getGlobalTtl = getGlobalTtl
|
getGlobalTtl = getGlobalTtl
|
||||||
getMe = getMe
|
getMe = getMe
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
ChosenInlineResult,
|
ChosenInlineResult,
|
||||||
Conversation,
|
Conversation,
|
||||||
DeleteMessageUpdate,
|
DeleteMessageUpdate,
|
||||||
|
DeleteStoryUpdate,
|
||||||
Dialog,
|
Dialog,
|
||||||
FileDownloadParameters,
|
FileDownloadParameters,
|
||||||
FormattedString,
|
FormattedString,
|
||||||
|
@ -72,6 +73,7 @@ import {
|
||||||
StoriesStealthMode,
|
StoriesStealthMode,
|
||||||
Story,
|
Story,
|
||||||
StoryInteractions,
|
StoryInteractions,
|
||||||
|
StoryUpdate,
|
||||||
StoryViewer,
|
StoryViewer,
|
||||||
StoryViewersList,
|
StoryViewersList,
|
||||||
TakeoutSession,
|
TakeoutSession,
|
||||||
|
|
|
@ -192,6 +192,14 @@ export async function _normalizeInputMedia(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (media.type === 'story') {
|
||||||
|
return {
|
||||||
|
_: 'inputMediaStory',
|
||||||
|
peer: await this.resolvePeer(media.peer),
|
||||||
|
id: media.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let inputFile: tl.TypeInputFile | undefined = undefined
|
let inputFile: tl.TypeInputFile | undefined = undefined
|
||||||
let thumb: tl.TypeInputFile | undefined = undefined
|
let thumb: tl.TypeInputFile | undefined = undefined
|
||||||
let mime = 'application/octet-stream'
|
let mime = 'application/octet-stream'
|
||||||
|
|
35
packages/client/src/methods/users/edit-close-friends.ts
Normal file
35
packages/client/src/methods/users/edit-close-friends.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { TelegramClient } from '../../client'
|
||||||
|
import { InputPeerLike } from '../../types'
|
||||||
|
import { normalizeToInputUser } from '../../utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit "close friends" list directly using user IDs
|
||||||
|
*
|
||||||
|
* @param ids User IDs
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export async function editCloseFriendsRaw(this: TelegramClient, ids: number[]): Promise<void> {
|
||||||
|
await this.call({
|
||||||
|
_: 'contacts.editCloseFriends',
|
||||||
|
id: ids,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit "close friends" list using `InputPeerLike`s
|
||||||
|
*
|
||||||
|
* @param ids User IDs
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export async function editCloseFriends(this: TelegramClient, ids: InputPeerLike[]): Promise<void> {
|
||||||
|
await this.call({
|
||||||
|
_: 'contacts.editCloseFriends',
|
||||||
|
id: await this.resolvePeerMany(ids, normalizeToInputUser).then((r) =>
|
||||||
|
r.map((u) => {
|
||||||
|
if ('userId' in u) return u.userId
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { MaybeArray, tl } from '@mtcute/core'
|
||||||
|
|
||||||
import { InputFileLike } from '../files'
|
import { InputFileLike } from '../files'
|
||||||
import { FormattedString } from '../parser'
|
import { FormattedString } from '../parser'
|
||||||
|
import { InputPeerLike } from '../peers'
|
||||||
import { VenueSource } from './venue'
|
import { VenueSource } from './venue'
|
||||||
|
|
||||||
export interface CaptionMixin {
|
export interface CaptionMixin {
|
||||||
|
@ -539,6 +540,23 @@ export interface InputMediaQuiz extends Omit<InputMediaPoll, 'type'> {
|
||||||
solutionEntities?: tl.TypeMessageEntity[]
|
solutionEntities?: tl.TypeMessageEntity[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A story to be sent
|
||||||
|
*/
|
||||||
|
export interface InputMediaStory extends CaptionMixin {
|
||||||
|
type: 'story'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Owner of the story
|
||||||
|
*/
|
||||||
|
peer: InputPeerLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the story
|
||||||
|
*/
|
||||||
|
id: number
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input media that can be sent somewhere.
|
* Input media that can be sent somewhere.
|
||||||
*
|
*
|
||||||
|
@ -565,6 +583,7 @@ export type InputMediaLike =
|
||||||
| InputMediaInvoice
|
| InputMediaInvoice
|
||||||
| InputMediaPoll
|
| InputMediaPoll
|
||||||
| InputMediaQuiz
|
| InputMediaQuiz
|
||||||
|
| InputMediaStory
|
||||||
| tl.TypeInputMedia
|
| tl.TypeInputMedia
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
@ -801,6 +820,18 @@ export namespace InputMedia {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a story to be sent
|
||||||
|
*
|
||||||
|
* @param params Story parameters
|
||||||
|
*/
|
||||||
|
export function story(params: OmitTypeAndFile<InputMediaStory>): InputMediaStory {
|
||||||
|
const ret = params as tl.Mutable<InputMediaStory>
|
||||||
|
ret.type = 'story'
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a document to be sent, which subtype
|
* Create a document to be sent, which subtype
|
||||||
* is inferred automatically by file contents.
|
* is inferred automatically by file contents.
|
||||||
|
|
|
@ -318,6 +318,15 @@ export class Message {
|
||||||
return this.raw.replyTo.replyToTopId ?? null
|
return this.raw.replyTo.replyToTopId ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For replies, information about the story that is being replied to
|
||||||
|
*/
|
||||||
|
get replyToStoryId(): tl.RawMessageReplyStoryHeader | null {
|
||||||
|
if (this.raw.replyTo?._ !== 'messageReplyStoryHeader') return null
|
||||||
|
|
||||||
|
return this.raw.replyTo
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this message contains mention of the current user
|
* Whether this message contains mention of the current user
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -202,6 +202,20 @@ export class Chat {
|
||||||
return this.peer._ === 'user' && this.peer.contact!
|
return this.peer._ === 'user' && this.peer.contact!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether this peer is a forum supergroup */
|
||||||
|
get isForum(): boolean {
|
||||||
|
return this.peer._ === 'channel' && this.peer.forum!
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether you have hidden (arhived) this chat's stories */
|
||||||
|
get storiesHidden(): boolean {
|
||||||
|
return 'storiesHidden' in this.peer ? this.peer.storiesHidden! : false
|
||||||
|
}
|
||||||
|
|
||||||
|
get storiesUnavailable(): boolean {
|
||||||
|
return 'storiesUnavailable' in this.peer ? this.peer.storiesUnavailable! : false
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether this group is a channel/supergroup with join requests enabled */
|
/** Whether this group is a channel/supergroup with join requests enabled */
|
||||||
get hasJoinRequests(): boolean {
|
get hasJoinRequests(): boolean {
|
||||||
return this.peer._ === 'channel' && this.peer.joinRequest!
|
return this.peer._ === 'channel' && this.peer.joinRequest!
|
||||||
|
@ -451,6 +465,19 @@ export class Chat {
|
||||||
return this.fullPeer?.ttlPeriod ?? null
|
return this.fullPeer?.ttlPeriod ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum ID of stories this chat has (or 0 if none)
|
||||||
|
*/
|
||||||
|
get storiesMaxId(): number {
|
||||||
|
switch (this.peer._) {
|
||||||
|
case 'channel':
|
||||||
|
case 'user':
|
||||||
|
return this.peer.storiesMaxId ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
private _user?: User
|
private _user?: User
|
||||||
/**
|
/**
|
||||||
* Get a {@link User} from this chat.
|
* Get a {@link User} from this chat.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { TelegramClient } from '../../client'
|
||||||
import { makeInspectable } from '../../utils'
|
import { makeInspectable } from '../../utils'
|
||||||
import { InputMediaLike } from '../media'
|
import { InputMediaLike } from '../media'
|
||||||
import { FormattedString } from '../parser'
|
import { FormattedString } from '../parser'
|
||||||
|
import { EmojiStatus } from '../reactions/emoji-status'
|
||||||
import { ChatPhoto } from './chat-photo'
|
import { ChatPhoto } from './chat-photo'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,6 +61,11 @@ export class User {
|
||||||
return this.raw.mutualContact!
|
return this.raw.mutualContact!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether this user is in yout "close friends" list */
|
||||||
|
get isCloseFriend(): boolean {
|
||||||
|
return this.raw.closeFriend!
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether this user is deleted */
|
/** Whether this user is deleted */
|
||||||
get isDeleted(): boolean {
|
get isDeleted(): boolean {
|
||||||
return this.raw.deleted!
|
return this.raw.deleted!
|
||||||
|
@ -70,6 +76,26 @@ export class User {
|
||||||
return this.raw.bot!
|
return this.raw.bot!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether this user is a bot that has access to all messages */
|
||||||
|
get isBotWithHistory(): boolean {
|
||||||
|
return this.raw.botChatHistory!
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether this user is a bot that can't be added to chats */
|
||||||
|
get isBotWithoutChats(): boolean {
|
||||||
|
return this.raw.botNochats!
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether this bot offers an attachment menu web app */
|
||||||
|
get isBotWithAttachmentMenu(): boolean {
|
||||||
|
return this.raw.botAttachMenu!
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether this bot can be edited by the current user */
|
||||||
|
get isBotEditable(): boolean {
|
||||||
|
return this.raw.botCanEdit!
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether this user has been verified by Telegram */
|
/** Whether this user has been verified by Telegram */
|
||||||
get isVerified(): boolean {
|
get isVerified(): boolean {
|
||||||
return this.raw.verified!
|
return this.raw.verified!
|
||||||
|
@ -279,6 +305,32 @@ export class User {
|
||||||
return this.firstName
|
return this.firstName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _emojiStatus?: EmojiStatus
|
||||||
|
/**
|
||||||
|
* User's emoji status, if any.
|
||||||
|
*/
|
||||||
|
get emojiStatus(): EmojiStatus | null {
|
||||||
|
if (!this.raw.emojiStatus || this.raw.emojiStatus._ === 'emojiStatusEmpty') return null
|
||||||
|
|
||||||
|
return (this._emojiStatus ??= new EmojiStatus(this.raw.emojiStatus))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether you have hidden (arhived) this user's stories */
|
||||||
|
get storiesHidden(): boolean {
|
||||||
|
return this.raw.storiesHidden!
|
||||||
|
}
|
||||||
|
|
||||||
|
get storiesUnavailable(): boolean {
|
||||||
|
return this.raw.storiesUnavailable!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum ID of stories this user has (or 0 if none)
|
||||||
|
*/
|
||||||
|
get storiesMaxId(): number {
|
||||||
|
return this.raw.storiesMaxId ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a mention for the user.
|
* Create a mention for the user.
|
||||||
*
|
*
|
||||||
|
|
24
packages/client/src/types/reactions/emoji-status.ts
Normal file
24
packages/client/src/types/reactions/emoji-status.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { tl } from '@mtcute/core'
|
||||||
|
|
||||||
|
import { makeInspectable } from '../../utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about user's emoji status
|
||||||
|
*/
|
||||||
|
export class EmojiStatus {
|
||||||
|
constructor(readonly raw: Exclude<tl.TypeEmojiStatus, tl.RawEmojiStatusEmpty>) {}
|
||||||
|
|
||||||
|
/** ID of the custom emoji */
|
||||||
|
get emoji(): tl.Long {
|
||||||
|
return this.raw.documentId
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This status is valid at most until this date */
|
||||||
|
get expireDate(): Date | null {
|
||||||
|
if (this.raw._ === 'emojiStatus') return null
|
||||||
|
|
||||||
|
return new Date(this.raw.until * 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeInspectable(EmojiStatus)
|
File diff suppressed because one or more lines are too long
|
@ -153,6 +153,7 @@
|
||||||
"account.initTakeoutSession": ["file_max_size"],
|
"account.initTakeoutSession": ["file_max_size"],
|
||||||
"account.registerDevice": ["other_uids"],
|
"account.registerDevice": ["other_uids"],
|
||||||
"account.unregisterDevice": ["other_uids"],
|
"account.unregisterDevice": ["other_uids"],
|
||||||
|
"contacts.editCloseFriends": ["id"],
|
||||||
"messages.addChatUser": ["chat_id"],
|
"messages.addChatUser": ["chat_id"],
|
||||||
"messages.deleteChat": ["chat_id"],
|
"messages.deleteChat": ["chat_id"],
|
||||||
"messages.deleteChatUser": ["chat_id"],
|
"messages.deleteChatUser": ["chat_id"],
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"docs-cli": "ts-node scripts/documentation.ts",
|
"docs-cli": "ts-node scripts/documentation.ts",
|
||||||
"gen-code": "ts-node scripts/gen-code.ts",
|
"gen-code": "ts-node scripts/gen-code.ts",
|
||||||
"gen-rsa": "ts-node scripts/gen-rsa-keys.ts",
|
"gen-rsa": "ts-node scripts/gen-rsa-keys.ts",
|
||||||
"fetch-and-gen": "yarn fetch-api && yarn gen-code"
|
"fetch-and-gen": "pnpm run fetch-api && pnpm run gen-code"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"long": "5.2.3"
|
"long": "5.2.3"
|
||||||
|
|
Loading…
Reference in a new issue