diff --git a/CenturyGothicBold.ttf b/CenturyGothicBold.ttf new file mode 100644 index 0000000..d3577b9 Binary files /dev/null and b/CenturyGothicBold.ttf differ diff --git a/MORJ.png b/MORJ.png new file mode 100644 index 0000000..bec9f82 Binary files /dev/null and b/MORJ.png differ diff --git a/main.py b/main.py index 8bfccd9..9c0b40b 100755 --- a/main.py +++ b/main.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import logging +import os import traceback from datetime import datetime, timedelta from html import escape @@ -8,6 +9,7 @@ from queue import Queue, Empty from time import sleep from threading import Thread from typing import Dict, List +from uuid import uuid4 import sentry_sdk from telegram.error import Unauthorized, TelegramError @@ -17,6 +19,7 @@ from telegram import Message, Update, Bot, InlineKeyboardMarkup, InlineKeyboardB from config import BOT_TOKEN, SENTRY_DSN, MANAGEMENT_CHAT, DEBUG from db import get_conn, Subscriber, PersistentMapping, commit +from morj import draw_morj from send_users_list import send_users_list @@ -232,6 +235,14 @@ def users_list(bot: Bot, update: Update): update.effective_message.reply_text('\n'.join(messages[i:i+40]), parse_mode='html') +def morj(bot: Bot, update: Update): + text = update.effective_message.text[5:] + fname = '/tmp/morj{}.png'.format(uuid4()) + draw_morj(text, fname) + update.effective_message.reply_document(open(fname, 'rb')) + os.unlink(fname) + + def _process_message(bot: Bot, m: Message): if m.sticker or m.animation: delta = datetime.now() - conn.root.last_media @@ -363,6 +374,7 @@ if __name__ == '__main__': updater.dispatcher.add_handler(CommandHandler('remove', remove_user, Filters.chat(MANAGEMENT_CHAT), pass_args=True)) updater.dispatcher.add_handler(CallbackQueryHandler(remove_user, pattern=r'^remove (\d+)$', pass_groups=True)) updater.dispatcher.add_handler(CommandHandler('users', users_list, Filters.private)) + updater.dispatcher.add_handler(CommandHandler('morj', morj)) updater.dispatcher.add_handler(MessageHandler(Filters.private, msg)) updater.start_polling() diff --git a/morj.py b/morj.py new file mode 100644 index 0000000..5021cf4 --- /dev/null +++ b/morj.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright 2011 Álvaro Justen [alvarojusten at gmail dot com] +# License: GPL + +from PIL import Image, ImageDraw, ImageFont + +FONT_FILE = 'CenturyGothicBold.ttf' +BG = 'MORJ.png' + + +class ImageText(object): + def __init__(self, filename_or_size, mode='RGBA', background=(0, 0, 0, 0), + encoding='utf8'): + if isinstance(filename_or_size, str): + self.filename = filename_or_size + self.image = Image.open(self.filename) + self.size = self.image.size + elif isinstance(filename_or_size, (list, tuple)): + self.size = filename_or_size + self.image = Image.new(mode, self.size, color=background) + self.filename = None + self.draw = ImageDraw.Draw(self.image) + self.encoding = encoding + + def save(self, filename=None): + self.image.save(filename or self.filename) + + def get_font_size(self, text, font, max_width=None, max_height=None): + if max_width is None and max_height is None: + raise ValueError('You need to pass max_width or max_height') + font_size = 1 + text_size = self.get_text_size(font, font_size, text) + if (max_width is not None and text_size[0] > max_width) or \ + (max_height is not None and text_size[1] > max_height): + raise ValueError("Text can't be filled in only (%dpx, %dpx)" % text_size) + while True: + if (max_width is not None and text_size[0] >= max_width) or \ + (max_height is not None and text_size[1] >= max_height): + return font_size - 1 + font_size += 1 + text_size = self.get_text_size(font, font_size, text) + + def write_text(self, position, text, font_filename, font_size=11, color=(0, 0, 0), max_width=None, max_height=None): + x, y = position + if font_size == 'fill' and \ + (max_width is not None or max_height is not None): + font_size = self.get_font_size(text, font_filename, max_width, max_height) + text_size = self.get_text_size(font_filename, font_size, text) + font = ImageFont.truetype(font_filename, font_size) + if x == 'center': + x = (self.size[0] - text_size[0]) / 2 + if y == 'center': + y = (self.size[1] - text_size[1]) / 2 + self.draw.text((x, y), text, font=font, fill=color) + return text_size + + def get_text_size(self, font_filename, font_size, text): + font = ImageFont.truetype(font_filename, font_size) + return font.getsize(text) + + def write_text_box(self, position, text, box_width, font_filename, font_size=11, color=(0, 0, 0), place='left', + justify_last_line=False): + x, y = position + lines = [] + line = [] + text_height = 0 + text_lines = text.split('\n') + for text_line in text_lines: + words = text_line.split(' ') + for word in words: + new_line = ' '.join(line + [word]) + size = self.get_text_size(font_filename, font_size, new_line) + text_height = size[1] + if size[0] <= box_width: + line.append(word) + else: + lines.append(line) + line = [word] + if line: + lines.append(line) + line = [] + lines = [' '.join(line) for line in lines if line] + height = y + for index, line in enumerate(lines): + height += text_height + if place == 'left': + self.write_text((x, height), line, font_filename, font_size, color) + elif place == 'right': + total_size = self.get_text_size(font_filename, font_size, line) + x_left = x + box_width - total_size[0] + self.write_text((x_left, height), line, font_filename, font_size, color) + elif place == 'center': + total_size = self.get_text_size(font_filename, font_size, line) + x_left = int(x + ((box_width - total_size[0]) / 2)) + self.write_text((x_left, height), line, font_filename, font_size, color) + elif place == 'justify': + words = line.split() + if (index == len(lines) - 1 and not justify_last_line) or len(words) == 1: + self.write_text((x, height), line, font_filename, font_size, color) + continue + line_without_spaces = ''.join(words) + total_size = self.get_text_size(font_filename, font_size, line_without_spaces) + space_width = (box_width - total_size[0]) / (len(words) - 1.0) + start_x = x + for word in words[:-1]: + self.write_text((start_x, height), word, font_filename, font_size, color) + word_size = self.get_text_size(font_filename, font_size, word) + start_x += word_size[0] + space_width + last_word_size = self.get_text_size(font_filename, font_size, words[-1]) + last_word_x = x + box_width - last_word_size[0] + self.write_text((last_word_x, height), words[-1], font_filename, font_size, color) + return box_width, height - y + + +def draw_morj(text, filename): + img = ImageText(BG) + img.write_text_box((67, 70), text, box_width=800, font_filename=FONT_FILE, font_size=40, color=(255, 255, 255)) + img.save(filename)