diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index 6272d592..3ae63f95 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -66,6 +66,7 @@ import { joinChat } from './methods/chats/join-chat' import { kickChatMember } from './methods/chats/kick-chat-member' import { leaveChat } from './methods/chats/leave-chat' import { markChatUnread } from './methods/chats/mark-chat-unread' +import { reorderUsernames } from './methods/chats/reorder-usernames' import { restrictChatMember } from './methods/chats/restrict-chat-member' import { saveDraft } from './methods/chats/save-draft' import { setChatDefaultPermissions } from './methods/chats/set-chat-default-permissions' @@ -74,6 +75,7 @@ import { setChatPhoto } from './methods/chats/set-chat-photo' import { setChatTitle } from './methods/chats/set-chat-title' import { setChatUsername } from './methods/chats/set-chat-username' import { setSlowMode } from './methods/chats/set-slow-mode' +import { toggleFragmentUsername } from './methods/chats/toggle-fragment-username' import { toggleJoinRequests } from './methods/chats/toggle-join-requests' import { toggleJoinToSend } from './methods/chats/toggle-join-to-send' import { unarchiveChats } from './methods/chats/unarchive-chats' @@ -208,9 +210,9 @@ import { resolvePeer } from './methods/users/resolve-peer' import { resolvePeerMany } from './methods/users/resolve-peer-many' import { setOffline } from './methods/users/set-offline' import { setProfilePhoto } from './methods/users/set-profile-photo' +import { setUsername } from './methods/users/set-username' import { unblockUser } from './methods/users/unblock-user' import { updateProfile } from './methods/users/update-profile' -import { updateUsername } from './methods/users/update-username' import { ArrayPaginated, ArrayWithTotal, @@ -1419,6 +1421,12 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId Chat ID */ markChatUnread(chatId: InputPeerLike): Promise + /** + * Reorder usernames + * + * @param peerId Bot, channel or "me"/"self" + */ + reorderUsernames(peerId: InputPeerLike, order: string[]): Promise /** * Restrict a user in a supergroup. * @@ -1520,6 +1528,28 @@ export interface TelegramClient extends BaseTelegramClient { * Valid values are: `0 (off), 10, 30, 60 (1m), 300 (5m), 900 (15m) or 3600 (1h)` */ setSlowMode(chatId: InputPeerLike, seconds?: number): Promise + /** + * Toggle a collectible (Fragment) username + * + * > **Note**: non-collectible usernames must still be changed + * > using {@link setUsername}/{@link setChatUsername} + * + * @param peerId Bot, channel or "me"/"self" + */ + toggleFragmentUsername( + peerId: InputPeerLike, + params: { + /** + * Username to toggle + */ + username: string + + /** + * Whether to enable or disable the username + */ + active: boolean + }, + ): Promise /** * Set whether a channel/supergroup has join requests enabled. * @@ -4241,6 +4271,15 @@ export interface TelegramClient extends BaseTelegramClient { media: InputFileLike | tl.TypeInputPhoto, previewSec?: number, ): Promise + /** + * Change username of the current user. + * + * Note that bots usernames must be changed through + * bot support or re-created from scratch. + * + * @param username New username (5-32 chars, allowed chars: `a-zA-Z0-9_`), or `null` to remove + */ + setUsername(username: string | null): Promise /** * Unblock a user * @@ -4270,15 +4309,6 @@ export interface TelegramClient extends BaseTelegramClient { */ bio?: string }): Promise - /** - * Change username of the current user. - * - * Note that bots usernames must be changed through - * bot support or re-created from scratch. - * - * @param username New username (5-32 chars, allowed chars: `a-zA-Z0-9_`), or `null` to remove - */ - updateUsername(username: string | null): Promise } export class TelegramClient extends BaseTelegramClient { @@ -4403,6 +4433,7 @@ export class TelegramClient extends BaseTelegramClient { kickChatMember = kickChatMember leaveChat = leaveChat markChatUnread = markChatUnread + reorderUsernames = reorderUsernames restrictChatMember = restrictChatMember saveDraft = saveDraft setChatDefaultPermissions = setChatDefaultPermissions @@ -4411,6 +4442,7 @@ export class TelegramClient extends BaseTelegramClient { setChatTitle = setChatTitle setChatUsername = setChatUsername setSlowMode = setSlowMode + toggleFragmentUsername = toggleFragmentUsername toggleJoinRequests = toggleJoinRequests toggleJoinToSend = toggleJoinToSend unarchiveChats = unarchiveChats @@ -4546,7 +4578,7 @@ export class TelegramClient extends BaseTelegramClient { resolvePeer = resolvePeer setOffline = setOffline setProfilePhoto = setProfilePhoto + setUsername = setUsername unblockUser = unblockUser updateProfile = updateProfile - updateUsername = updateUsername } diff --git a/packages/client/src/methods/chats/reorder-usernames.ts b/packages/client/src/methods/chats/reorder-usernames.ts new file mode 100644 index 00000000..5531b07a --- /dev/null +++ b/packages/client/src/methods/chats/reorder-usernames.ts @@ -0,0 +1,40 @@ +import { TelegramClient } from '../../client' +import { InputPeerLike } from '../../types' +import { isInputPeerChannel, isInputPeerUser, normalizeToInputChannel, normalizeToInputUser } from '../../utils' + +/** + * Reorder usernames + * + * @param peerId Bot, channel or "me"/"self" + * @internal + */ +export async function reorderUsernames(this: TelegramClient, peerId: InputPeerLike, order: string[]): Promise { + const peer = await this.resolvePeer(peerId) + + if (isInputPeerUser(peer)) { + // either a bot or self + + if (peer._ === 'inputPeerSelf' || peer.userId === this._userId) { + // self + await this.call({ + _: 'account.reorderUsernames', + order, + }) + + return + } + + // bot + await this.call({ + _: 'bots.reorderUsernames', + bot: normalizeToInputUser(peer, peerId), + order, + }) + } else if (isInputPeerChannel(peer)) { + await this.call({ + _: 'channels.reorderUsernames', + channel: normalizeToInputChannel(peer, peerId), + order, + }) + } +} diff --git a/packages/client/src/methods/chats/toggle-fragment-username.ts b/packages/client/src/methods/chats/toggle-fragment-username.ts new file mode 100644 index 00000000..a0296ec5 --- /dev/null +++ b/packages/client/src/methods/chats/toggle-fragment-username.ts @@ -0,0 +1,62 @@ +import { TelegramClient } from '../../client' +import { InputPeerLike } from '../../types' +import { isInputPeerChannel, isInputPeerUser, normalizeToInputChannel, normalizeToInputUser } from '../../utils' + +/** + * Toggle a collectible (Fragment) username + * + * > **Note**: non-collectible usernames must still be changed + * > using {@link setUsername}/{@link setChatUsername} + * + * @param peerId Bot, channel or "me"/"self" + * @internal + */ +export async function toggleFragmentUsername( + this: TelegramClient, + peerId: InputPeerLike, + params: { + /** + * Username to toggle + */ + username: string + + /** + * Whether to enable or disable the username + */ + active: boolean + }, +): Promise { + const { username, active } = params + + const peer = await this.resolvePeer(peerId) + + if (isInputPeerUser(peer)) { + // either a bot or self + + if (peer._ === 'inputPeerSelf' || peer.userId === this._userId) { + // self + await this.call({ + _: 'account.toggleUsername', + username, + active, + }) + + return + } + + // bot + await this.call({ + _: 'bots.toggleUsername', + bot: normalizeToInputUser(peer, peerId), + username, + active, + }) + } else if (isInputPeerChannel(peer)) { + await this.call({ + _: 'channels.toggleUsername', + channel: normalizeToInputChannel(peer, peerId), + username, + active, + }) + } +} diff --git a/packages/client/src/methods/users/update-username.ts b/packages/client/src/methods/users/set-username.ts similarity index 84% rename from packages/client/src/methods/users/update-username.ts rename to packages/client/src/methods/users/set-username.ts index 6202ab4b..dbb8f559 100644 --- a/packages/client/src/methods/users/update-username.ts +++ b/packages/client/src/methods/users/set-username.ts @@ -10,7 +10,7 @@ import { User } from '../../types' * @param username New username (5-32 chars, allowed chars: `a-zA-Z0-9_`), or `null` to remove * @internal */ -export async function updateUsername(this: TelegramClient, username: string | null): Promise { +export async function setUsername(this: TelegramClient, username: string | null): Promise { if (username === null) username = '' const res = await this.call({ diff --git a/packages/client/src/types/peers/chat.ts b/packages/client/src/types/peers/chat.ts index 3cefd20e..42fad580 100644 --- a/packages/client/src/types/peers/chat.ts +++ b/packages/client/src/types/peers/chat.ts @@ -223,7 +223,21 @@ export class Chat { * Username, for private chats, bots, supergroups and channels if available */ get username(): string | null { - return 'username' in this.peer ? this.peer.username ?? null : null + if (!('username' in this.peer)) return null + + return this.peer.username ?? this.peer.usernames?.[0].username ?? null + } + + /** + * Usernames (inclufing collectibles), for private chats, bots, supergroups and channels if available + */ + get usernames(): ReadonlyArray | null { + if (!('usernames' in this.peer)) return null + + return ( + this.peer.usernames ?? + (this.peer.username ? [{ _: 'username', username: this.peer.username, active: true }] : null) + ) } /** diff --git a/packages/client/src/types/peers/user.ts b/packages/client/src/types/peers/user.ts index e47157a1..4b0c1eeb 100644 --- a/packages/client/src/types/peers/user.ts +++ b/packages/client/src/types/peers/user.ts @@ -197,7 +197,15 @@ export class User { /** User's or bot's username */ get username(): string | null { - return this.raw.username ?? null + return this.raw.username ?? this.raw.usernames?.[0].username ?? null + } + + /** User's or bot's usernames (including collectibles) */ + get usernames(): ReadonlyArray | null { + return ( + this.raw.usernames ?? + (this.raw.username ? [{ _: 'username', username: this.raw.username, active: true }] : null) + ) } /** IETF language tag of the user's language */