#!/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()