ResponseWithBarcodeBot
@responseWithBarcodeBot is an automated Telegram bot designed to convert raw text payloads and URLs into Code 128 barcode graphics on the fly.
Architecture Overview
I designed @responseWithBarcodeBot as a decoupled component within my Telegram bot infrastructure. The architecture separates raw image rendering from event dispatching and payload validation.
+------------------+ +--------------------------+ +------------------------+
| Telegram Server | -----> | Handler & Auth Layer | -----> | Core Barcode Engine |
| (Webhook/Update) | | (handlers.py) | | (core.py) |
+------------------+ +--------------------------+ +------------------------+
| |
v v
[Length & Auth Checks] [In-Memory BytesIO PNG]
The system relies on two primary components:
- Core Rendering Engine (
barcodebot/core.py): A pure Python module usingpython-barcodeto construct high-density Code 128 images into in-memory byte streams. - Telegram Interface (
barcodebot/handlers.py): An event-driven dispatcher layer usingpython-telegram-botto manage authorization, validate inputs, register command filters, and deliver photo updates.
Core Barcode Rendering Pipeline
To minimize disk I/O latency and simplify server maintenance, I opted against saving generated barcode images as temporary files. Instead, the rendering logic generates PNG graphics directly inside an io.BytesIO buffer.
import io
import logging
from typing import Optional
import barcode
from barcode.writer import ImageWriter
logger = logging.getLogger(__name__)
def generate_barcode(message: str) -> Optional[io.BytesIO]:
try:
writer_options = {
"write_text": False,
"background": "white",
"foreground": "black",
"module_width": 0.3,
"module_height": 15,
"format": "PNG"
}
barcode_obj = barcode.Code128(str(message), writer=ImageWriter())
buffer = io.BytesIO()
barcode_obj.write(buffer, options=writer_options)
buffer.seek(0)
return buffer
except Exception as e:
logger.error(f"Error generating barcode: {e}")
return None
Key Design Parameters
- Code 128 Encoding: Selected for high data density and native support for alphanumeric ASCII payloads.
- In-Memory Buffering: Writing to
io.BytesIOallows the Telegram Bot API to read image streams directly without requiring temporary disk cleanups or file locking. - Custom Dimension Ratios: Setting
module_width=0.3andmodule_height=15ensures standard scanner readability while keeping image payloads lightweight.
Request Validation and Authorization
In barcodebot/handlers.py, incoming text messages undergo validation before reaching the barcode rendering pipeline.
def parse_update_message(update) -> Optional[str]:
if not update.message.text:
return None
elif len(update.message.text) > int(settings.RESPONSEWITHBARCODEBOT_TEXT_LENGTH):
return None
else:
return update.message.text
Payload Constraints and Auth Filtering
- Payload Guardrails: Code 128 barcodes scale horizontally with text length. I capped text updates to
64characters (RESPONSEWITHBARCODEBOT_TEXT_LENGTH) to avoid producing unresolvable, excessively wide barcodes on mobile device screens. - Access Control: When
settings.SERHIIXXX_TELEGRAM_IDis configured, the handler verifies the incoming Telegram user ID against the administrative whitelist before proceeding with image rendering. - Lifecycle Management: Event listeners track bot membership updates using
ChatMemberHandlerto handle user departures cleanly.
Telegram Handler Registration
Handlers are bound to the python-telegram-bot dispatcher through register_responsewithbarcodebot_handlers:
def register_responsewithbarcodebot_handlers(dispatcher):
dispatcher.add_handler(CommandHandler('start', handle_start_message))
dispatcher.add_handler(MessageHandler(Filters.text, handle_message))
dispatcher.add_handler(ChatMemberHandler(user_left, ChatMemberHandler.MY_CHAT_MEMBER))
When a user transmits text, the bot acknowledges the request, generates the image buffer via generate_barcode(), and sends the image back as a photo reply using update.message.reply_photo(buffer, caption=...).