feat(session_string_generator): implement QR code and phone number login methods for Telegram session generation

This commit is contained in:
Daniil Isakov 2026-02-28 04:14:22 +03:00
parent 021298dae5
commit fa11aaaf88

View file

@ -19,26 +19,89 @@ parameters support integer IDs, string representations of IDs (e.g., "123456"),
and usernames (e.g., "@mychannel"). and usernames (e.g., "@mychannel").
""" """
import asyncio
import io
import os import os
from telethon.sync import TelegramClient
from telethon.sessions import StringSession
from dotenv import load_dotenv
import sys import sys
# Load environment variables from .env file from dotenv import load_dotenv
from telethon import errors
from telethon.sessions import StringSession
from telethon.sync import TelegramClient
load_dotenv() load_dotenv()
def _qr_login(client: TelegramClient) -> None:
import qrcode
qr = client.qr_login()
print("\n----- QR Code Login -----\n")
qr_obj = qrcode.QRCode(border=1)
qr_obj.add_data(qr.url)
qr_obj.make(fit=True)
f = io.StringIO()
qr_obj.print_ascii(out=f, invert=True)
print(f.getvalue())
print("Scan the QR code above with your Telegram app:")
print(" Open Telegram > Settings > Devices > Link Desktop Device\n")
print(f"Or open this link on a device where you're logged in:\n {qr.url}\n")
print(f"Expires at: {qr.expires.strftime('%H:%M:%S')}")
print("Waiting for you to scan...")
try:
client.loop.run_until_complete(qr.wait(timeout=120))
except asyncio.TimeoutError:
print("\nQR code expired. Please try again.")
client.disconnect()
sys.exit(1)
except errors.SessionPasswordNeededError:
pw = input("\nTwo-factor authentication enabled. Please enter your password: ")
client.sign_in(password=pw)
def _phone_login(client: TelegramClient) -> None:
phone = input("Please enter your phone (or bot token): ")
try:
client.send_code_request(phone)
except errors.FloodWaitError as e:
print(
f"\nFlood wait error; you must wait {e.seconds} seconds before trying again."
)
client.disconnect()
sys.exit(1)
except errors.PhoneNumberInvalidError:
print("\nThe phone number is invalid.")
client.disconnect()
sys.exit(1)
except Exception as e:
print(f"\nError sending code: {e}")
client.disconnect()
sys.exit(1)
code = input("\nPlease enter the code you received: ")
try:
client.sign_in(phone, code)
except errors.SessionPasswordNeededError:
pw = input("Two-factor authentication enabled. Please enter your password: ")
client.sign_in(password=pw)
def main() -> None: def main() -> None:
API_ID = os.getenv("TELEGRAM_API_ID") API_ID = os.getenv("TELEGRAM_API_ID")
API_HASH = os.getenv("TELEGRAM_API_HASH") API_HASH = os.getenv("TELEGRAM_API_HASH")
if not API_ID or not API_HASH: if not API_ID or not API_HASH:
print("Error: TELEGRAM_API_ID and TELEGRAM_API_HASH must be set in .env file") print("Error: TELEGRAM_API_ID and TELEGRAM_API_HASH must be set in .env file")
print("Create an .env file with your credentials from https://my.telegram.org/apps") print(
"Create an .env file with your credentials from https://my.telegram.org/apps"
)
sys.exit(1) sys.exit(1)
# Convert API_ID to integer
try: try:
API_ID = int(API_ID) API_ID = int(API_ID)
except ValueError: except ValueError:
@ -47,18 +110,26 @@ def main() -> None:
print("\n----- Telegram Session String Generator -----\n") print("\n----- Telegram Session String Generator -----\n")
print("This script will generate a session string for your Telegram account.") print("This script will generate a session string for your Telegram account.")
print(
"You will be asked to enter your phone number and the verification code sent to your Telegram app."
)
print("The generated session string can be added to your .env file.") print("The generated session string can be added to your .env file.")
print( print(
"\nYour credentials will NOT be stored on any server and are only used for local authentication.\n" "\nYour credentials will NOT be stored on any server and are only used for local authentication.\n"
) )
print("Choose login method:")
print(" 1) QR code login (recommended -- scan from your Telegram app)")
print(" 2) Phone number + verification code")
method = input("\nEnter 1 or 2 [default: 1]: ").strip() or "1"
try: try:
# Connect to Telegram and generate the session string client = TelegramClient(StringSession(), API_ID, API_HASH)
with TelegramClient(StringSession(), API_ID, API_HASH) as client: client.connect()
# The client.session.save() function from StringSession returns the session string
if not client.is_user_authorized():
if method == "1":
_qr_login(client)
else:
_phone_login(client)
session_string = StringSession.save(client.session) session_string = StringSession.save(client.session)
print("\nAuthentication successful!") print("\nAuthentication successful!")
@ -68,17 +139,14 @@ def main() -> None:
print(f"TELEGRAM_SESSION_STRING={session_string}") print(f"TELEGRAM_SESSION_STRING={session_string}")
print("\nIMPORTANT: Keep this string private and never share it with anyone!") print("\nIMPORTANT: Keep this string private and never share it with anyone!")
# Optional: auto-update the .env file
choice = input( choice = input(
"\nWould you like to automatically update your .env file with this session string? (y/N): " "\nWould you like to automatically update your .env file with this session string? (y/N): "
) )
if choice.lower() == "y": if choice.lower() == "y":
try: try:
# Read the current .env file
with open(".env", "r") as file: with open(".env", "r") as file:
env_contents = file.readlines() env_contents = file.readlines()
# Update or add the SESSION_STRING line
session_string_line_found = False session_string_line_found = False
for i, line in enumerate(env_contents): for i, line in enumerate(env_contents):
if line.startswith("TELEGRAM_SESSION_STRING="): if line.startswith("TELEGRAM_SESSION_STRING="):
@ -89,7 +157,6 @@ def main() -> None:
if not session_string_line_found: if not session_string_line_found:
env_contents.append(f"TELEGRAM_SESSION_STRING={session_string}\n") env_contents.append(f"TELEGRAM_SESSION_STRING={session_string}\n")
# Write back to the .env file
with open(".env", "w") as file: with open(".env", "w") as file:
file.writelines(env_contents) file.writelines(env_contents)
@ -98,6 +165,8 @@ def main() -> None:
print(f"\nError updating .env file: {e}") print(f"\nError updating .env file: {e}")
print("Please manually add the session string to your .env file.") print("Please manually add the session string to your .env file.")
client.disconnect()
except Exception as e: except Exception as e:
print(f"\nError: {e}") print(f"\nError: {e}")
print("Failed to generate session string. Please try again.") print("Failed to generate session string. Please try again.")