sob sob and just more sobbing
This commit is contained in:
parent
867b53e4c3
commit
04b0144281
10 changed files with 131 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,3 +6,4 @@ memory.json
|
||||||
*.pkl
|
*.pkl
|
||||||
memory.json
|
memory.json
|
||||||
venv/
|
venv/
|
||||||
|
output.png
|
||||||
|
|
BIN
assets/fonts/impact.ttf
Normal file
BIN
assets/fonts/impact.ttf
Normal file
Binary file not shown.
BIN
assets/images/attention.webp
Normal file
BIN
assets/images/attention.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
BIN
assets/images/bibinos.png
Normal file
BIN
assets/images/bibinos.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 295 KiB |
BIN
assets/images/crash.webp
Normal file
BIN
assets/images/crash.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 155 KiB |
BIN
assets/images/genuineidiot.png
Normal file
BIN
assets/images/genuineidiot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 355 KiB |
20
bot.py
20
bot.py
|
@ -12,6 +12,7 @@ import psutil
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands, tasks
|
from discord.ext import commands, tasks
|
||||||
from discord import app_commands
|
from discord import app_commands
|
||||||
|
from discord import Colour
|
||||||
|
|
||||||
import nltk
|
import nltk
|
||||||
from nltk.data import find
|
from nltk.data import find
|
||||||
|
@ -26,6 +27,7 @@ from modules.version import *
|
||||||
from modules.sentenceprocessing import *
|
from modules.sentenceprocessing import *
|
||||||
from modules.prestartchecks import start_checks
|
from modules.prestartchecks import start_checks
|
||||||
from modules.unhandledexception import handle_exception
|
from modules.unhandledexception import handle_exception
|
||||||
|
from modules.image import gen_image
|
||||||
from discord.ext import commands, tasks
|
from discord.ext import commands, tasks
|
||||||
from discord import app_commands
|
from discord import app_commands
|
||||||
sys.excepthook = handle_exception
|
sys.excepthook = handle_exception
|
||||||
|
@ -244,13 +246,23 @@ async def talk(ctx, sentence_size: int = 5):
|
||||||
# Remove default help command to use custom help
|
# Remove default help command to use custom help
|
||||||
bot.help_command = None
|
bot.help_command = None
|
||||||
|
|
||||||
|
# Command: Show help information
|
||||||
|
@bot.hybrid_command(description=f"{get_translation(LOCALE, 'command_desc_help')}")
|
||||||
|
async def image(ctx):
|
||||||
|
await gen_image()
|
||||||
|
await send_message(ctx, file=discord.File("output.png"))
|
||||||
|
|
||||||
|
|
||||||
|
# Remove default help command to use custom help
|
||||||
|
bot.help_command = None
|
||||||
|
|
||||||
# Command: Show help information
|
# Command: Show help information
|
||||||
@bot.hybrid_command(description=f"{get_translation(LOCALE, 'command_desc_help')}")
|
@bot.hybrid_command(description=f"{get_translation(LOCALE, 'command_desc_help')}")
|
||||||
async def help(ctx):
|
async def help(ctx):
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"{get_translation(LOCALE, 'command_help_embed_title')}",
|
title=f"{get_translation(LOCALE, 'command_help_embed_title')}",
|
||||||
description=f"{get_translation(LOCALE, 'command_help_embed_desc')}",
|
description=f"{get_translation(LOCALE, 'command_help_embed_desc')}",
|
||||||
color=discord.Color.blue()
|
color=Colour(0x000000)
|
||||||
)
|
)
|
||||||
|
|
||||||
command_categories = {
|
command_categories = {
|
||||||
|
@ -343,7 +355,7 @@ async def ping(ctx):
|
||||||
f"{PING_LINE}\n"
|
f"{PING_LINE}\n"
|
||||||
f"`{get_translation(LOCALE, 'command_ping_embed_desc')}: {latency}ms`\n"
|
f"`{get_translation(LOCALE, 'command_ping_embed_desc')}: {latency}ms`\n"
|
||||||
),
|
),
|
||||||
color=discord.Color.blue()
|
color=Colour(0x000000)
|
||||||
)
|
)
|
||||||
LOLembed.set_footer(text=f"{get_translation(LOCALE, 'command_ping_footer')} {ctx.author.name}", icon_url=ctx.author.avatar.url)
|
LOLembed.set_footer(text=f"{get_translation(LOCALE, 'command_ping_footer')} {ctx.author.name}", icon_url=ctx.author.avatar.url)
|
||||||
|
|
||||||
|
@ -355,7 +367,7 @@ async def about(ctx):
|
||||||
print("-----------------------------------\n\n")
|
print("-----------------------------------\n\n")
|
||||||
latest_version = check_for_update() # check_for_update from modules/version.py
|
latest_version = check_for_update() # check_for_update from modules/version.py
|
||||||
print("-----------------------------------")
|
print("-----------------------------------")
|
||||||
embed = discord.Embed(title=f"{get_translation(LOCALE, 'command_about_embed_title')}", description="", color=discord.Color.blue())
|
embed = discord.Embed(title=f"{get_translation(LOCALE, 'command_about_embed_title')}", description="", color=Colour(0x000000))
|
||||||
embed.add_field(name=f"{get_translation(LOCALE, 'command_about_embed_field1')}", value=f"{NAME}", inline=False)
|
embed.add_field(name=f"{get_translation(LOCALE, 'command_about_embed_field1')}", value=f"{NAME}", inline=False)
|
||||||
embed.add_field(name=f"{get_translation(LOCALE, 'command_about_embed_field2name')}", value=f"{get_translation(LOCALE, 'command_about_embed_field2value').format(local_version=local_version, latest_version=latest_version)}", inline=False)
|
embed.add_field(name=f"{get_translation(LOCALE, 'command_about_embed_field2name')}", value=f"{get_translation(LOCALE, 'command_about_embed_field2value').format(local_version=local_version, latest_version=latest_version)}", inline=False)
|
||||||
|
|
||||||
|
@ -374,7 +386,7 @@ async def stats(ctx):
|
||||||
|
|
||||||
with open(memory_file, 'r') as file:
|
with open(memory_file, 'r') as file:
|
||||||
line_count = sum(1 for _ in file)
|
line_count = sum(1 for _ in file)
|
||||||
embed = discord.Embed(title=f"{get_translation(LOCALE, 'command_stats_embed_title')}", description=f"{get_translation(LOCALE, 'command_stats_embed_desc')}", color=discord.Color.blue())
|
embed = discord.Embed(title=f"{get_translation(LOCALE, 'command_stats_embed_title')}", description=f"{get_translation(LOCALE, 'command_stats_embed_desc')}", color=Colour(0x000000))
|
||||||
embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field1name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field1value').format(file_size=file_size, line_count=line_count)}", inline=False)
|
embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field1name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field1value').format(file_size=file_size, line_count=line_count)}", inline=False)
|
||||||
embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field2name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field2value').format(local_version=local_version, latest_version=latest_version)}", inline=False)
|
embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field2name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field2value').format(local_version=local_version, latest_version=latest_version)}", inline=False)
|
||||||
embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field3name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field3value').format(NAME=NAME, PREFIX=PREFIX, ownerid=ownerid, cooldown_time=cooldown_time, PING_LINE=PING_LINE, showmemenabled=showmemenabled, USERTRAIN_ENABLED=USERTRAIN_ENABLED, last_random_talk_time=last_random_talk_time, song=song, splashtext=splashtext)}", inline=False)
|
embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field3name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field3value').format(NAME=NAME, PREFIX=PREFIX, ownerid=ownerid, cooldown_time=cooldown_time, PING_LINE=PING_LINE, showmemenabled=showmemenabled, USERTRAIN_ENABLED=USERTRAIN_ENABLED, last_random_talk_time=last_random_talk_time, song=song, splashtext=splashtext)}", inline=False)
|
||||||
|
|
|
@ -40,5 +40,5 @@ song = os.getenv("song")
|
||||||
arch = platform.machine()
|
arch = platform.machine()
|
||||||
slash_commands_enabled = False
|
slash_commands_enabled = False
|
||||||
latest_version = "0.0.0"
|
latest_version = "0.0.0"
|
||||||
local_version = "0.15.8"
|
local_version = "1.0.0"
|
||||||
os.environ['gooberlocal_version'] = local_version
|
os.environ['gooberlocal_version'] = local_version
|
||||||
|
|
112
modules/image.py
Normal file
112
modules/image.py
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
from modules.markovmemory import load_markov_model
|
||||||
|
from modules.sentenceprocessing import improve_sentence_coherence, rephrase_for_coherence
|
||||||
|
|
||||||
|
generated_sentences = set()
|
||||||
|
|
||||||
|
async def gen_image(sentence_size=5, max_attempts=10):
|
||||||
|
images_folder = "assets/images"
|
||||||
|
image_files = [f for f in os.listdir(images_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.webp'))]
|
||||||
|
if not image_files:
|
||||||
|
return
|
||||||
|
|
||||||
|
markov_model = load_markov_model()
|
||||||
|
if not markov_model:
|
||||||
|
return
|
||||||
|
|
||||||
|
def load_font(size):
|
||||||
|
return ImageFont.truetype("assets/fonts/Impact.ttf", size=size)
|
||||||
|
|
||||||
|
def draw_text_with_outline(draw, text, x, y, font):
|
||||||
|
outline_offsets = [(-2, -2), (-2, 2), (2, -2), (2, 2), (0, -2), (0, 2), (-2, 0), (2, 0)]
|
||||||
|
for ox, oy in outline_offsets:
|
||||||
|
draw.text((x + ox, y + oy), text, font=font, fill="black")
|
||||||
|
draw.text((x, y), text, font=font, fill="white")
|
||||||
|
|
||||||
|
def text_height(font, text):
|
||||||
|
bbox = draw.textbbox((0, 0), text, font=font)
|
||||||
|
return bbox[3] - bbox[1]
|
||||||
|
|
||||||
|
def fits_in_width(text, font, max_width):
|
||||||
|
bbox = draw.textbbox((0,0), text, font=font)
|
||||||
|
text_width = bbox[2] - bbox[0]
|
||||||
|
return text_width <= max_width
|
||||||
|
|
||||||
|
def split_text_to_fit(text, font, max_width):
|
||||||
|
words = text.split()
|
||||||
|
for i in range(len(words), 0, -1):
|
||||||
|
top_text = " ".join(words[:i])
|
||||||
|
bottom_text = " ".join(words[i:])
|
||||||
|
if fits_in_width(top_text, font, max_width) and fits_in_width(bottom_text, font, max_width):
|
||||||
|
return top_text, bottom_text
|
||||||
|
midpoint = len(words)//2
|
||||||
|
return " ".join(words[:midpoint]), " ".join(words[midpoint:])
|
||||||
|
|
||||||
|
attempt = 0
|
||||||
|
while attempt < max_attempts:
|
||||||
|
chosen_image_path = os.path.join(images_folder, random.choice(image_files))
|
||||||
|
img = Image.open(chosen_image_path).convert("RGBA")
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
width, height = img.size
|
||||||
|
|
||||||
|
font_size = int(height / 10)
|
||||||
|
font = load_font(font_size)
|
||||||
|
|
||||||
|
# Generate text
|
||||||
|
response = None
|
||||||
|
for _ in range(20):
|
||||||
|
if sentence_size == 1:
|
||||||
|
candidate = markov_model.make_short_sentence(max_chars=100, tries=100)
|
||||||
|
if candidate:
|
||||||
|
candidate = candidate.split()[0]
|
||||||
|
else:
|
||||||
|
candidate = markov_model.make_sentence(tries=100, max_words=sentence_size)
|
||||||
|
|
||||||
|
if candidate and candidate not in generated_sentences:
|
||||||
|
if sentence_size > 1:
|
||||||
|
candidate = improve_sentence_coherence(candidate)
|
||||||
|
generated_sentences.add(candidate)
|
||||||
|
response = candidate
|
||||||
|
break
|
||||||
|
|
||||||
|
if not response:
|
||||||
|
response = "no text generated"
|
||||||
|
|
||||||
|
cleaned_response = re.sub(r'[^\w\s]', '', response).lower()
|
||||||
|
coherent_response = rephrase_for_coherence(cleaned_response).upper()
|
||||||
|
bbox = draw.textbbox((0, 0), coherent_response, font=font)
|
||||||
|
text_width = bbox[2] - bbox[0]
|
||||||
|
text_height_px = bbox[3] - bbox[1]
|
||||||
|
max_text_height = height // 4
|
||||||
|
|
||||||
|
if text_width <= width and text_height_px <= max_text_height:
|
||||||
|
# Fits on top, draw at y=0 (top)
|
||||||
|
draw_text_with_outline(draw, coherent_response, (width - text_width) / 2, 0, font)
|
||||||
|
img.save("output.png")
|
||||||
|
return
|
||||||
|
top_text, bottom_text = split_text_to_fit(coherent_response, font, width)
|
||||||
|
|
||||||
|
top_bbox = draw.textbbox((0,0), top_text, font=font)
|
||||||
|
bottom_bbox = draw.textbbox((0,0), bottom_text, font=font)
|
||||||
|
|
||||||
|
top_height = top_bbox[3] - top_bbox[1]
|
||||||
|
bottom_height = bottom_bbox[3] - bottom_bbox[1]
|
||||||
|
if top_height <= max_text_height and bottom_height <= max_text_height:
|
||||||
|
# top text
|
||||||
|
draw_text_with_outline(draw, top_text, (width - (top_bbox[2]-top_bbox[0])) / 2, 0, font)
|
||||||
|
# bottom text
|
||||||
|
y_bottom = height - bottom_height
|
||||||
|
draw_text_with_outline(draw, bottom_text, (width - (bottom_bbox[2]-bottom_bbox[0])) / 2, y_bottom, font)
|
||||||
|
img.save("output.png")
|
||||||
|
return
|
||||||
|
attempt += 1
|
||||||
|
|
||||||
|
# If all attempts fail, cry.
|
||||||
|
truncated = coherent_response[:100]
|
||||||
|
bbox = draw.textbbox((0, 0), truncated, font=font)
|
||||||
|
text_width = bbox[2] - bbox[0]
|
||||||
|
draw_text_with_outline(draw, truncated, (width - text_width) / 2, 0, font)
|
||||||
|
img.save("output.png")
|
|
@ -5,3 +5,4 @@ requests
|
||||||
psutil
|
psutil
|
||||||
better_profanity
|
better_profanity
|
||||||
python-dotenv
|
python-dotenv
|
||||||
|
pillow
|
Loading…
Add table
Add a link
Reference in a new issue