chore(client)!: better parsed peer handling
breaking: anonymous sender is now represented with `AnonymousSender` interface and not `string`
This commit is contained in:
parent
9db9411c27
commit
893a15d111
14 changed files with 120 additions and 145 deletions
|
@ -3,8 +3,8 @@ import { MtTypeAssertionError, tl } from '@mtcute/core'
|
|||
import { makeInspectable } from '../../utils/inspectable.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Chat } from '../peers/chat.js'
|
||||
import { parsePeer, PeerSender } from '../peers/peer.js'
|
||||
import { PeersIndex } from '../peers/peers-index.js'
|
||||
import { User } from '../peers/user.js'
|
||||
import { _messageMediaFromTl } from './message-media.js'
|
||||
|
||||
/**
|
||||
|
@ -27,20 +27,16 @@ export class MessageForwardInfo {
|
|||
* Sender of the original message (either user or a channel)
|
||||
* or their name (for users with private forwards)
|
||||
*/
|
||||
get sender(): User | Chat | string {
|
||||
get sender(): PeerSender {
|
||||
if (this.raw.fromName) {
|
||||
return this.raw.fromName
|
||||
return {
|
||||
type: 'anonymous',
|
||||
displayName: this.raw.fromName,
|
||||
}
|
||||
}
|
||||
|
||||
if (this.raw.fromId) {
|
||||
switch (this.raw.fromId._) {
|
||||
case 'peerChannel':
|
||||
return new Chat(this._peers.chat(this.raw.fromId.channelId))
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(this.raw.fromId.userId))
|
||||
default:
|
||||
throw new MtTypeAssertionError('raw.fwdFrom.fromId', 'peerUser | peerChannel', this.raw.fromId._)
|
||||
}
|
||||
return parsePeer(this.raw.fromId, this._peers)
|
||||
}
|
||||
|
||||
throw new MtTypeAssertionError('MessageForwardInfo', 'to have fromId or fromName', 'neither')
|
||||
|
@ -50,7 +46,7 @@ export class MessageForwardInfo {
|
|||
* For "saved" messages (i.e. messages forwarded to yourself,
|
||||
* "Saved Messages"), the peer where the message was originally sent
|
||||
*/
|
||||
fromChat(): User | Chat | null {
|
||||
fromChat(): Chat | null {
|
||||
if (!this.raw.savedFromPeer) return null
|
||||
|
||||
return Chat._parseFromPeer(this.raw.savedFromPeer, this._peers)
|
||||
|
|
|
@ -2,9 +2,8 @@ import { getMarkedPeerId, tl } from '@mtcute/core'
|
|||
|
||||
import { makeInspectable } from '../../utils/inspectable.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Chat } from '../peers/chat.js'
|
||||
import { parsePeer, Peer } from '../peers/peer.js'
|
||||
import { PeersIndex } from '../peers/peers-index.js'
|
||||
import { User } from '../peers/user.js'
|
||||
|
||||
/**
|
||||
* Information about replies to a message
|
||||
|
@ -65,19 +64,8 @@ export class MessageRepliesInfo {
|
|||
/**
|
||||
* Last few commenters to the post (usually 3)
|
||||
*/
|
||||
get repliers(): (User | Chat)[] {
|
||||
return (
|
||||
this.raw.recentRepliers?.map((it) => {
|
||||
switch (it._) {
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(it.userId))
|
||||
case 'peerChannel':
|
||||
return new Chat(this._peers.chat(it.channelId))
|
||||
default:
|
||||
throw new Error('Unexpected peer type: ' + it._)
|
||||
}
|
||||
}) ?? []
|
||||
)
|
||||
get repliers(): Peer[] {
|
||||
return this.raw.recentRepliers?.map((it) => parsePeer(it, this._peers)) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
import {
|
||||
assertNever,
|
||||
getMarkedPeerId,
|
||||
MtArgumentError,
|
||||
MtTypeAssertionError,
|
||||
tl,
|
||||
toggleChannelIdMark,
|
||||
} from '@mtcute/core'
|
||||
import { assertNever, getMarkedPeerId, MtArgumentError, tl, toggleChannelIdMark } from '@mtcute/core'
|
||||
import { assertTypeIsNot } from '@mtcute/core/utils.js'
|
||||
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
|
@ -13,6 +6,7 @@ import { memoizeGetters } from '../../utils/memoize.js'
|
|||
import { BotKeyboard, ReplyMarkup } from '../bots/keyboards.js'
|
||||
import { TextWithEntities } from '../misc/index.js'
|
||||
import { Chat } from '../peers/chat.js'
|
||||
import { parsePeer, Peer } from '../peers/peer.js'
|
||||
import { PeersIndex } from '../peers/peers-index.js'
|
||||
import { User } from '../peers/user.js'
|
||||
import { _messageActionFromTl, MessageAction } from './message-action.js'
|
||||
|
@ -114,7 +108,7 @@ export class Message {
|
|||
* If the message is a forwarded channel post,
|
||||
* sender is the channel itself.
|
||||
*/
|
||||
get sender(): User | Chat {
|
||||
get sender(): Peer {
|
||||
const from = this.raw.fromId
|
||||
|
||||
if (!from) {
|
||||
|
@ -125,14 +119,8 @@ export class Message {
|
|||
// anon admin, return the chat
|
||||
return this.chat
|
||||
}
|
||||
switch (from._) {
|
||||
case 'peerChannel': // forwarded channel post or anon
|
||||
return new Chat(this._peers.chat(from.channelId))
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(from.userId))
|
||||
default:
|
||||
throw new MtTypeAssertionError('raw.fromId', 'peerUser | peerChannel', from._)
|
||||
}
|
||||
|
||||
return parsePeer(from, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ import { MtTypeAssertionError, tl } from '@mtcute/core'
|
|||
import { makeInspectable } from '../../utils/inspectable.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Chat } from '../peers/chat.js'
|
||||
import { PeerSender } from '../peers/peer.js'
|
||||
import { PeersIndex } from '../peers/peers-index.js'
|
||||
import { User } from '../peers/user.js'
|
||||
import { MessageEntity } from './message-entity.js'
|
||||
|
@ -27,12 +28,12 @@ export interface _RepliedMessageAssertionsByOrigin {
|
|||
other_chat: {
|
||||
id: number
|
||||
chat: Chat
|
||||
sender: User | Chat | string
|
||||
sender: PeerSender
|
||||
}
|
||||
private: {
|
||||
id: null
|
||||
chat: null
|
||||
sender: User | Chat | string
|
||||
sender: PeerSender
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ export class RepliedMessageInfo {
|
|||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,12 +129,15 @@ export class RepliedMessageInfo {
|
|||
*
|
||||
* `null` if the sender is not available (for `same_chat` origin)
|
||||
*/
|
||||
get sender(): User | Chat | string | null {
|
||||
get sender(): PeerSender | null {
|
||||
const { replyFrom, replyToPeerId } = this.raw
|
||||
if (!replyFrom && !replyToPeerId) return null
|
||||
|
||||
if (replyFrom?.fromName) {
|
||||
return replyFrom.fromName
|
||||
return {
|
||||
type: 'anonymous',
|
||||
displayName: replyFrom.fromName,
|
||||
}
|
||||
}
|
||||
|
||||
const peer = replyFrom?.fromId ?? replyToPeerId
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { MtTypeAssertionError, tl } from '@mtcute/core'
|
||||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { hasValueAtKey, makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { MtMessageNotFoundError } from '../errors.js'
|
||||
import { DraftMessage, Message } from '../messages/index.js'
|
||||
import { Chat } from './chat.js'
|
||||
import { parsePeer, Peer } from './peer.js'
|
||||
import { PeersIndex } from './peers-index.js'
|
||||
import { User } from './user.js'
|
||||
|
||||
export class ForumTopic {
|
||||
static COLOR_BLUE = 0x6fb9f0
|
||||
|
@ -108,15 +107,8 @@ export class ForumTopic {
|
|||
/**
|
||||
* Creator of the topic
|
||||
*/
|
||||
get creator(): User | Chat {
|
||||
switch (this.raw.fromId._) {
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(this.raw.fromId.userId))
|
||||
case 'peerChat':
|
||||
return new Chat(this._peers.chat(this.raw.fromId.chatId))
|
||||
default:
|
||||
throw new MtTypeAssertionError('ForumTopic#creator', 'peerUser | peerChat', this.raw.fromId._)
|
||||
}
|
||||
get creator(): Peer {
|
||||
return parsePeer(this.raw.fromId, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
|
||||
export * from './chat.js'
|
||||
export * from './chat-event/index.js'
|
||||
export * from './chat-invite-link.js'
|
||||
|
@ -10,33 +8,7 @@ export * from './chat-permissions.js'
|
|||
export * from './chat-photo.js'
|
||||
export * from './chat-preview.js'
|
||||
export * from './forum-topic.js'
|
||||
export * from './peer.js'
|
||||
export * from './peers-index.js'
|
||||
export * from './typing-status.js'
|
||||
export * from './user.js'
|
||||
|
||||
/**
|
||||
* More extensive peer types, that differentiate between
|
||||
* users and bots, channels and supergroups.
|
||||
*/
|
||||
export type PeerType = 'user' | 'bot' | 'group' | 'channel' | 'supergroup'
|
||||
|
||||
/**
|
||||
* Type that can be used as an input peer to most of the high-level methods. Can be:
|
||||
* - `number`, representing peer's marked ID*
|
||||
* - `string`, representing peer's username (without preceding `@`)
|
||||
* - `string`, representing user's phone number
|
||||
* - `"me"` and `"self"` which will be replaced with the current user/bot
|
||||
* - Any object with `inputPeer: tl.TypeInputPeer` property
|
||||
* - Raw TL object
|
||||
*
|
||||
* > * Telegram has moved to int64 IDs. Though, Levin [has confirmed](https://t.me/tdlibchat/25071)
|
||||
* > that new IDs *will* still fit into int53, meaning JS integers are fine.
|
||||
*/
|
||||
export type InputPeerLike =
|
||||
| string
|
||||
| number
|
||||
| tl.TypePeer
|
||||
| tl.TypeInputPeer
|
||||
| tl.TypeInputUser
|
||||
| tl.TypeInputChannel
|
||||
| { inputPeer: tl.TypeInputPeer }
|
||||
|
|
71
packages/client/src/types/peers/peer.ts
Normal file
71
packages/client/src/types/peers/peer.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { Chat } from './chat.js'
|
||||
import { PeersIndex } from './peers-index.js'
|
||||
import { User } from './user.js'
|
||||
|
||||
/**
|
||||
* More extensive peer types, that differentiate between
|
||||
* users and bots, channels and supergroups.
|
||||
*/
|
||||
export type PeerType = 'user' | 'bot' | 'group' | 'channel' | 'supergroup'
|
||||
|
||||
/**
|
||||
* Type that can be used as an input peer to most of the high-level methods. Can be:
|
||||
* - `number`, representing peer's marked ID*
|
||||
* - `string`, representing peer's username (without preceding `@`)
|
||||
* - `string`, representing user's phone number
|
||||
* - `"me"` and `"self"` which will be replaced with the current user/bot
|
||||
* - Any object with `inputPeer: tl.TypeInputPeer` property
|
||||
* - Raw TL object
|
||||
*
|
||||
* > * Telegram has moved to int64 IDs. Though, Levin [has confirmed](https://t.me/tdlibchat/25071)
|
||||
* > that new IDs *will* still fit into int53, meaning JS integers are fine.
|
||||
*/
|
||||
export type InputPeerLike =
|
||||
| string
|
||||
| number
|
||||
| tl.TypePeer
|
||||
| tl.TypeInputPeer
|
||||
| tl.TypeInputUser
|
||||
| tl.TypeInputChannel
|
||||
| { inputPeer: tl.TypeInputPeer }
|
||||
|
||||
/**
|
||||
* Peer (a user or a chat)
|
||||
*
|
||||
* Type of the peer can be determined by the `.type` property
|
||||
*/
|
||||
export type Peer = User | Chat
|
||||
|
||||
/**
|
||||
* An object representing an anonymous sender (e.g. for users that have forwards hidden)
|
||||
*/
|
||||
export interface AnonymousSender {
|
||||
readonly type: 'anonymous'
|
||||
|
||||
/**
|
||||
* Name of the anonymous sender that should be displayed
|
||||
*/
|
||||
readonly displayName: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Object representing a sender of a forwarded message,
|
||||
* which can be either a {@link Peer} or an {@link AnonymousSender}
|
||||
*/
|
||||
export type PeerSender = Peer | AnonymousSender
|
||||
|
||||
/**
|
||||
* Given a `tl.TypePeer`, return a {@link Peer} object ({@link User} or {@link Chat})
|
||||
*/
|
||||
export function parsePeer(peer: tl.TypePeer, index: PeersIndex): Peer {
|
||||
switch (peer._) {
|
||||
case 'peerUser':
|
||||
return new User(index.user(peer.userId))
|
||||
case 'peerChat':
|
||||
return new Chat(index.chat(peer.chatId))
|
||||
case 'peerChannel':
|
||||
return new Chat(index.chat(peer.channelId))
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import { tl } from '@mtcute/core'
|
|||
|
||||
import { assertTypeIs, makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Chat, PeersIndex, User } from '../peers/index.js'
|
||||
import { parsePeer, Peer, PeersIndex } from '../peers/index.js'
|
||||
import { Story } from './story.js'
|
||||
|
||||
export class PeerStories {
|
||||
|
@ -14,15 +14,8 @@ export class PeerStories {
|
|||
/**
|
||||
* Peer that owns these stories.
|
||||
*/
|
||||
get peer(): User | Chat {
|
||||
switch (this.raw.peer._) {
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(this.raw.peer.userId))
|
||||
case 'peerChat':
|
||||
return new Chat(this._peers.chat(this.raw.peer.chatId))
|
||||
case 'peerChannel':
|
||||
return new Chat(this._peers.chat(this.raw.peer.channelId))
|
||||
}
|
||||
get peer(): Peer {
|
||||
return parsePeer(this.raw.peer, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { Chat, PeersIndex, User } from '../../types/peers/index.js'
|
||||
import { parsePeer, Peer, PeersIndex } from '../../types/peers/index.js'
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
|
||||
|
@ -16,15 +16,8 @@ export class DeleteStoryUpdate {
|
|||
/**
|
||||
* Peer that owns these stories.
|
||||
*/
|
||||
get peer(): User | Chat {
|
||||
switch (this.raw.peer._) {
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(this.raw.peer.userId))
|
||||
case 'peerChat':
|
||||
return new Chat(this._peers.chat(this.raw.peer.chatId))
|
||||
case 'peerChannel':
|
||||
return new Chat(this._peers.chat(this.raw.peer.channelId))
|
||||
}
|
||||
get peer(): Peer {
|
||||
return parsePeer(this.raw.peer, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { MtUnsupportedError, tl } from '@mtcute/core'
|
||||
import { assertTypeIs } from '@mtcute/core/utils.js'
|
||||
|
||||
import { makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
import { Chat, PeersIndex, User } from '../peers/index.js'
|
||||
import { parsePeer, Peer, PeersIndex } from '../peers/index.js'
|
||||
|
||||
/**
|
||||
* Some user has voted in a public poll.
|
||||
|
@ -27,14 +26,8 @@ export class PollVoteUpdate {
|
|||
/**
|
||||
* Peer who has voted
|
||||
*/
|
||||
get peer(): User | Chat {
|
||||
if (this.raw.peer._ === 'peerUser') {
|
||||
return new User(this._peers.user(this.raw.peer.userId))
|
||||
}
|
||||
|
||||
assertTypeIs('PollVoteUpdate.peer', this.raw.peer, 'peerChannel')
|
||||
|
||||
return new Chat(this._peers.chat(this.raw.peer.channelId))
|
||||
get peer(): Peer {
|
||||
return parsePeer(this.raw.peer, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { tl } from '@mtcute/core'
|
||||
|
||||
import { Chat, PeersIndex, User } from '../../types/peers/index.js'
|
||||
import { parsePeer, Peer, PeersIndex } from '../../types/peers/index.js'
|
||||
import { Story } from '../../types/stories/index.js'
|
||||
import { assertTypeIs, makeInspectable } from '../../utils/index.js'
|
||||
import { memoizeGetters } from '../../utils/memoize.js'
|
||||
|
@ -20,15 +20,8 @@ export class StoryUpdate {
|
|||
/**
|
||||
* Peer that owns these stories.
|
||||
*/
|
||||
get peer(): User | Chat {
|
||||
switch (this.raw.peer._) {
|
||||
case 'peerUser':
|
||||
return new User(this._peers.user(this.raw.peer.userId))
|
||||
case 'peerChat':
|
||||
return new Chat(this._peers.chat(this.raw.peer.chatId))
|
||||
case 'peerChannel':
|
||||
return new Chat(this._peers.chat(this.raw.peer.channelId))
|
||||
}
|
||||
get peer(): Peer {
|
||||
return parsePeer(this.raw.peer, this._peers)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
import {
|
||||
Chat,
|
||||
Message,
|
||||
MtPeerNotFoundError,
|
||||
OmitInputMessageId,
|
||||
ParametersSkip1,
|
||||
TelegramClient,
|
||||
User,
|
||||
} from '@mtcute/client'
|
||||
import { Message, MtPeerNotFoundError, OmitInputMessageId, ParametersSkip1, Peer, TelegramClient } from '@mtcute/client'
|
||||
import { DeleteMessagesParams } from '@mtcute/client/src/methods/messages/delete-messages.js'
|
||||
import { ForwardMessageOptions } from '@mtcute/client/src/methods/messages/forward-messages.js'
|
||||
import { SendCopyParams } from '@mtcute/client/src/methods/messages/send-copy.js'
|
||||
|
@ -53,7 +45,7 @@ export class MessageContext extends Message implements UpdateContext<Message> {
|
|||
*
|
||||
* Learn more: [Incomplete peers](https://mtcute.dev/guide/topics/peers.html#incomplete-peers)
|
||||
*/
|
||||
async getSender(): Promise<User | Chat> {
|
||||
async getCompleteSender(): Promise<Peer> {
|
||||
if (!this.sender.isMin) return this.sender
|
||||
|
||||
let res
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
// ^^ will be looked into in MTQ-29
|
||||
import {
|
||||
_RepliedMessageAssertionsByOrigin,
|
||||
Chat,
|
||||
MaybeArray,
|
||||
Message,
|
||||
MessageAction,
|
||||
MessageMediaType,
|
||||
Peer,
|
||||
RawDocument,
|
||||
RawLocation,
|
||||
RepliedMessageInfo,
|
||||
|
@ -208,7 +208,7 @@ export const action = <T extends Exclude<MessageAction, null>['type']>(
|
|||
action: Extract<MessageAction, { type: T }>
|
||||
sender: T extends 'user_joined_link' | 'user_removed' | 'history_cleared' | 'contact_joined' | 'bot_allowed'
|
||||
? User
|
||||
: User | Chat
|
||||
: Peer
|
||||
}
|
||||
> => {
|
||||
if (Array.isArray(type)) {
|
||||
|
@ -261,7 +261,7 @@ export const withCompleteSender =
|
|||
): UpdateFilter<MessageContext, Mod, State> =>
|
||||
async (msg, state) => {
|
||||
try {
|
||||
await msg.getSender()
|
||||
await msg.getCompleteSender()
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { assertNever, Chat, MaybeAsync, User } from '@mtcute/client'
|
||||
import { assertNever, MaybeAsync, Peer } from '@mtcute/client'
|
||||
|
||||
import { CallbackQueryContext, MessageContext } from '../context/index.js'
|
||||
|
||||
|
@ -10,7 +10,7 @@ import { CallbackQueryContext, MessageContext } from '../context/index.js'
|
|||
* @param msg Message or callback from which to derive the key
|
||||
* @param scene Current scene UID, or `null` if none
|
||||
*/
|
||||
export type StateKeyDelegate = (upd: MessageContext | CallbackQueryContext | User | Chat) => MaybeAsync<string | null>
|
||||
export type StateKeyDelegate = (upd: MessageContext | CallbackQueryContext | Peer) => MaybeAsync<string | null>
|
||||
|
||||
/**
|
||||
* Default state key delegate.
|
||||
|
|
Loading…
Reference in a new issue