feat: more stories-related stuff

i forgor 💀
This commit is contained in:
alina 🌸 2023-10-04 20:50:57 +03:00
parent c13cb93b97
commit 15b76aab60
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
12 changed files with 224 additions and 2 deletions

View file

@ -229,6 +229,7 @@ import {
} from './methods/updates'
import { blockUser } from './methods/users/block-user'
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 { getGlobalTtl } from './methods/users/get-global-ttl'
import { getMe } from './methods/users/get-me'
@ -266,6 +267,7 @@ import {
ChosenInlineResult,
Conversation,
DeleteMessageUpdate,
DeleteStoryUpdate,
Dialog,
FileDownloadParameters,
FormattedString,
@ -307,6 +309,7 @@ import {
StoriesStealthMode,
Story,
StoryInteractions,
StoryUpdate,
StoryViewer,
StoryViewersList,
TakeoutSession,
@ -464,6 +467,20 @@ export interface TelegramClient extends BaseTelegramClient {
* @param handler Pre checkout query handler
*/
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
*
@ -4139,6 +4156,8 @@ export interface TelegramClient extends BaseTelegramClient {
* - `{ 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>
/**
@ -4730,6 +4749,18 @@ export interface TelegramClient extends BaseTelegramClient {
* @param ids ID(s) of the photos. Can be file IDs or raw TL objects
*/
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
*
@ -5211,6 +5242,8 @@ export class TelegramClient extends BaseTelegramClient {
_keepAliveAction = _keepAliveAction
blockUser = blockUser
deleteProfilePhotos = deleteProfilePhotos
editCloseFriendsRaw = editCloseFriendsRaw
editCloseFriends = editCloseFriends
getCommonChats = getCommonChats
getGlobalTtl = getGlobalTtl
getMe = getMe

View file

@ -31,6 +31,7 @@ import {
ChosenInlineResult,
Conversation,
DeleteMessageUpdate,
DeleteStoryUpdate,
Dialog,
FileDownloadParameters,
FormattedString,
@ -72,6 +73,7 @@ import {
StoriesStealthMode,
Story,
StoryInteractions,
StoryUpdate,
StoryViewer,
StoryViewersList,
TakeoutSession,

View file

@ -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 thumb: tl.TypeInputFile | undefined = undefined
let mime = 'application/octet-stream'

View 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
}),
),
})
}

View file

@ -2,6 +2,7 @@ import { MaybeArray, tl } from '@mtcute/core'
import { InputFileLike } from '../files'
import { FormattedString } from '../parser'
import { InputPeerLike } from '../peers'
import { VenueSource } from './venue'
export interface CaptionMixin {
@ -539,6 +540,23 @@ export interface InputMediaQuiz extends Omit<InputMediaPoll, 'type'> {
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.
*
@ -565,6 +583,7 @@ export type InputMediaLike =
| InputMediaInvoice
| InputMediaPoll
| InputMediaQuiz
| InputMediaStory
| tl.TypeInputMedia
// eslint-disable-next-line @typescript-eslint/no-namespace
@ -801,6 +820,18 @@ export namespace InputMedia {
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
* is inferred automatically by file contents.

View file

@ -318,6 +318,15 @@ export class Message {
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
*/

View file

@ -202,6 +202,20 @@ export class Chat {
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 */
get hasJoinRequests(): boolean {
return this.peer._ === 'channel' && this.peer.joinRequest!
@ -451,6 +465,19 @@ export class Chat {
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
/**
* Get a {@link User} from this chat.

View file

@ -5,6 +5,7 @@ import { TelegramClient } from '../../client'
import { makeInspectable } from '../../utils'
import { InputMediaLike } from '../media'
import { FormattedString } from '../parser'
import { EmojiStatus } from '../reactions/emoji-status'
import { ChatPhoto } from './chat-photo'
/**
@ -60,6 +61,11 @@ export class User {
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 */
get isDeleted(): boolean {
return this.raw.deleted!
@ -70,6 +76,26 @@ export class User {
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 */
get isVerified(): boolean {
return this.raw.verified!
@ -279,6 +305,32 @@ export class User {
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.
*

View 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

View file

@ -153,6 +153,7 @@
"account.initTakeoutSession": ["file_max_size"],
"account.registerDevice": ["other_uids"],
"account.unregisterDevice": ["other_uids"],
"contacts.editCloseFriends": ["id"],
"messages.addChatUser": ["chat_id"],
"messages.deleteChat": ["chat_id"],
"messages.deleteChatUser": ["chat_id"],

View file

@ -13,7 +13,7 @@
"docs-cli": "ts-node scripts/documentation.ts",
"gen-code": "ts-node scripts/gen-code.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": {
"long": "5.2.3"