diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e5ac79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +__pycache__ \ No newline at end of file diff --git a/README.md b/README.md index fd0752f..aec57cd 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,65 @@ -# Telegram API Hash Generator +# Telegram API Generator (FORK) -An app for create or get telegram api id and api +The Telegram API Generator is a Python utility designed to programmatically retrieve or create `api_id` and `api_hash` credentials from the Telegram Developer Portal (`my.telegram.org`). This tool streamlines the process of obtaining API credentials required for developing Telegram bots or applications using the Telegram API. -## Possibilities - - Fast response to messages and communication with the Telegram - - Simple and Comprehensive +## Features -## Example -``` python -from tgapi import TelegramApplication +- **Efficient Authentication**: Automates the process of sending a password request, logging in, and retrieving or creating API credentials. +- **Robust Error Handling**: Manages network errors, invalid inputs, and Telegram server responses gracefully. +- **Secure Data Handling**: Sanitizes inputs and uses fake User-Agent headers to enhance request anonymity. +- **Simple Interface**: Minimal user input required, making it accessible for developers of all levels. -app = TelegramApplication(PHONE_NUMBER) -send_password = app.send_password() +## Installation -if send_password: - auth_login = app.auth_login(PASSWORD) - - if auth_login: - auth_app = app.auth_app() - print(auth_app) +1. Clone the repository: + ```bash + git clone https://github.com/gnilobaiter/Telegram-API-Generator + cd Telegram-API-Generator + ``` + +2. Install the required dependencies: + ```bash + pip install -r requirements.txt + ``` + +3. Required dependencies (as specified in `requirements.txt`): + - `lxml==5.4.0`: For parsing HTML responses from the Telegram Developer Portal. + - `requests==2.32.4`: For sending HTTP requests to the Telegram API. + - `fake-useragent==2.2.0`: For generating random User-Agent headers to mimic browser requests. + +## Usage + +1. Run the main script (`main.py`): + ```bash + python main.py + ``` + +2. Follow the prompts: + - Enter your phone number (in international format, e.g., `+1234567890`). + - Enter the verification code received via message from Telegram. + +3. If successful, the script outputs the `api_id` and `api_hash` as a tuple. + +### Example Code + +```python +from src.api.tgapi import TelegramApplication + +# Initialize with phone number +app = TelegramApplication(phone_number="+1234567890") + +# Request verification code +if app.send_password(): + # Authenticate with the received code + if app.auth_login(cloud_password="received_code"): + # Retrieve or create API credentials + api_credentials = app.auth_app() + if api_credentials: + print(api_credentials[0], api_credentials[1]) # Outputs api_id and api_hash ``` + +## Project Structure + +- `main.py`: Entry point for user interaction, handling input and output. +- `tgapi.py`: Core logic for interacting with the Telegram Developer Portal, including authentication and API credential retrieval. +- `requirements.txt`: Lists required Python packages. \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..589d389 --- /dev/null +++ b/main.py @@ -0,0 +1,11 @@ +from src.api.tgapi import TelegramApplication + +app = TelegramApplication(str(input("Enter phone: "))) +send_password = app.send_password() + +if send_password: + auth_login = app.auth_login(str(input("Enter code: "))) + + if auth_login: + auth_app = app.auth_app() + print(auth_app[0], auth_app[1]) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a3596c0..b2ea2f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -lxml -requests +lxml==5.4.0 +requests==2.32.4 +fake-useragent==2.2.0 \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/api/__init__.py b/src/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/api/tgapi.py b/src/api/tgapi.py new file mode 100644 index 0000000..eabbd7f --- /dev/null +++ b/src/api/tgapi.py @@ -0,0 +1,165 @@ +from typing import Optional, Tuple, Any +import re +import requests +from urllib.parse import quote +from lxml import html +from fake_useragent import FakeUserAgent + +fake_useragent = FakeUserAgent() + +class TelegramApplication: + def __init__( + self, + phone_number: str, + app_title: str = "", + app_shortname: str = "", + app_url: str = "", + app_platform: str = "desktop", + app_desc: str = "", + random_hash: Optional[str] = None, + stel_token: Optional[str] = None, + useragent: Optional[str] = None + ) -> None: + # Sanitize and validate phone number + if not self._validate_phone_number(phone_number): + raise ValueError("Invalid phone number format") + self.phone_number = phone_number.strip() + + # Sanitize app parameters + self.app_title = self._sanitize_input(app_title, max_length=255) + self.app_shortname = self._sanitize_input(app_shortname, max_length=64) + self.app_url = self._sanitize_url(app_url) + self.app_platform = app_platform.lower() if app_platform in {"desktop", "ios", "android"} else "desktop" + self.app_desc = self._sanitize_input(app_desc, max_length=255) + + # Secure sensitive fields + self._random_hash = random_hash + self._stel_token = stel_token + self.useragent = useragent or fake_useragent.random + + def _validate_phone_number(self, phone: str) -> bool: + """Validate phone number format.""" + phone_pattern = r'^\+?[1-9]\d{1,14}$' + return bool(re.match(phone_pattern, phone.strip())) + + def _sanitize_input(self, value: str, max_length: int) -> str: + """Sanitize input strings.""" + if not value: + return "" + # Remove dangerous characters and limit length + sanitized = re.sub(r'[^\w\s\-\.]', '', value.strip()) + return sanitized[:max_length] + + def _sanitize_url(self, url: str) -> str: + """Sanitize and validate URL.""" + if not url: + return "" + # Basic URL validation + url_pattern = r'^https?://[\w\-\.]+(?:/[\w\-\./]*)*$' + sanitized = self._sanitize_input(url, max_length=2048) + return sanitized if re.match(url_pattern, sanitized) else "" + + def _get_headers(self, is_post: bool = True, referer: str = "https://my.telegram.org/auth") -> dict: + """Generate common headers for requests.""" + headers = { + "Origin": "https://my.telegram.org", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-US,en;q=0.9", + "User-Agent": self.useragent, + "Accept": "application/json, text/javascript, */*; q=0.01" if is_post else "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Referer": referer, + "Connection": "keep-alive", + "DNT": "1" + } + if is_post: + headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8" + headers["X-Requested-With"] = "XMLHttpRequest" + return headers + + def send_password(self) -> bool: + """Send password request to Telegram.""" + try: + response = requests.post( + url="https://my.telegram.org/auth/send_password", + data=f"phone={quote(self.phone_number)}", + headers=self._get_headers(), + timeout=10 + ) + response.raise_for_status() + data = response.json() + if "random_hash" not in data: + return False + self._random_hash = data["random_hash"] + return bool(self._random_hash) + except (requests.RequestException, ValueError): + return False + + def auth_login(self, cloud_password: str) -> bool: + """Authenticate with cloud password.""" + if not self._random_hash or not cloud_password: + return False + try: + sanitized_password = self._sanitize_input(cloud_password, max_length=100) + response = requests.post( + url="https://my.telegram.org/auth/login", + data=f"phone={quote(self.phone_number)}&random_hash={quote(self._random_hash)}&password={quote(sanitized_password)}", + headers=self._get_headers(), + timeout=10 + ) + response.raise_for_status() + self._stel_token = response.cookies.get("stel_token") + return bool(self._stel_token) + except (requests.RequestException, KeyError): + return False + + def auth_app(self) -> Optional[Tuple[str, str]]: + """Retrieve or create Telegram app credentials.""" + if not self._stel_token: + return None + try: + headers = self._get_headers(is_post=False, referer="https://my.telegram.org/org") + headers["Cookie"] = f"stel_token={quote(self._stel_token)}" + headers["Upgrade-Insecure-Requests"] = "1" + headers["Cache-Control"] = "max-age=0" + + response = requests.get( + url="https://my.telegram.org/apps", + headers=headers, + timeout=10 + ) + response.raise_for_status() + tree = html.fromstring(response.content) + api_fields = tree.xpath('//span[@class="form-control input-xlarge uneditable-input"]//text()') + if len(api_fields) >= 2: + return api_fields[0], api_fields[1] + + # Try to create a new app + hidden_hash = tree.xpath('//input[@name="hash"]/@value') + if not hidden_hash: + return None + + requests.post( + url="https://my.telegram.org/apps/create", + data=f"hash={quote(hidden_hash[0])}&app_title={quote(self.app_title)}&app_shortname={quote(self.app_shortname)}&app_url={quote(self.app_url)}&app_platform={self.app_platform}&app_desc={quote(self.app_desc)}", + headers=self._get_headers(referer="https://my.telegram.org/apps"), + timeout=10 + ).raise_for_status() + + response = requests.get( + url="https://my.telegram.org/apps", + headers=headers, + timeout=10 + ) + response.raise_for_status() + tree = html.fromstring(response.content) + api_fields = tree.xpath('//span[@class="form-control input-xlarge uneditable-input"]//text()') + return (api_fields[0], api_fields[1]) if len(api_fields) >= 2 else None + except (requests.RequestException, IndexError, ValueError): + return None + + def __setattr__(self, name: str, value: Any) -> None: + """Secure sensitive attributes.""" + if name in ("_random_hash", "_stel_token") and value is not None: + object.__setattr__(self, name, value[:100]) # Limit length + else: + object.__setattr__(self, name, value) \ No newline at end of file diff --git a/tgapi.py b/tgapi.py deleted file mode 100644 index 434128f..0000000 --- a/tgapi.py +++ /dev/null @@ -1,136 +0,0 @@ -import json -import requests -from lxml import html -from fake_useragent import FakeUserAgent - -fake_useragent = FakeUserAgent() - -class TelegramApplication: - def __init__(self, - phone_number: str, - app_title: str = "", - app_shortname: str = "", - app_url: str = "", - app_platform: str = "desktop", - app_desc: str = "", - random_hash: str = None, - stel_token: str = None, - useragent: str = fake_useragent.random - ) -> None: - self.phone_number = phone_number - self.app_title = app_title - self.app_shortname = app_shortname - self.app_url = app_url - self.app_platform = app_platform - self.app_desc = app_desc - self.random_hash = random_hash - self.stel_token = stel_token - self.useragent = useragent - - def send_password(self) -> bool: - try: - response = requests.post( - url="https://my.telegram.org/auth/send_password", - data="phone={0}".format(self.phone_number), - headers={ - "Origin": "https://my.telegram.org", - "Accept-Encoding": "gzip, deflate, br", - "Accept-Language": "it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4", - "User-Agent": self.useragent, - "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - "Accept": "application/json, text/javascript, */*; q=0.01", - "Reffer": "https://my.telegram.org/auth", - "X-Requested-With": "XMLHttpRequest", - "Connection": "keep-alive", - "Dnt": "1" - }) - - get_json = json.loads(response.content) - self.random_hash = get_json["random_hash"] - return True - except: - return False - - def auth_login(self, cloud_password: str) -> bool: - try: - responses = requests.post( - url="https://my.telegram.org/auth/login", - data="phone={0}&random_hash={1}&password={2}".format(self.phone_number, self.random_hash, cloud_password), - headers={ - "Origin": "https://my.telegram.org", - "Accept-Encoding": "gzip, deflate, br", - "Accept-Language": "it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4", - "User-Agent": self.useragent, - "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - "Accept": "application/json, text/javascript, */*; q=0.01", - "Reffer": "https://my.telegram.org/auth", - "X-Requested-With": "XMLHttpRequest", - "Connection": "keep-alive", - "Dnt": "1" - } - ) - self.stel_token = responses.cookies['stel_token'] - return True - except: - return False - - def auth_app(self) -> tuple: - try: - resp = requests.get( - url="https://my.telegram.org/apps", - headers={ - "Cookie": "stel_token={0}".format(self.stel_token), - "Accept-Encoding": "gzip, deflate, br", - "Accept-Language": "it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4", - "Upgrade-Insecure-Requests": "1", - "User-Agent": self.useragent, - "Reffer": "https://my.telegram.org/org", - "Cache-Control": "max-age=0", - "Dnt": "1" - } - ) - tree = html.fromstring(resp.content) - api = tree.xpath('//span[@class="form-control input-xlarge uneditable-input"]//text()') - return api[0], api[1] - except: - try: - s = resp.text.split('"/>')[0] - value = s.split('