First you need to generate a self-signed certificate. Certificate authority is not required to place on the client side.
openssl genrsa -out private.key 2048
openssl req -new -key private.key -out cert.csr
openssl x509 -req -days 36500 -in cert.csr -signkey private.key -out cert.crt- create
.env(see env.example) - make sure BOT_TOKEN is the correct secret for your Telegram bot.
docker compose up --build
curl -X GET https://localhost:9374/ \
--cert cert.crt \
--key private.key \
--insecure
- Using pip:
python -m venv .venv
source .venv/bin/activate.fish
pip install -r requirements.txt- Using poetry:
poetry install- Using uv:
uv sync
uv run main.pyERROR - TeleBot: "Threaded polling exception: A request to the Telegram API was unsuccessful. Error code: 409. Description: Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first"
Delete webhook by accessing this endpoint:
- https://api.telegram.org/bot/deleteWebhook
uv run test_webhook.py
uv run test_real_messages.py[
{
"ids": "123456789",
"sms": "Login code: 123456"
},
{
"ids": "987654321",
"call": true,
"from": "+1234567890",
"to": "SIM 1"
},
{
"ids": "555555555",
"sms": "Reset your password with code 654321"
}
]The format_message() function processes incoming SMS and call data, transforming them into user-friendly Telegram messages with highlighted OTP codes and phone number snippets.
def format_message(data: Dict[str, Any]) -> str:
"""Format the incoming data into a readable Telegram message."""- data (Dict[str, Any]): Dictionary containing message data with the following possible keys:
sms(str): SMS text contentcall(bool): Flag indicating incoming callfrom(str): Incoming call phone numberto(str): Destination SIM or location
When data["sms"] is provided:
- The function extracts OTP codes (4-8 digit sequences)
- OTP codes are wrapped in backticks for easy copying
- Returns formatted SMS text with highlighted codes
Input:
{
"sms": "Your verification code is 827364. Do not share."
}Output:
Your verification code is `827364`. Do not share.
If the SMS contains multiple OTP codes, all are highlighted:
Input:
{
"sms": "First code: 1234, second code: 567890"
}Output:
First code: `1234`, second code: `567890`
When data["call"] is True:
- Full phone number from
data["from"]is displayed - Last 6 digits of the phone number are extracted and wrapped in backticks
- Destination (SIM) information from
data["to"]is included - Call emoji (π) indicates incoming call
Input:
{
"call": True,
"from": "+861234567890",
"to": "SIM 1"
}Output:
π +861234567890 (`567890`), SIM 1
The function uses extract_last_digits() helper to:
- Remove all non-digit characters from phone number
- Extract the last 6 digits
- Return fewer digits if the phone number contains less than 6 digits
Examples:
"+861234567890"β"567890""+79991234567"β"234567""1234567890"β"567890""12345"β"12345"(only 5 digits available)
- SMS takes priority over calls: If both
smsandcallare provided, only SMS is formatted - Mutual exclusivity: In production, either SMS or call should be present, not both
- (str): Formatted message ready to send to Telegram
- Empty string if neither SMS nor call data is provided
def format_message(data: Dict[str, Any]) -> str:
"""Format the incoming data into a readable Telegram message."""
lines = []
# Check if it's SMS or Call
has_call = bool(data.get("call") and data.get("call", True))
has_sms = bool(data.get("sms"))
if has_sms:
# Format SMS message
formatted_sms = extract_otp_codes(data["sms"])
lines.append(formatted_sms)
elif has_call:
# Format Call message with last 6 digits wrapped in backticks
from_phone = data.get('from', 'Unknown')
to_location = data.get('to', 'Unknown')
last_digits = extract_last_digits(from_phone, 6)
lines.append(f"π {from_phone} (`{last_digits}`), {to_location}")
return "\n".join(lines)Wraps 4-8 digit sequences in backticks using regex pattern \b(\d{4,8})\b.
def extract_otp_codes(text: str) -> str:
"""Extract OTP codes from text and wrap them in backticks for easy copying."""
otp_pattern = r'\b(\d{4,8})\b'
def replace_otp(match):
return f"`{match.group(1)}`"
formatted_text = re.sub(otp_pattern, replace_otp, text)
return formatted_textExtracts the last N digits from a phone number by removing non-digit characters.
def extract_last_digits(phone: str, digits: int = 6) -> str:
"""Extract last N digits from a phone number."""
digits_only = re.sub(r'\D', '', phone)
return digits_only[-digits:] if len(digits_only) >= digits else digits_onlyThe function handles missing data gracefully:
- Missing phone number defaults to
"Unknown" - Missing SIM/location defaults to
"Unknown" - Empty data returns empty string
See test_webhook.py for unit tests of the formatting logic.