Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-connectiong an authorized user with string session does not work #665

Open
Natansal1 opened this issue Apr 16, 2024 · 0 comments
Open

Comments

@Natansal1
Copy link

Natansal1 commented Apr 16, 2024

Hi, I am encountering a bug When I try to create a new TelegramClient with a new StringSession from a stored value (saved in my DB from the session.save() method).
The bug I'm getting is that the client.isUserAuthorized method returns false even if the user was connected a minute ago (before I restarted the server). Am I missing something?

type ConnectedClient = {
  client: TelegramClient;
  session: StringSession;
  userId: string;
};

@Injectable()
export class TelegramAuthService {
  apiId = parseInt(process.env.TELEGRAM_API_ID);
  apiHash = process.env.TELEGRAM_API_HASH;

  connectedClients: ConnectedClient[] = [];

  constructor(
    @InjectModel(Telegram.name) private readonly TelegramModel: Model<Telegram>,
    @InjectModel(Crisis.name) private readonly crisisModel: Model<Crisis>,
    private readonly volunteerService: VolunteerService
  ) {}

// The function that should return a client and session
  private async getClient(userId: string, userKey: string = "") {
    const connectedClient = this.connectedClients.find((v) => v.userId === userId);
    if (connectedClient) {
      if (!connectedClient.client.connected) await connectedClient.client.connect();
      return connectedClient;
    }

    const session = new StringSession(userKey);
    const client = new TelegramClient(session, this.apiId, this.apiHash, {});

    await client.connect();

    const newClient: ConnectedClient = {
      client,
      session,
      userId,
    };

    this.connectedClients.push(newClient);

    return newClient;
  }

//Returns the stored session if exists to null otherwise
  async getUserKey(userId: string): Promise<string | null> {
    const userKey: string | null = await this.volunteerService.getVolTelegramKeyById(userId);
    return userKey;
  }

  async sendTelegramCode(userId: string) {
    const { client } = await this.getClient(userId);

    const phoneNumber = await this.getSignedPhoneNumberById(userId);

    try {
      const sentCode = await client.sendCode(
        {
          apiHash: this.apiHash,
          apiId: this.apiId,
        },
        phoneNumber
      );

      console.log("Code sent successfully:", sentCode);

      return {
        success: true,
      };
    } catch (error) {
      return {
        success: false,
        seconds: error.seconds,
      };
    }
  }

  async connectWithKey(config: {
    userId: string;
    key: string;
  }) {
    const { key: userKey, userId } = config;
    if (!userKey) throw new BadRequestException("User has no telegram key");

    console.log(userKey); // print a 350+ length string that is stored in the DB

    const { client } = await this.getClient(userId, userKey);

    const authorized = await client.isUserAuthorized();  //always comes as false

    if (!authorized) throw new BadRequestException("User is not authorized"); 

    return {
      success: true,
    };
  }

  async connectWithCode(config: {
    userId: string;
    code: string;
  }) {
    const { code, userId } = config;

    const phoneNumber = await this.getSignedPhoneNumberById(userId);

    try {
      const { client, session } = await this.getClient(userId);

      await client.signInUser(
        {
          apiHash: this.apiHash,
          apiId: this.apiId,
        },
        {
          phoneCode: async () => code,
          phoneNumber: phoneNumber,
          onError: async (e) => (console.log(e), true),
        }
      );

      const userKey = session.save();

      await this.volunteerService.storeVolTelegramKey(userId, userKey);

    } catch (e) {
      console.error(e);
      if (e && typeof e === "object" && e.code === 420) {
        throw new UnauthorizedException(
          {
            seconds: e.seconds,
            message: `User is banned for ${e.errorMessage}`,
          },
          `User is banned for ${e.errorMessage}`
        );
      } else if (e instanceof Error && e.message === "AUTH_USER_CANCEL") {
        throw new UnauthorizedException("Wrong Code");
      } else {
        console.log("error inside catch", e);
        throw e;
      }
    }
  }

  //Utils:

  private async getSignedPhoneNumberById(userId: string) {
    const number = await this.volunteerService.getPhoneNumber(userId);
    return this.toSignedPhoneNumber(number);
  }

  private toSignedPhoneNumber(phoneNumber: string) {
    phoneNumber = phoneNumber.trim();
    if (phoneNumber.startsWith("0")) return "+972" + phoneNumber.slice(1);
    if (phoneNumber.startsWith("972")) return "+" + phoneNumber;

    return phoneNumber;
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant