Files
receipt_maker/receipt.py
2026-03-07 14:38:53 +00:00

163 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python3
from escpos import printer
from PIL import Image
import os
import subprocess
import random
import requests
# Return T20II printer
def get_T20II_usb():
p = printer.Usb(0x04B8, 0x0202) # , profile="TM-T20II")
# p.set_with_default(align='center', font='a', bold=False, width=2, height=2, custom_size=True, smooth=True)
return p
def get_T20II_ethernet():
p = printer.Network("192.168.192.168", port=9100) # , profile="TM-T20II")
# p.set_with_default(align='center', font='a', bold=False, width=2, height=2, custom_size=True, smooth=True)
return p
def resize_image_to_fullwidth(img_src_name, target_width=576):
# Make fullwidth dir
os.makedirs("img_fullwidth", exist_ok=True)
# Open the image
img = Image.open(img_src_name)
# Get original dimensions
width, height = img.size
# Calculate new height to maintain aspect ratio
aspect_ratio = height / width
new_height = int(target_width * aspect_ratio)
# Resize the image
resized_img = img.resize((target_width, new_height), Image.LANCZOS)
# Save the resized image
_, ext = os.path.splitext(img_src_name)
filename_no_ext = os.path.splitext(os.path.basename(img_src_name))[0]
# Build destination filename
dest_name = f"img_fullwidth/{filename_no_ext}_fullwidth{ext}"
resized_img.save(dest_name)
return dest_name
def get_random_bant_image():
# Create img directory if it doesn't exist
os.makedirs("img", exist_ok=True)
# Fetch the catalog JSON for /bant/
url = "https://a.4cdn.org/bant/catalog.json"
response = requests.get(url)
response.raise_for_status()
catalog = response.json()
# Flatten the list of threads from all pages
threads = [thread for page in catalog for thread in page["threads"]]
# Filter threads that have images (tim and ext fields)
image_threads = [
thread
for thread in threads
if "tim" in thread
and "ext" in thread
and thread["ext"].lower() not in [".gif", ".mp4", ".webm"]
]
if not image_threads:
return None # No images found
# Choose a random thread with an image
thread = random.choice(image_threads)
# Construct image URL
image_url = f"https://i.4cdn.org/bant/{thread['tim']}{thread['ext']}"
filename = f"img/{thread['tim']}{thread['ext']}"
# Download and save image
img_response = requests.get(image_url)
img_response.raise_for_status()
with open(filename, "wb") as f:
f.write(img_response.content)
return filename
def print_random_bant_image(p, sh_file):
img = get_random_bant_image()
if img is None:
print("No images found on /bant/.")
return
filename_no_ext = os.path.splitext(os.path.basename(img))[0]
p.textln(filename_no_ext)
fimg = resize_image_to_fullwidth(img)
try:
p.image(fimg, impl="bitImageColumn")
except Exception as e:
print(f"Print failed, reconnecting: {e}")
subprocess.run(["bash", sh_file], check=True)
p = get_T20II_ethernet()
p.cut()
def print_note(p, text):
p.textln(text)
p.cut()
def print_local_image(p, sh_file, img_path, message=None):
if not os.path.isfile(img_path):
print(f"File not found: {img_path}")
return
if message:
p.textln(message)
fimg = resize_image_to_fullwidth(img_path)
try:
p.image(fimg, impl="bitImageColumn")
except Exception as e:
print(f"Print failed, reconnecting: {e}")
subprocess.run(["bash", sh_file], check=True)
p = get_T20II_ethernet()
p.cut()
def main():
import argparse
parser = argparse.ArgumentParser(description="Receipt printer CLI")
subparsers = parser.add_subparsers(dest="command", required=True)
subparsers.add_parser("image", help="Print a random /bant/ image")
note_p = subparsers.add_parser("note", help="Print a text note")
note_p.add_argument("text", help="The note to print")
print_p = subparsers.add_parser("print", help="Print a local image")
print_p.add_argument("path", help="Path to the image file")
print_p.add_argument("message", nargs="?", default=None, help="Optional caption")
args = parser.parse_args()
script_dir = os.path.dirname(os.path.abspath(__file__))
sh_file = os.path.join(script_dir, "connect_recipt.sh")
subprocess.run(["bash", sh_file], check=True)
p = get_T20II_ethernet()
if args.command == "image":
print_random_bant_image(p, sh_file)
elif args.command == "note":
print_note(p, args.text)
elif args.command == "print":
print_local_image(p, sh_file, args.path, args.message)
if __name__ == "__main__":
main()