add booru image search

This commit is contained in:
Owl 2025-01-05 00:00:42 +07:00
parent 2a98b55b8d
commit f8051314cc
17 changed files with 1161 additions and 75 deletions

102
tgbot/shit/handlers.py Normal file
View file

@ -0,0 +1,102 @@
import requests
from telegram import Update, InlineQueryResultPhoto
from telegram.ext import ContextTypes
from tgbot.config import STICKER_SHITHOLE, BOORU_API_URL
from tgbot.shit.hentai import QueryParams
from tgbot.shit.render import render_text_on_image
async def handle_xitter(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.inline_query.query
xcom = "https://x.com"
results = [
{
"type": "article",
"id": "1",
"title": "fix xitter links",
"description": query.replace(xcom, "https://fxtwitter.com"),
"input_message_content": {
"message_text": query.replace(xcom, "https://fxtwitter.com")
}
}
]
await context.bot.answer_inline_query(update.inline_query.id, results)
async def handle_red_ebalo(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.inline_query.query
file = render_text_on_image("tgbot/assets/red_ebalo.png", query)
file_id = (await context.bot.send_sticker(chat_id=STICKER_SHITHOLE, sticker=file)).sticker.file_id
results = [
{
"type": "sticker",
"id": "1",
"sticker_file_id": file_id
}
]
await context.bot.answer_inline_query(update.inline_query.id, results)
async def handle_hentai(update: Update, context: ContextTypes.DEFAULT_TYPE):
error_response = [
{
"type": "article",
"id": "1",
"title": "ERROR OCCURRED! That means, at least one of us is a retard.",
"description": "None",
"input_message_content": {
"message_text": "None"
}
}
]
query = update.inline_query.query
try:
params = QueryParams.from_query_str(query).__dict__
except ValueError as e:
print(e)
error_response[0]["description"] = "error parsing query"
error_response[0]["input_message_content"]["message_text"] = "error parsing query"
return await context.bot.answer_inline_query(update.inline_query.id, error_response)
response = requests.post(BOORU_API_URL, json=params)
if response.status_code == 200:
posts = response.json()
results = []
for idx, post in enumerate(posts):
booru_post_url = post["booru"]["domain"] + \
post["booru"]["site"]["api"]["postView"] + post["id"]
results.append(
InlineQueryResultPhoto(
id="%d" % idx,
photo_url=post["fileUrl"],
thumbnail_url=post["previewUrl"],
title="IMAGE #%d" % idx,
description="Image from booru",
caption="source -> " + booru_post_url
)
)
await context.bot.answer_inline_query(update.inline_query.id, results)
else:
print(response.text)
error_response[0]["description"] = "booru error"
error_response[0]["input_message_content"]["message_text"] = response.text
return await context.bot.answer_inline_query(update.inline_query.id, error_response)

46
tgbot/shit/hentai.py Normal file
View file

@ -0,0 +1,46 @@
import re
def combine_whitespaces(s: str) -> str:
return re.compile(r"\s+").sub(" ", s).strip()
class QueryParams:
def __init__(self, booru: str, tags: list[str], random: bool = True, limit: int = 10):
self.booru = booru
self.tags = tags
self.random = random
self.limit = limit
@classmethod
def from_query_str(cls, query: str):
query = query.replace("hentai ", "")
query = combine_whitespaces(query)
list_ = query.split(" ")
booru = list_[0]
list_.remove(booru)
tags = []
random = False
limit = 10
for e in list_:
if "random=" in e: # this is 'random' argument
random = e.replace("random=", "").lower() == "true"
continue
if "limit=" in e: # this is 'limit' argument
limit = int(e.replace("limit=", ""))
continue
tags.append(e)
return cls(booru, tags, random, limit)
def __str__(self):
return "QueryParams(booru=" + self.booru + ", tags=" + str(self.tags) + ", random=" + str(self.random) + \
", limit=" + str(self.limit) + ")"

97
tgbot/shit/render.py Normal file
View file

@ -0,0 +1,97 @@
from PIL import Image, ImageDraw, ImageFont
import io
def render_text_on_image(input_image_path, text_to_draw, output_image_path=None,
font_path="tgbot/assets/arial-unicode-ms-bold.ttf", font_size=52):
image = Image.open(input_image_path)
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(font_path, font_size)
text_color = (255, 255, 255)
image_width, image_height = image.size
def wrap_text(text, draw, font, max_width):
words = text.split()
lines = []
current_line = []
current_line_width = 0
for word in words:
word_width, word_height = draw.textbbox((0, 0), word, font=font)[2:4]
space_width = draw.textbbox((0, 0), ' ', font=font)[2]
if current_line and (current_line_width + word_width + space_width) > max_width:
lines.append(' '.join(current_line))
current_line = [word]
current_line_width = word_width
else:
current_line.append(word)
current_line_width += word_width + space_width
if current_line:
lines.append(' '.join(current_line))
return lines
lines = wrap_text(text_to_draw, draw, font, image_width - 20)
total_text_height = sum([draw.textbbox((0, 0), line, font=font)[3] for line in lines])
current_y = 10
for line in lines:
draw.text((10, current_y), line, font=font, fill=text_color)
current_y += draw.textbbox((0, 0), line, font=font)[3] + 5
if current_y > image_height:
break
if output_image_path:
image.save(output_image_path)
else:
file = io.BytesIO()
image.thumbnail((512, 512))
image.save(file, format="WEBP")
file.seek(0)
return file
WIDTH = 22
HEIGHT = 9
def image_to_string(image_file):
img = Image.open(image_file)
img = img.resize((WIDTH, HEIGHT), Image.Resampling.LANCZOS)
img = img.convert("1")
# Get image dimensions
width, height = img.size
if width != 22 or height != 9:
raise ValueError("The image must be exactly 22x9 pixels.")
# Create the string representation
pixel_string = ""
for y in range(height):
for x in range(width):
# Get the pixel value (0 for black, 255 for white)
pixel = img.getpixel((x, y))
if pixel == 0: # Black pixel
pixel_string += "Ń"
else: # White pixel
pixel_string += ""
pixel_string += " " # New line for each row
return pixel_string