nitreojs / puregram

powerful and modern telegram bot api sdk for node.js and typescript 😁
https://puregram.cool
Do What The F*ck You Want To Public License
188 stars 10 forks source link

ForwardedMessage is undefined #84

Closed culda closed 11 months ago

culda commented 11 months ago

The bug

message.forwardedMessage.chat resolve to undefined

Steps to reproduce

Steps to reproduce the behavior:

  1. Forward a msg to my bot
  2. try to fetch the forwarded message with console.log("fwc", update.message.forwardedMessage?.chat);
  3. result is undefined

Expected behavior

Expect forwardedMessage?.chat to resolve to { id: -1001997091997, title: 'tgdaddytest', type: 'channel' }

Screenshots

Update message contains forward_from_chat, but fwc is undefined

image

Environment

package 2.20.1
puregram X.Y.Z
node X.Y.Z
TypeScript X.Y.Z
yarn or npm X.Y.Z

Additional context

Add any other context about the problem here.

The code runs inside AWS lambda

nitreojs commented 11 months ago

what context exactly is this? according to your report, update.message is used. what exactly is update? do you handle updates by your side?

culda commented 11 months ago

I'm using a webhook into my aws lambda via api gateway. update comes from event.body from the API gw http request and it works fine. Also update.message looks good

nitreojs commented 11 months ago

I'm using a webhook

are you using telegram.updates.handleUpdate(update)? or do you process each update manually? if you do, there's nothing unexpected that happens. the forwardedMessage field appears only when updates were processed by puregram itself: forwardedMessage is, in fact, a getter of MessageContext

nitreojs commented 11 months ago

or do you just use the webhook as shown in examples/webhook?

culda commented 11 months ago

I am processing manually the update as http request data because I'm using a serverless approach. Puregram isn't running anywhere. Can I parse the incoming data as if it was puregram processing it?

culda commented 11 months ago

this is the full code btw

import { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { Keyboard, Telegram, Update } from "puregram";
import { LinkChannelText } from "./utils";

const telegram = Telegram.fromToken(
  "..."
);

export const handler: APIGatewayProxyHandlerV2 = async (event) => {
  try {
    const update: Update = JSON.parse(event.body as string);
    await handleUpdate(update);
  } catch (err) {
    console.log(err);
  } finally {
    return {
      statusCode: 200,
    };
  }
};

async function handleUpdate(update: Update) {
  console.log(update);
  if (update.message) {
    const { message } = update;
    const { text, chat, forwardedMessage } = message;
    if (text === "/start") {
      await telegram.api.sendMessage({
        chat_id: chat.id,
        text: "Welcome to TG Daddy!",
        parse_mode: "Markdown",
        reply_markup: Keyboard.keyboard([
          [Keyboard.textButton(LinkChannelText)],
        ]),
      });
    }

    if (text === LinkChannelText) {
      console.log("Link Channel");
      await telegram.api.sendMessage({
        chat_id: chat.id,
        text: "Please forward a message from your channel",
        parse_mode: "Markdown",
        reply_markup: Keyboard.keyboard([[Keyboard.textButton("Cancel")]]),
      });
    }

    if (forwardedMessage?.chat) {
      console.log("hi");
      await telegram.api.sendMessage({
        chat_id: chat.id,
        text: `Received ${forwardedMessage}`,
        parse_mode: "Markdown",
      });
    }
  }
}
nitreojs commented 11 months ago

Can I parse the incoming data as if it was puregram processing it?

sure, you can just use telegram.updates.handleUpdate(update) and it will return a Context (if puregram knows how to process it, of course):

// i'm using `getUpdates` just to make things easier for me to test out
const updates = await telegram.api.getUpdates()

for (const update of updates) {
  const context = await telegram.updates.handleUpdate(update)

  console.log(context)
}
culda commented 11 months ago

Thanks, the update from the context has all the expected TS props

const context = await telegram.updates.handleUpdate(update)
conts upd = context.update
nitreojs commented 11 months ago
const upd = context.update

no, you don't need to use context.update, you can just use context.forwardedMessage and all its fields... but you do you, i guess

culda commented 11 months ago

I can see forwardMessage when I log the context object. However context.forwardMessage is not valid TS, so maybe there's a typedef issue?

nitreojs commented 11 months ago

forwardMessage is deprecated, use forwardedMessage

culda commented 11 months ago

My context object only has this on it. image

nitreojs commented 11 months ago

yeah, everything is OK: telegram.updates.handleUpdate(...) returns Context since there is no real way to return the actual context type. Context is the general context type behind all others. if you need MessageContext's methods and getters, consider calling context.is('message'):

const context = await telegram.updates.handleUpdate(update)
// context: Context, general type

if (context.is('message')) {
  // context: MessageContext
  const fwd = context.forwardedMessage
  // ...
}
culda commented 11 months ago

Got it now, thanks!