Initial commit

This commit is contained in:
Ed 2023-08-01 23:10:14 +02:00
commit bfceff8f10
4 changed files with 223 additions and 0 deletions

72
README.md Normal file
View File

@ -0,0 +1,72 @@
# Telegram Printer Bot
This Python script implements a Telegram bot that can print images and stickers sent by users. The bot supports resizing images, converting them to grayscale, and applying gamma correction before printing to ensure maximum quality.
Currently, you can set a command to print your sticker (by default we used brother_ql to print to a Brother printer). You can use any external program you want to print to other brands and models of printers.
## Requirements
* Python 3.6+
* telethon
* PIL (Python Imaging Library) library (Pillow)
* brother_ql
You can install the requirements by running this command:
`python3 -m pip install -r requirements.txt`
If this is the first time running the script and your printer uses the `lp` protocol, remember to add your user to the `lp` group using the following command:
`sudo usermod -a -G lp ${USER}`
## Configuration
Before running the script, you need to set up the configuration parameters. You can use "config.example.py" as a guide (rename it to config.py). The following parameters must be defined:
* API_ID: Your Telegram API ID. You can obtain it by creating a Telegram application
* API_HASH: Your Telegram API hash. You can obtain it from the same page where you got the API ID.
* BOT_TOKEN: The token for your Telegram bot. You can create a new bot and obtain the token by following the instructions here.
* ADMIN_ID: Your user id. This is the user that will receive administrative rights and error reports.
* PRINT_COMMAND: Adjust with your printer model and path.
## Usage
After setting up the configuration file, you can just run the bot by using the command
`python bot.py`
Once the bot is running, it will respond to specific commands:
* `/id`: Returns your Telegram user ID, which you need to add to the ADMIN_ID list in the config.py file to grant yourself privileges.
* `/start`: Displays a welcome message and requests a password if set in the config.py file.
When the user sends the correct password in a private message, the printer functionality will be unlocked for that user.
## Features
* Printer password (pin code) protection
* Cooldown period for users
* Caching of images and stickers
* Resizing images to the correct printer resolution for maximum crispness
* Conversion to greyscale with gamma adjustment (improves images a lot!)
* Ratio limit to prevent excessively long stickers from being printed
## Important Notes
1. Make sure to set proper permissions for the cache directory to ensure the bot can write to it.
2. The PRINT_COMMAND and PRINT_SUCCESS_COMMAND in the config.py file should be customized to match the print command on your system.
3. Ensure you have a functioning printer setup before running the bot. You will find the output from the command in the console!
## License
This project is licensed under the BEER-WARE License.
```/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*/```
**This script is provided as-is, without any warranty or support. Use it at your own risk. The authors are not responsible for any misuse or damage caused by this script.**

111
bot.py Normal file
View File

@ -0,0 +1,111 @@
from telethon import TelegramClient
import logging, asyncio
from telethon.tl.types import MessageMediaDocument, DocumentAttributeSticker, DocumentAttributeAnimated, MessageMediaPhoto
from telethon import events
from telethon.tl.custom import Button
from os.path import isfile, join
from os import system
from time import time
from PIL import Image
from config import *
from os import makedirs
logging.basicConfig(level=logging.INFO)
client = TelegramClient('bot', API_ID, API_HASH).start(bot_token=BOT_TOKEN)
client.flood_sleep_threshold = 120
print_log = {}
@client.on(events.NewMessage(pattern='^/id'))
async def debug_id(ev):
await ev.respond(f"Hello! Your id is `{ev.peer_id.user_id}` please add it to the ADMIN_ID to give youself privileges :)")
@client.on(events.NewMessage(pattern='^/start'))
async def welcome(ev):
await ev.respond(WELCOME_MSG)
if (ev.peer_id.user_id not in print_log) and PASSWORD:
await ev.respond(UNLOCK_MSG)
# This one triggers on a single message with the pin code written
@client.on(events.NewMessage(pattern=PASSWORD, func=lambda e: e.is_private))
async def unlock_printer(ev):
if ev.peer_id.user_id not in print_log:
print_log[ev.peer_id.user_id] = 0
if PASSWORD:
await ev.respond(UNLOCKED_MSG)
@client.on(events.NewMessage(incoming=True, func=lambda e: e.is_private and e.message.media))
async def handler(ev):
msg = ev.message
if ev.peer_id.user_id not in print_log:
await ev.respond(UNLOCK_MSG)
# Check if the file is valid
if msg.photo:
fn = join(CACHE_DIR, f"{msg.photo.id}.jpg")
elif msg.sticker:
fn = join(CACHE_DIR, f"{msg.sticker.id}.webp")
for att in msg.sticker.attributes:
if isinstance(att, DocumentAttributeAnimated):
fn = None
break
else:
fn = None
if not fn:
await ev.respond(FORMAT_ERR_MSG)
return
# Check if the user is still in the cooldown period
time_left = int((print_log[ev.peer_id.user_id] + BASE_COOLDOWN) - time())
if time_left > 0:
await ev.respond(RATELIMIT_MSG.format(time_left=time_left))
return
# Download the file unless it's in the cache!
if not isfile(fn):
await client.download_media(msg, file=fn)
# Try opening the image, at least
try:
img = Image.open(fn)
except:
await ev.respond(FORMAT_ERR_MSG)
return
# Limit stickers ratio (so people don't print incredibly long stickers)
if img.size[1]/img.size[0] > MAX_ASPECT_RATIO:
return ev.respond(RATIO_ERR_MSG)
# Remove transparency
if img.mode == 'RGBA':
bg_img = Image.new(img.mode, img.size, BACKGROUND_COLOR)
img = Image.alpha_composite(bg_img, img)
# Resize the image
img.thumbnail([WIDTH_PX, HEIGHT_PX], resample=Image.LANCZOS, reducing_gap=None)
# Convert to grayscale and apply a gamma of 1.8
img = img.convert('L')
if GAMMA_CORRECTION != 1:
img = Image.eval(img, lambda x: int(255*pow((x/255),(1/GAMMA_CORRECTION))))
img.save(IMAGE_PATH, 'PNG')
status_code = system(PRINT_COMMAND)
if status_code == 0:
print_log[ev.peer_id.user_id] = time()
await ev.respond(PRINT_SUCCESS_MSG)
else:
await ev.respond(PRINT_FAIL_MSG)
await client.send_message(ADMIN_ID, f'Printer is not working. Process returned status code {status_code}')
if PRINT_SUCCESS_COMMAND:
system(PRINT_SUCCESS_COMMAND)
if __name__ == '__main__':
makedirs(CACHE_DIR, exist_ok=True)
client.run_until_disconnected()

37
config.example.py Normal file
View File

@ -0,0 +1,37 @@
# To get an API_ID and API_HASH, you need to sign up to be a Telegram Dev.
# Do it here: https://core.telegram.org/api/obtaining_api_id
API_ID = 11111
API_HASH = '5d41402abc4b2a76b9719d911017c592'
# Get a bot token from Telegram by creating a bot with @BotFather
BOT_TOKEN = '1222222222:b2YgZXdvaWZld29maHdlb2lmaA'
WELCOME_MSG = 'Hello!\nWelcome to **Foxo\'s label printer**! Send me any sticker or other media to print it!'
UNLOCK_MSG = 'The printer is currently locked for you. Please enter the password!'
PRINT_FAIL_MSG = 'I wasn\'t able to print your sticker.'
RATIO_ERR_MSG = 'That image is too tall. It would waste a lot of paper. Please give me a shorter sticker.'
PRINT_SUCCESS_MSG = 'Your sticker has finished printing now! Enjoy it :3'
FORMAT_ERR_MSG = 'Cannot print this. Try with a (static) sticker or a picture!'
RATELIMIT_MSG = 'Woo calm down fam!\n\nSend the sticker again in {time_left} seconds!'
UNLOCKED_MSG = 'Printer has been unlocked. Have fun!'
# Limits to prevent abuse
PASSWORD = '12345' # Set to None if no password required
BASE_COOLDOWN = 10 # Seconds between stickers printing
MAX_ASPECT_RATIO = 1.5 # Maximum ratio between height/width of sticker
ADMIN_ID = 111111 # Find your own id with the /id command
# Folder settings
IMAGE_PATH = '/tmp/image.png'
CACHE_DIR = '/tmp/printercache'
# Remember to add your user to the "lp" group or this won't work!
PRINT_COMMAND = f"brother_ql -m QL-700 -b linux_kernel -p file:///dev/usb/lp0 print -l 62 {IMAGE_PATH} -d"
PRINT_SUCCESS_COMMAND = None # "mpv --no-video success.wav" - this was used to play audio
# Resize and process settings
WIDTH_PX = 696
HEIGHT_PX = 9999 # This means "do not care about height"
GAMMA_CORRECTION = 1.8
BACKGROUND_COLOR = 'white'

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
telethon
Pillow
brother_ql