1
0
Эх сурвалжийг харах

feat: pinMessage and unpinMessage convenience methods

- Add client.pinMessage and client.unpinMessage methods
- Add Message.pin and Message.unpin
- Add docs for all pin and unpin methods
Man Nguyen 3 жил өмнө
parent
commit
bc117e3668

+ 66 - 0
gramjs/client/TelegramClient.ts

@@ -776,6 +776,72 @@ export class TelegramClient extends TelegramBaseClient {
         });
     }
 
+    /**
+     * Pins a message in a chat.
+     *
+     * See also {@link Message.pin}`.
+     *
+     * @remarks The default behavior is to **not** notify members, unlike the official applications.
+     * @param entity - The chat where the message should be pinned.
+     * @param message - The message or the message ID to pin. If it's `undefined`, all messages will be unpinned instead.
+     * @param pinMessageParams - see {@link UpdatePinMessageParams}.
+     * @return
+     * The pinned message. if message is undefined the return will be {@link AffectedHistory}
+     * @example
+     *  ```ts
+     *  const message = await client.sendMessage(chat, 'GramJS is awesome!');
+     *
+     *  await client.pinMessage(chat, message);
+     *  ```
+     */
+    pinMessage(
+        entity: EntityLike,
+        message?: MessageIDLike,
+        pinMessageParams?: messageMethods.UpdatePinMessageParams
+    ) {
+        return messageMethods.pinMessage(
+            this,
+            entity,
+            message,
+            pinMessageParams
+        );
+    }
+
+    /**
+     * Unpins a message in a chat.
+     *
+     * See also {@link Message.unpin}`.
+     *
+     * @remarks The default behavior is to **not** notify members, unlike the official applications.
+     * @param entity - The chat where the message should be pinned.
+     * @param message - The message or the message ID to pin. If it's `undefined`, all messages will be unpinned instead.
+     * @param pinMessageParams - see {@link UpdatePinMessageParams}.
+     * @return
+     * The pinned message. if message is undefined the return will be {@link AffectedHistory}
+     * @example
+     *  ```ts
+     *  const message = await client.sendMessage(chat, 'GramJS is awesome!');
+     *
+     *  // unpin one message
+     *  await client.unpinMessage(chat, message);
+     *
+     *  // unpin all messages
+     *  await client.unpinMessage(chat)
+     *  ```
+     */
+    unpinMessage(
+        entity: EntityLike,
+        message?: MessageIDLike,
+        unpinMessageParams?: messageMethods.UpdatePinMessageParams
+    ) {
+        return messageMethods.unpinMessage(
+            this,
+            entity,
+            message,
+            unpinMessageParams
+        );
+    }
+
     //endregion
     //region dialogs
 

+ 96 - 1
gramjs/client/messages.ts

@@ -571,6 +571,18 @@ export interface EditMessageParams {
     schedule?: DateLike;
 }
 
+/** Interface for editing messages */
+export interface UpdatePinMessageParams {
+    /** Whether the pin should notify people or not. <br />
+     *  By default it has the opposite behavior of official clients, it will not notify members.
+     */
+    notify?: boolean;
+    /** Whether the message should be pinned for everyone or not. <br />
+     *  By default it has the opposite behavior of official clients, and it will pin the message for both sides, in private chats.
+     */
+    pmOneSide?: boolean;
+}
+
 /** @hidden */
 export function iterMessages(
     client: TelegramClient,
@@ -887,7 +899,7 @@ export async function editMessage(
         inputMedia = media;
     }
     if (message instanceof Api.Message) {
-        id = utils.getMessageId(message);
+        id = getMessageId(message);
         text = message.message;
         entities = message.entities;
         if (buttons == undefined) {
@@ -984,4 +996,87 @@ export async function deleteMessages(
     return Promise.all(results);
 }
 
+/** @hidden */
+export async function pinMessage(
+    client: TelegramClient,
+    entity: EntityLike,
+    message?: MessageIDLike,
+    pinMessageParams?: UpdatePinMessageParams
+) {
+    return await _pin(
+        client,
+        entity,
+        message,
+        false,
+        pinMessageParams?.notify,
+        pinMessageParams?.pmOneSide
+    );
+}
+
+/** @hidden */
+export async function unpinMessage(
+    client: TelegramClient,
+    entity: EntityLike,
+    message?: MessageIDLike,
+    unpinMessageParams?: UpdatePinMessageParams
+) {
+    return await _pin(
+        client,
+        entity,
+        message,
+        true,
+        unpinMessageParams?.notify,
+        unpinMessageParams?.pmOneSide
+    );
+}
+
+/** @hidden */
+export async function _pin(
+    client: TelegramClient,
+    entity: EntityLike,
+    message: MessageIDLike | undefined,
+    unpin: boolean,
+    notify: boolean = false,
+    pmOneSide: boolean = false
+) {
+    message = utils.getMessageId(message) || 0;
+    entity = await client.getInputEntity(entity);
+    let request:
+        | Api.messages.UnpinAllMessages
+        | Api.messages.UpdatePinnedMessage;
+
+    if (message === 0) {
+        request = new Api.messages.UnpinAllMessages({
+            peer: entity,
+        });
+        return await client.invoke(request);
+    }
+
+    request = new Api.messages.UpdatePinnedMessage({
+        silent: !notify,
+        unpin,
+        pmOneside: pmOneSide,
+        peer: entity,
+        id: message,
+    });
+    const result = await client.invoke(request);
+
+    /**
+     * Unpinning does not produce a service message.
+     * Pinning a message that was already pinned also produces no service message.
+     * Pinning a message in your own chat does not produce a service message,
+     * but pinning on a private conversation with someone else does.
+     */
+    if (
+        unpin ||
+        !("updates" in result) ||
+        ("updates" in result && !result.updates)
+    ) {
+        return;
+    }
+
+    // Pinning a message that doesn't exist would RPC-error earlier
+    return client._getResponseMessage(request, result, entity) as Api.Message;
+}
+
 // TODO do the rest

+ 29 - 1
gramjs/tl/custom/message.ts

@@ -6,7 +6,11 @@ import { ChatGetter } from "./chatGetter";
 import * as utils from "../../Utils";
 import { Forward } from "./forward";
 import type { File } from "./file";
-import { EditMessageParams, SendMessageParams } from "../../client/messages";
+import {
+    EditMessageParams,
+    SendMessageParams,
+    UpdatePinMessageParams,
+} from "../../client/messages";
 import { DownloadMediaInterface } from "../../client/downloads";
 import { inspect } from "util";
 import { betterConsoleLog, returnBigInt } from "../../Helpers";
@@ -816,6 +820,30 @@ export class CustomMessage extends SenderGetter {
         }
     }
 
+    async pin(params?: UpdatePinMessageParams) {
+        if (this._client) {
+            const entity = await this.getInputChat();
+            if (entity === undefined) {
+                throw Error(
+                    "Failed to pin message due to cannot get input chat."
+                );
+            }
+            return this._client.pinMessage(entity, this.id, params);
+        }
+    }
+
+    async unpin(params?: UpdatePinMessageParams) {
+        if (this._client) {
+            const entity = await this.getInputChat();
+            if (entity === undefined) {
+                throw Error(
+                    "Failed to unpin message due to cannot get input chat."
+                );
+            }
+            return this._client.unpinMessage(entity, this.id, params);
+        }
+    }
+
     async downloadMedia(params: DownloadMediaInterface) {
         // small hack for patched method
         if (this._client)