gram-js / gramjs

NodeJS/Browser MTProto API Telegram client library,
MIT License
1.25k stars 178 forks source link

Client not starting on Docker containerization #637

Open francestu96 opened 7 months ago

francestu96 commented 7 months ago

I have this simple code:

const client = new TelegramClient(new StoreSession("my_session"), parseInt(process.env.API_ID), process.env.API_HASH, {
    connectionRetries: 5,
});

(async () => {
    await client.start({
        phoneNumber: async () => await input.text("Please enter your number: "),
        password: async () => await input.text("Please enter your password: "),
        phoneCode: async () => await input.text("Please enter the code you received: "),
        onError: (err) => console.log(err),
    });

    console.log("You should now be connected.");

    await client.sendMessage("me", { message: "test" });
    console.log("Sent to me.");
})()

It perfectly works without containerization. I want to create a Docker container with this code but it looks like it stucks on client.start function. This is the container log:

2024-02-08 17:42:34 [2024-02-08T16:42:34.106] [INFO] - [Running gramJS version 2.19.9]
2024-02-08 17:42:34 [2024-02-08T16:42:34.119] [INFO] - [Connecting to 91.108.56.132:80/TCPFull...]
2024-02-08 17:42:34 [2024-02-08T16:42:34.125] [INFO] - [Connection to 91.108.56.132:80/TCPFull complete!]
2024-02-08 17:42:34 [2024-02-08T16:42:34.134] [INFO] - [Using LAYER 166 for initial connect] 

It doesn't even print "You should now be connected". I took care of copying into the image also "my_session" in order to avoid the need to login again.

This is the Dockerfile:

FROM node:18-alpine

WORKDIR /telegrambot

COPY ./bot.js ./package.json .
COPY ./my_session ./my_session

RUN npm install

CMD [ "node", "bot.js" ]

What does it could be the problem?

Thank you in advance!

Inbell1s commented 6 months ago

Having the exact same issue here.

Node Version v20.11.0 Docker Version 24.0.7

alvvaysxxx commented 5 months ago

i suppose that may be because of deprecated input(). You can try fixing it manually

francestu96 commented 5 months ago

Still not working even with readline... Moreover, the input() is not supposed to be called since I copied the session and it doesn't need to call it

francestu96 commented 5 months ago

I even tried with a StringSession and used it to connect. Than called await client.start() without any parameters and it successfully connect, yet no way to proceed nor to add a listener for new messages... same output of before

Is it possible it is some Docker port mapping problem? This is getting me crazy

polRk commented 4 months ago

I have the same issue. I do not use any readline or something, because i send session from file directly, and call client.connect()

PeterVoronov commented 4 months ago

Did you tried to run the docker image in interactive mode? I.e.

docker run -it image_name
polRk commented 3 months ago

error: Not connected at /home/bun/app/node_modules/telegram/network/connection/Connection.js:71:15

coderFaiisal commented 3 months ago

@francestu96 I have the same problem. Have you found any solutions to this issue?

PeterVoronov commented 3 months ago

I have no problems at all with run in docker. Did you pass an API_ID nd API_HASH to docker? docker run -e API_ID='something' -e API_HASH='something' ... ?

coderFaiisal commented 3 months ago

@PeterVoronov Could you please elaborate on this? Also, which version of gramjs are you using?

Here is logs error: WhatsApp Image 2024-06-21 at 8 22 06 PM (1)

I've been trying to connect to Telegram using the Gramjs TelegramClient in a worker thread. The worker hangs up to await client.connect() and after retries, it throws a connection error.

`import { Api, TelegramClient } from "telegram"; import accounts from "./accounts"; import redisClient from "./redis"; import { Worker } from "bullmq";

(async function init() { accounts.forEach((account, index) => { new Worker( message-queue-${index}, async (job) => { const { recipient, message } = job.data;

    console.log(`Processing job for recipient: ${recipient}`);

    const client = new TelegramClient(
      account.stringSession,
      account.apiId,
      account.apiHash,
      {
        connectionRetries: 5
      }
    );

    try {
      console.log("Connecting telegram client...");
      await client.connect();
      console.log("Telegram client connected...");

      await client.invoke(
        new Api.messages.SendMessage({
          peer: recipient,
          message: message,
          randomId: BigInt(`${Date.now()}`) as any,
          noWebpage: true,
          noforwards: true,
        })
      );

      console.log("Message sent...");
    } catch (error) {
      console.log("Failed to send message:", error);
    } finally {
      await client.disconnect();
      console.log("Telegram client disconnected...");
    }

    console.log(`Message sent...`);
  },
  {
    limiter: {
      max: 1,
      duration: 10000,
    },
    connection: redisClient,
  }
);

}); })();`

The application has been dockerized. Here is the docker-compose.yml.

docker-compose

DockerFile

Dockerfile

Finally, caddyfile for reverse proxy

Caddy

@PeterVoronov Any ideas?

Some observations:

I have checked the Docker network, and the containers are all connected, and I could ping Redis and Caddy from within the telegram. The Bullmq worker is also working fine.

PeterVoronov commented 3 months ago

@PeterVoronov Could you please elaborate on this? Also, which version of gramjs are you using?

There is only one idea - I use after creation a client not a client.connect but cient.start. And for message sending i prefer to use clientsendMessage(peerId, messageParams)... P.S. And I can reommend to not reconnect each time, when do you receive a message. I,e, put client.start outside a workers.

hamakh11 commented 1 month ago

same issue here, any solution guys?

` await this.client.start({ phoneNumber: tgConfig.phoneNumber, password: async () => tgConfig.password, phoneCode: async () => await input.text("Please enter the code you received: "), onError: (err) => console.log(err.name + "stack error"), forceSMS: false, });

    console.log("telegram connected.");`

in local its connecting fine and all working but in docker environment it gives this output stucks here for a while and then crushed the docker program.

2024-02-08 17:42:34 [2024-02-08T16:42:34.106] [INFO] - [Running gramJS version 2.19.9]
2024-02-08 17:42:34 [2024-02-08T16:42:34.119] [INFO] - [Connecting to 91.108.56.132:80/TCPFull...]
2024-02-08 17:42:34 [2024-02-08T16:42:34.125] [INFO] - [Connection to 91.108.56.132:80/TCPFull complete!]
2024-02-08 17:42:34 [2024-02-08T16:42:34.134] [INFO] - [Using LAYER 166 for initial connect] 
PeterVoronov commented 1 month ago

As I said for me is the solution to make a first run of the docker in interactive mode:

docker run -it image_name -v docker_path:external_path -e ENV_VAR='somethin' comman_to_run_app

If you don't use the volume mapping inside the container - you can sipt -v docker_path:external_path, the same - for environment variables... Most important thing is the comman_to_run_app, which has to be equal to CMD comman_to_run_app from Dockerfile. I.e. if in docker file it is CMD npm run start, and no any volumes and environments, please try for the first run next command:

docker run -it image_name npm run start
hamakh11 commented 1 month ago

I tried the command you provided, which by running -it you can interact with the running image. and I guess this might fix the issues with having (input) to enter phone and password.

majority of people here have the telegram session already setup and they don't need input. the input is not the issue, there is something else. thanks,

coderFaiisal commented 1 month ago

@hamakh11 I recently encountered and resolved an issue with the Telegram client connection in a Docker environment, and I wanted to share my solution to help others who might face the same problem.

Problem When using the Telegram client in a Docker environment, I noticed that creating a new connection each time an API endpoint was hit caused the client to freeze or block. This happens because Telegram only allows one connection request per session. If multiple connections are attempted from the same account, it leads to issues, especially when handling multiple API requests. as Telegram authentication tokens (stringSession) do not expire on their own. They remain valid indefinitely unless one of the following conditions occurs:

  1. Account Deletion: The token becomes invalid if the associated Telegram account is deleted.
  2. Manual Logout: The token expires if the user logs out from the session.
  3. Inactivity: If the session is not used for 6 months, it will expire based on Telegram's inactivity policy.

Solution The key to solving this problem is to create the Telegram client connection only once and keep it persistent, similar to how you would handle a database connection. What you should have to do is generate a sessionString, store this string as a credential, and then use this sessionString, apiHash, and apiId as credentials to connect to the client. Here’s a detailed explanation:

Instead of creating a new Telegram client connection for each API request, establish the connection once the server starts. Maintain this connection for all subsequent operations. This prevents multiple connection attempts and ensures smooth communication with the Telegram API.

hamakh11 commented 1 month ago

thanks for your explanation,

I will try this, because every time that I wanted to connect to the telegram client I used the same session key that was generated on my local. I will try to generate the token on the docker client and then persist it.

hamakh11 commented 1 month ago

I didn't know what is the problem. but using the same docker image in ubuntu 22.4 worked fine with no problems I can connect to telegram, but on windows docker I coudln't get it to work.