feat(client): contacts related methods

This commit is contained in:
teidesu 2021-04-25 17:10:37 +03:00
parent 2fc8a90edf
commit 39236c94c2
6 changed files with 255 additions and 0 deletions

View file

@ -40,6 +40,10 @@ 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 { unarchiveChats } from './methods/chats/unarchive-chats'
import { addContact } from './methods/contacts/add-contact'
import { deleteContacts } from './methods/contacts/delete-contacts'
import { getContacts } from './methods/contacts/get-contacts'
import { importContacts } from './methods/contacts/import-contacts'
import { createFolder } from './methods/dialogs/create-folder'
import { deleteFolder } from './methods/dialogs/delete-folder'
import { editFolder } from './methods/dialogs/edit-folder'
@ -707,6 +711,67 @@ export interface TelegramClient extends BaseTelegramClient {
* @param chats Chat ID(s), username(s), phone number(s), `"me"` or `"self"`
*/
unarchiveChats(chats: MaybeArray<InputPeerLike>): Promise<void>
/**
* Add an existing Telegram user as a contact
*
* @param userId User ID, username or phone number
* @param params Contact details
*/
addContact(
userId: InputPeerLike,
params: {
/**
* First name of the contact
*/
firstName: string
/**
* Last name of the contact
*/
lastName?: string
/**
* Phone number of the contact, if available
*/
phone?: string
/**
* Whether to share your own phone number
* with the newly created contact (defaults to `false`)
*/
sharePhone?: boolean
}
): Promise<User>
/**
* Delete a single contact from your Telegram contacts list
*
* Returns deleted contact's profile or `null` in case
* that user was not in your contacts list
*
* @param userId User ID, username or phone number
*/
deleteContacts(userId: InputPeerLike): Promise<User | null>
/**
* Delete one or more contacts from your Telegram contacts list
*
* Returns deleted contact's profiles. Does not return
* profiles of users that were not in your contacts list
*
* @param userIds User IDs, usernames or phone numbers
*/
deleteContacts(userIds: InputPeerLike[]): Promise<User[]>
/**
* Get list of contacts from your Telegram contacts list.
*/
getContacts(): Promise<User[]>
/**
* Import contacts to your Telegram contacts list.
*
* @param contacts List of contacts
*/
importContacts(
contacts: PartialOnly<Omit<tl.RawInputPhoneContact, '_'>, 'clientId'>[]
): Promise<tl.contacts.RawImportedContacts>
/**
* Create a folder from given parameters
*
@ -1834,6 +1899,10 @@ export class TelegramClient extends BaseTelegramClient {
setChatUsername = setChatUsername
setSlowMode = setSlowMode
unarchiveChats = unarchiveChats
addContact = addContact
deleteContacts = deleteContacts
getContacts = getContacts
importContacts = importContacts
createFolder = createFolder
deleteFolder = deleteFolder
editFolder = editFolder

View file

@ -0,0 +1,61 @@
import { TelegramClient } from '../../client'
import { InputPeerLike, MtCuteInvalidPeerTypeError, MtCuteTypeAssertionError, User } from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl'
/**
* Add an existing Telegram user as a contact
*
* @param userId User ID, username or phone number
* @param params Contact details
* @internal
*/
export async function addContact(
this: TelegramClient,
userId: InputPeerLike,
params: {
/**
* First name of the contact
*/
firstName: string
/**
* Last name of the contact
*/
lastName?: string
/**
* Phone number of the contact, if available
*/
phone?: string
/**
* Whether to share your own phone number
* with the newly created contact (defaults to `false`)
*/
sharePhone?: boolean
}
): Promise<User> {
const peer = normalizeToInputUser(await this.resolvePeer(userId))
if (!peer) throw new MtCuteInvalidPeerTypeError(userId, 'user')
const res = await this.call({
_: 'contacts.addContact',
id: peer,
firstName: params.firstName,
lastName: params.lastName ?? '',
phone: params.phone ?? '',
addPhonePrivacyException: !!params.sharePhone
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'addContact',
'updates | updatesCombined',
res._
)
this._handleUpdate(res)
return new User(this, res.users[0] as tl.RawUser)
}

View file

@ -0,0 +1,76 @@
import { TelegramClient } from '../../client'
import { MaybeArray } from '@mtcute/core'
import { InputPeerLike, MtCuteInvalidPeerTypeError, MtCuteTypeAssertionError, User } from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl'
/**
* Delete a single contact from your Telegram contacts list
*
* Returns deleted contact's profile or `null` in case
* that user was not in your contacts list
*
* @param userId User ID, username or phone number
* @internal
*/
export async function deleteContacts(
this: TelegramClient,
userId: InputPeerLike
): Promise<User | null>
/**
* Delete one or more contacts from your Telegram contacts list
*
* Returns deleted contact's profiles. Does not return
* profiles of users that were not in your contacts list
*
* @param userIds User IDs, usernames or phone numbers
* @internal
*/
export async function deleteContacts(
this: TelegramClient,
userIds: InputPeerLike[]
): Promise<User[]>
/** @internal */
export async function deleteContacts(
this: TelegramClient,
userIds: MaybeArray<InputPeerLike>
): Promise<MaybeArray<User> | null> {
const single = !Array.isArray(userIds)
if (single) userIds = [userIds as InputPeerLike]
const inputPeers = ((
await Promise.all(
(userIds as InputPeerLike[]).map((it) =>
this.resolvePeer(it).then(normalizeToInputUser)
)
)
).filter(Boolean) as unknown) as tl.TypeInputUser[]
if (single && !inputPeers.length)
throw new MtCuteInvalidPeerTypeError(
(userIds as InputPeerLike[])[0],
'user'
)
const res = await this.call({
_: 'contacts.deleteContacts',
id: inputPeers
})
if (!(res._ === 'updates' || res._ === 'updatesCombined'))
throw new MtCuteTypeAssertionError(
'addContact',
'updates | updatesCombined',
res._
)
if (single && !res.updates.length) return null
this._handleUpdate(res)
const users = res.users.map(user => new User(this, user as tl.RawUser))
return single ? users[0] : users
}

View file

@ -0,0 +1,20 @@
import { TelegramClient } from '../../client'
import { User } from '../../types'
import { assertTypeIs } from '../../utils/type-assertion'
import { tl } from '@mtcute/tl'
/**
* Get list of contacts from your Telegram contacts list.
* @internal
*/
export async function getContacts(
this: TelegramClient
): Promise<User[]> {
const res = await this.call({
_: 'contacts.getContacts',
hash: 0
})
assertTypeIs('getContacts', res, 'contacts.contacts')
return res.users.map((user) => new User(this, user as tl.RawUser))
}

View file

@ -0,0 +1,28 @@
import { TelegramClient } from '../../client'
import { tl } from '@mtcute/tl'
import { PartialOnly } from '@mtcute/core'
import bigInt from 'big-integer'
/**
* Import contacts to your Telegram contacts list.
*
* @param contacts List of contacts
* @internal
*/
export async function importContacts(
this: TelegramClient,
contacts: PartialOnly<Omit<tl.RawInputPhoneContact, '_'>, 'clientId'>[]
): Promise<tl.contacts.RawImportedContacts> {
let seq = bigInt.zero
const contactsNorm: tl.RawInputPhoneContact[] = contacts.map((input) => ({
_: 'inputPhoneContact',
clientId: (seq = seq.plus(1)),
...input,
}))
return await this.call({
_: 'contacts.importContacts',
contacts: contactsNorm,
})
}

View file

@ -1,5 +1,6 @@
export type MaybeAsync<T> = T | Promise<T>
export type PartialExcept<T, K extends keyof T> = Partial<Omit<T, K>> &
Pick<T, K>
export type PartialOnly<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>
export type MaybeArray<T> = T | T[]