From f7ab68fc0796ed9ec7e56ea75f836041eacafaf5 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Sun, 24 Sep 2023 21:38:46 +0300 Subject: Update to 2023 --- .gitignore | 6 +- .vscode/settings.json | 7 ++ Dockerfile | 12 ++++ Procfile | 1 - build-and.push.sh | 7 ++ docker-compose.yml | 9 +++ requirements.txt | 23 +++++-- runtime.txt | 1 - taulu.png | Bin 370904 -> 0 bytes taulubot.py | 186 ++++++++++++++++++++++++++++---------------------- wooden.png | Bin 0 -> 370904 bytes 11 files changed, 162 insertions(+), 90 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Dockerfile delete mode 100644 Procfile create mode 100755 build-and.push.sh create mode 100644 docker-compose.yml delete mode 100644 runtime.txt delete mode 100644 taulu.png create mode 100644 wooden.png diff --git a/.gitignore b/.gitignore index a8515b8..06f5b02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ -photo -run_bot.bat +.venv +*.pyc +.env +photo/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..445067b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "editor.formatOnSave": true, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.analysis.typeCheckingMode": "basic" +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..32d3d05 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.11-alpine + +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app +COPY requirements.txt ./ +RUN pip install -r requirements.txt + +COPY *.png /app/ +COPY taulubot.py /app/taulubot.py + +CMD ["python", "taulubot.py"] diff --git a/Procfile b/Procfile deleted file mode 100644 index 052715a..0000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -worker: python taulubot.py 185486156:AAG2-8O_FtNIYWgg9F0lqMXoE16MO1o1NVE diff --git a/build-and.push.sh b/build-and.push.sh new file mode 100755 index 0000000..09732a8 --- /dev/null +++ b/build-and.push.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +IMAGE=registry.digitalocean.com/jan-systems-registry/taulubot:latest + +set -euxo pipefail +docker build --platform linux/amd64 -t $IMAGE . +docker push $IMAGE diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6f9a1b2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3.8' + +services: + taulubot: + image: registry.digitalocean.com/jan-systems-registry/taulubot:latest + volumes: + - ${PWD}/photo:/app/photo + environment: + BOT_TOKEN: "${BOT_TOKEN}" diff --git a/requirements.txt b/requirements.txt index 0bafeec..de427cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,19 @@ -Pillow==3.1.1 -requests==2.9.1 -telepot==6.3 -virtualenv==14.0.6 \ No newline at end of file +aiohttp==3.8.5 +aiosignal==1.3.1 +anyio==4.0.0 +async-timeout==4.0.3 +attrs==23.1.0 +certifi==2023.7.22 +charset-normalizer==3.2.0 +frozenlist==1.4.0 +h11==0.14.0 +httpcore==0.17.3 +httpx==0.24.1 +idna==3.4 +multidict==6.0.4 +Pillow==10.0.1 +requests==2.31.0 +sniffio==1.3.0 +telepot==12.7 +urllib3==2.0.5 +yarl==1.9.2 diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index f72c511..0000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.9.0 diff --git a/taulu.png b/taulu.png deleted file mode 100644 index 19856c1..0000000 Binary files a/taulu.png and /dev/null differ diff --git a/taulubot.py b/taulubot.py index 40e6367..ae8a9b8 100644 --- a/taulubot.py +++ b/taulubot.py @@ -1,121 +1,143 @@ -import sys import random import time from pprint import pprint import telepot -import urllib.request +from telepot.loop import MessageLoop import time from PIL import Image import os import calendar import logging -logging.basicConfig(format='%(asctime)s %(message)s') -taulu_im = Image.open("taulu.png") +logging.basicConfig(format="%(asctime)s %(message)s", level=logging.INFO) + +BOT_TOKEN = os.getenv("BOT_TOKEN", default=None) +if not BOT_TOKEN: + raise Exception("BOT_TOKEN not defined in env") + +wooden_im = Image.open("wooden.png") golden_im = Image.open("golden.png") img_size = (640, 640) -GOLDEN_CHANCE = 2 #% +GOLDEN_CHANCE = 1 # % START_TIME = calendar.timegm(time.gmtime()) -taulu_im.thumbnail(img_size, Image.ANTIALIAS) -golden_im.thumbnail(img_size, Image.ANTIALIAS) +wooden_im.thumbnail(img_size) +golden_im.thumbnail(img_size) -def run_taulu(chat_id, user_id): +bot = telepot.Bot(BOT_TOKEN) +logging.warning("Connected with token {}".format(BOT_TOKEN)) - photos = bot.getUserProfilePhotos(user_id) +last_user_by_chat_id = {} - if photos["total_count"] == 0: - logging.error("No pictures found, sending message...") - bot.sendMessage(chat_id, "Vitun taulu, hommaa kuva!") - return - logging.warning("Looking up picture...") - pic = photos["photos"][0][-1] - file_id = pic["file_id"] +def edit_image(unedited_path, edited_path, frame_im): + if os.path.exists(edited_path): + im = Image.open(edited_path) + else: + im = Image.open(unedited_path) + im.thumbnail(img_size) + im.paste(frame_im, (0, 0), frame_im) + im.save(edited_path) - if not os.path.exists("photo/"): - logging.warning("No 'photo' directory in working directory, creating one...") - os.makedirs("photo/") + return im - # download to a file with user_id in the name for duplicate recognition - filepath = "photo/" + str(abs(user_id)) + ".jpg" - finalpath = "photo/" + str(abs(user_id)) + "final.png" - # every 100th image has golden borders :) - golden_number= random.randrange(1, 100) - logging.warning("Random gold number was: {}".format(golden_number)) - is_golden = (golden_number < GOLDEN_CHANCE) +def run(chat_id, user_id): + photos = bot.getUserProfilePhotos(user_id) - if os.path.exists(finalpath) and not is_golden: - logging.warning("User profile already found. Skipping download and edit...") - else: - logging.warning("Downloading picture...") - bot.downloadFile(file_id, filepath) - # time.sleep(2) + if photos["total_count"] == 0: + logging.error("No pictures found, sending message...") + bot.sendMessage(chat_id, "Vitun taulu, hommaa kuva!") + return - logging.warning("Opening image for editing...") - im = Image.open(filepath) - im.thumbnail(img_size, Image.ANTIALIAS) + logging.warning("Looking up picture...") + pic = photos["photos"][0][-1] + file_id = pic["file_id"] - if is_golden: - logging.warning("Golden taulu!") - im.paste(golden_im, (0, 0), golden_im) - bot.sendMessage(chat_id, "Onneksi olkoon! Kultainen taulu ilmestyy vain kerran tuhannessa vuodessa!") - else: - im.paste(taulu_im, (0, 0), taulu_im) + if not os.path.exists("photo/"): + logging.warning("No 'photo' directory in working directory, creating one...") + os.makedirs("photo/") - logging.warning("Saving image...") - im.save(finalpath) + unedited_path = f"photo/{file_id}.jpg" + edited_path_wooden = f"photo/{file_id}_wooden.png" + edited_path_gold = f"photo/{file_id}_gold.png" - f = open(finalpath, "rb") - logging.warning("Sending photo {} to chat {}...".format(finalpath, chat_id)) - bot.sendPhoto(chat_id, f) + if os.path.exists(unedited_path): + logging.info("User profile pic already found. Skipping download...") + else: + logging.warning(f"Downloading profile image with file_id {file_id}...") + bot.download_file(file_id, unedited_path) - logging.warning("Image sent succesfully.") - return + # one image in 100 has golden borders :) + golden_number = random.randrange(0, 100 - 1) + logging.warning("Random gold number was: {}".format(golden_number)) + is_golden = golden_number < GOLDEN_CHANCE -# Getting the token from command-line is better than embedding it in code, -# because tokens are supposed to be kept secret. -TOKEN = sys.argv[1] + if is_golden: + bot.sendMessage( + chat_id, + "Onneksi olkoon! Kultainen taulu ilmestyy vain kerran tuhannessa vuodessa!", + ) + edited_path = edited_path_gold + frame_im = golden_im + else: + edited_path = edited_path_wooden + frame_im = wooden_im -bot = telepot.Bot(TOKEN) -logging.warning("Connected with token {}".format(TOKEN)) + logging.warning( + "Editing and sending photo {} to chat {}...".format(edited_path, chat_id) + ) + im = edit_image(unedited_path, edited_path, frame_im) + with open(edited_path, "rb") as f: + bot.sendPhoto(chat_id, f) + + logging.warning("Image sent succesfully.") + return -last_user_by_chat_id = {} -done_list = [] def is_taulu_command(text): - return "taulu" in text.strip().lower() + return "taulu" in text.strip().lower() + def handle(msg): + chat_id = msg["chat"]["id"] + user_id = msg["from"]["id"] + user_name = msg["from"]["first_name"] + msg_text = msg["text"] + logging.debug( + "New message! chat_id: {}, user_name: {}, msg_text: {}".format( + chat_id, user_name, msg_text + ) + ) + + if is_taulu_command(msg_text): + logging.info("Taulu command found!") + attempt, ATTEMPTS = 0, 3 + while attempt < ATTEMPTS: + try: + taulu_id = last_user_by_chat_id[chat_id] + logging.warning("Running taulu for user id {}".format(taulu_id)) + run(chat_id, taulu_id) + break + except KeyError: + logging.error( + "No chat id found in chat dict. Maybe no previous messages in the chat?" + ) + break + except: + logging.error( + "Error occured during process. Retrying... (attempt {})".format( + attempt + ) + ) + attempt += 1 + + last_user_by_chat_id[chat_id] = user_id + - chat_id = msg["chat"]["id"] - user_id = msg["from"]["id"] - user_name = msg["from"]["first_name"] - msg_text = msg["text"] - logging.warning("New message! chat_id: {}, user_name: {}, msg_text: {}".format(chat_id, user_name, msg_text)) - - if is_taulu_command(msg_text): - logging.warning("Taulu command found!") - attempt, ATTEMPTS = 0, 3 - while attempt < ATTEMPTS: - try: - taulu_id = last_user_by_chat_id[chat_id] - logging.warning("Running taulu for user id {}".format(taulu_id)) - run_taulu(chat_id, taulu_id) - break - except KeyError: - logging.error("No chat id found in chat dict. Maybe no previous messages in the chat?") - break - except: - logging.error("Error occured during process. Retrying... (attempt {})".format(attempt)) - attempt += 1 - - last_user_by_chat_id[chat_id] = user_id - -bot.notifyOnMessage(handle) logging.warning("Listening...") +MessageLoop(bot, handle).run_as_thread() # Keep the program running. while 1: - time.sleep(5) + time.sleep(1) diff --git a/wooden.png b/wooden.png new file mode 100644 index 0000000..19856c1 Binary files /dev/null and b/wooden.png differ -- cgit v1.3