memebot workflow v1

master
HeyMoon 2022-08-14 19:57:07 -05:00
parent e5a6248600
commit 2435edc666
3 changed files with 690 additions and 0 deletions

117
BotModels.py 100644
View File

@ -0,0 +1,117 @@
from datetime import datetime
from email.policy import default
import time
import openai
import sqlalchemy
from sqlalchemy.orm import declarative_base, Session
from sqlalchemy import Column, DateTime, String, ForeignKey, Integer, Boolean, Table, and_, or_
Base = declarative_base()
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key = True)
number_of_comments = Column(Integer, default = 0)
def get_user(user_id : int, session : Session):
stmt = sqlalchemy.select(User).where(User.id == user_id)
user = session.execute(stmt).scalar_one_or_none()
if (user == None):
user = User(id = user_id, number_of_comments = 0)
session.add(user)
return user
def increase_number_of_comments(user_id : int, session : Session):
User.get_user(user_id, session).number_of_comments+=1
def get_number_of_comments(user_id : int, session : Session) -> int:
return User.get_user(user_id, session).number_of_comments
def reset_number_of_comments(user_id : int, session : Session):
User.get_user(user_id, session).number_of_comments = 0
def reset_all_comments(session : Session):
stmt = sqlalchemy.select(User)
all_comments = session.execute(stmt).scalars().fetchall()
for comment in all_comments:
comment.number_of_comments = 0
session.flush()
session.commit()
class Comment(Base):
__tablename__ = "comment"
id = Column(Integer, primary_key = True)
user_comment_id = Column(Integer)
bbbb_comment_id = Column(Integer)
comment_string = Column(String)
def get_past_comments(session : Session) -> 'list[str]':
stmt = sqlalchemy.select(Comment)
return [i.comment_string for i in session.execute(stmt).scalars().fetchall()[0:100]]
def get_user_comment(user_comment_id:int, session : Session):
stmt = sqlalchemy.select(Comment).where(Comment.user_comment_id == user_comment_id)
comments = session.execute(stmt).scalars().fetchall()
if len(comments) == 0:
return None
else:
return comments[0]
def get_bbbb_comment(bbbb_comment_id:int, session : Session):
stmt = sqlalchemy.select(Comment).where(Comment.bbbb_comment_id == bbbb_comment_id)
comments = session.execute(stmt).scalars().fetchall()
if len(comments) == 0:
return None
else:
return comments[0]
def get_comment(comment_id : int, session : Session):
user_comment = Comment.get_user_comment(comment_id, session)
if (user_comment is not None):
return user_comment
else:
return Comment.get_bbbb_comment(comment_id, session)
def has_replied_to_comment(comment_id : int, session : Session):
return Comment.get_comment(comment_id, session) == None
def create_new_comment(user_comment_id : int, bbbb_comment_id : int, comment_string : str, session : Session):
comment = Comment(user_comment_id = user_comment_id, bbbb_comment_id = bbbb_comment_id, comment_string = comment_string)
session.add(comment)
class Post(Base):
__tablename__ = "post"
id = Column(Integer, primary_key = True)
has_replied = Column(Boolean, default = False)
replies_to_post = Column(Integer, default = 0)
def get_post(post_id : int, session : Session):
stmt = sqlalchemy.select(Post).where(Post.id == post_id)
post = session.execute(stmt).scalar_one_or_none()
if (post == None):
post = Post(id = post_id)
session.add(post)
return post
def has_replied_to_post(post_id : int, session : Session):
return Post.get_post(post_id, session).has_replied
def increment_replies(post_id : int, session : Session):
Post.get_post(post_id, session).replies_to_post += 1
def get_number_of_replies(post_id : int, session : Session):
replies = Post.get_post(post_id, session).replies_to_post
if replies == None:
replies = 0
return replies
def register_post_reply(post_id : int, session : Session):
Post.get_post(post_id, session).has_replied = True

207
automeme.py 100644
View File

@ -0,0 +1,207 @@
import base64
import io
import json
import re
import meme_generator
from RDramaAPIInterface import RDramaAPIInterface
from datetime import datetime
from os.path import exists, join, realpath, split
from threading import Timer
from BotModels import Base, Comment, Post, User
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
import os
from markdown import markdown
from bs4 import BeautifulSoup
TEST_MODE = True
TEST_AUTH_TOKEN = "ED3eURMKP9FKBFbi-JUxo8MPGWkEihuyIlAUGtVL7xwx0NEy4Nf6J_mxWYTPgAQx1iy1X91hx7PPHyEBS79hvKVIy5DMEzOyAe9PAc5pmqSJlLGq_-ROewMwFzGrqer4"
MINUTES_BEFORE_FORCED_SHUTDOWN = 10
DB_FILENAME = "automeme_database.db"
PAGES_TO_SCAN = 5
AUTOMEME_ID = 3 #TODO
ALLOWED_COMMENTS_PER_POST = 20
ALLOWED_COMMENTS_PER_USER_PER_DAY = 20
def get_real_filename(filename : str):
path_to_script = realpath(__file__)
path_to_script_directory, _ = split(path_to_script)
return join(path_to_script_directory, filename)
# rdrama = RDramaAPIInterface(TEST_AUTH_TOKEN, "localhost", sleep=5, https=False)
# print(open('emoji_cache/klanjak.webp', 'rb'))
# image = meme_generator.create_classic_meme_from_emoji("marseyannoyed", "THAT FACE WHEN YOU", "FORGET TO TAKE OUT THE TRASH")
# output = io.BytesIO()
# image.save(output, format="webp")
# file = {'file': ('based.webp', output.getvalue(), 'image/webp')}
# rdrama.reply_to_comment_easy(175, 1, "assddsfssdssdsd", file=file)
def comment_with_image(image, comment_id, post_id):
output = io.BytesIO()
image.save(output, format="webp")
file = {'file': ('based.webp', output.getvalue(), 'image/webp')}
rdrama.reply_to_comment_easy(comment_id, post_id, "ffffff", file=file)
class TextElement():
pass
class Text(TextElement):
def __init__(self, text):
self.text = text
def __repr__(self) -> str:
return f"Text({self.text})"
class Emoji(TextElement):
def __init__(self, emoji, big):
self.emoji = emoji
self.big = big
def __repr__(self) -> str:
return f"Emoji({self.emoji}, big={self.big})"
def get_text_only(text_elements : list[TextElement]) -> str:
text = [i.text for i in text_elements if isinstance(i, Text)]
return " ".join(text)
def text_elements(string : str):
EMOJI_REGEX = r"(:[^ ]*:)"
elements = re.split(EMOJI_REGEX, string)
to_return = []
for element in elements:
if element == "":
continue
if not re.match(EMOJI_REGEX, element):
to_return.append(Text(element.strip()))
else:
if "#" in element:
big = True
element = element.replace("#","")
else:
big = False
element = element.strip(":")
to_return.append(Emoji(element, big))
return to_return
def strip_markdown(markdown_string):
markdown_string = re.sub(">.*\n", "", markdown_string)
try:
html = markdown(markdown_string)
except AttributeError:
html = markdown_string #if there is no markdown in the string you get an error
soup = BeautifulSoup(html, "html.parser")
text = ''.join(soup.findAll(text=True))
text = re.sub(r"!blackjack[^ ]*", "", text)
text = re.sub(r"fortune", "", text)
text = re.sub(r"factcheck", "", text)
text = re.sub("!slots.*?\s", "", text)
text = re.sub(r"\"", "'", text)
# make sure there are only letters in the string.
if len(set(list(text.lower())).intersection(set(["a",'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']))) == 0:
return ""
text = re.sub("@(.*?)\s", "", text)
text = re.sub("!slots.*?\s", "", text)
text = re.sub("(?i)trans lives matter", "", text)
return text
def remove_duplicates(list):
return [json.loads(j) for j in set([json.dumps(i) for i in list])]
def get_eligible_comments(rdrama : RDramaAPIInterface, session : Session):
comments = rdrama.get_comments(number_of_pages=PAGES_TO_SCAN)['data']
comments = [comment for comment in comments if not comment['is_bot']] #No bots
comments = [comment for comment in comments if not comment['author']['id'] == BBBB_ID] #Don't reply to self
comments = [comment for comment in comments if Post.get_number_of_replies(comment['post_id'], session) < ALLOWED_COMMENTS_PER_POST] #Don't spam posts
comments = [comment for comment in comments if User.get_number_of_comments(comment['author']['id'], session) < ALLOWED_COMMENTS_PER_USER_PER_DAY] #Don't spam users
comments = [comment for comment in comments if Comment.get_comment(comment['id'], session) is None] #Double check that we haven't replied to the comment
comments = remove_duplicates(comments) #Remove the duplicates
return comments
def main_processing_task(rdrama : RDramaAPIInterface, session : Session):
is_chudded = False #Do we have the chud award?
can_communicate = True #Can we send any message at all?
is_pizzad = False
rdrama.get_front_page()
bbbb_information = rdrama.get_user_information(BBBB_ID)
print(f"coins: {bbbb_information['coins']} comments: {bbbb_information['comment_count']}")
for badge in bbbb_information['badges']:
if (badge['name'] == "Marsey Award"):
print("We have the marsey award. STOP.")
can_communicate = False
if (badge['name'] == "Chud"):
print("We have the CHUD award. CONTINUE")
is_chudded = True
if (badge['name'] == "Bird Site Award"):
print("We have the Bird Site Award. STOP.")
can_communicate = False
if (badge['name'] == "Pizzashill Award"):
print("We have the Pizzashill Award. CONTINUE.")
is_pizzad = True
if bbbb_information['is_banned']:
print("We are banned. STOP.")
can_communicate = False
if can_communicate:
eligible_comments = get_eligible_comments(rdrama, session)
for eligible_comment in eligible_comments:
comment_text = eligible_comment['body']
cleaned_comment_text = strip_markdown(comment_text)
comment_lines = cleaned_comment_text.split("\n")
comment_lines = [comment_line for comment_line in comment_lines if comment_line != ""]
element_lines = [text_elements(line) for line in comment_lines]
image = None
if (len(element_lines) == 2):
if isinstance(element_lines[0][0], Emoji) and isinstance(element_lines[1][0], Emoji):
emoji1 = element_lines[0][0].emoji
emoji2 = element_lines[1][0].emoji
caption1 = get_text_only(element_lines[0][1:])
caption2 = get_text_only(element_lines[1][1:])
image = meme_generator.create_soy_vs_chad_meme(emoji1, emoji2, caption1, caption2)
if image != None:
comment_with_image(image, eligible_comment['id'], eligible_comment['post_id'])
if __name__ == "__main__":
TEST_AUTH_TOKEN = "ED3eURMKP9FKBFbi-JUxo8MPGWkEihuyIlAUGtVL7xwx0NEy4Nf6J_mxWYTPgAQx1iy1X91hx7PPHyEBS79hvKVIy5DMEzOyAe9PAc5pmqSJlLGq_-ROewMwFzGrqer4"
print(f"======= RUNNING AT {datetime.now().hour}:{datetime.now().minute} ======= ")
if TEST_MODE:
website = "localhost"
auth = TEST_AUTH_TOKEN
https = False
timeout = 1
BBBB_ID = 6
OPERATOR_ID = 9
ACTUALLY_CALL_OPEN_AI = False
else:
website = "rdrama.net"
with open(get_real_filename("rdrama_auth_token"), "r") as f:
auth = f.read()
https = True
timeout = 10
rdrama = RDramaAPIInterface(auth, website, timeout, https=https)
#Set up fail safe
def exitfunc():
print("*That's it, you're going in the retard squisher.*")
print("FAILSAFE FORCED SHUTDOWN", datetime.now())
os._exit(0)
timer = Timer(60*MINUTES_BEFORE_FORCED_SHUTDOWN, exitfunc)
timer.start()
engine = create_engine(f"sqlite:///{get_real_filename(DB_FILENAME)}")
Base.metadata.create_all(engine)
with Session(engine) as session:
main_processing_task(rdrama, session)
session.commit()
timer.cancel()

366
meme_generator.py 100644
View File

@ -0,0 +1,366 @@
import math
from tkinter import UNITS
from typing import Union
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from PIL import ImageOps
import requests
import io
from image_utils import ImageText
from os.path import exists
HIGHLIGHT_MODE = False
class ColorScheme:
BLACK = 0
WHITE_WITH_BLACK_BORDER = 1
def create_soy_vs_chad_meme(emoji1, emoji2, caption1, caption2):
LEFT_MARGIN_COLUMN = 20
CONTENT_COLUMN = 300
MIDDLE_MARGIN_COLUMN = 80
RIGHT_MARGIN_COLUMN = LEFT_MARGIN_COLUMN
TOP_MARGIN_ROW = 80
IMAGE_ROW = 300
MIDDLE_MARGIN_ROW = 20
TEXT_ROW = 100
BOTTOM_MARGIN_ROW = 200
total_image_size_x = 2*CONTENT_COLUMN + LEFT_MARGIN_COLUMN + RIGHT_MARGIN_COLUMN + MIDDLE_MARGIN_COLUMN
total_image_size_y = TOP_MARGIN_ROW + IMAGE_ROW + MIDDLE_MARGIN_ROW + TEXT_ROW + BOTTOM_MARGIN_ROW
left_image = get_emoji_from_rdrama(emoji1)
right_image = get_emoji_from_rdrama(emoji2)
#Resize images
left_image = ImageOps.contain(left_image, (CONTENT_COLUMN, IMAGE_ROW))
right_image = ImageOps.contain(right_image, (CONTENT_COLUMN, IMAGE_ROW))
right_image = ImageOps.mirror(right_image)
#Base image
base = Image.new(mode="RGB", size=(total_image_size_x,total_image_size_y), color=(255,255,255))
#Add images
center_and_paste(base, left_image, (LEFT_MARGIN_COLUMN,TOP_MARGIN_ROW), (CONTENT_COLUMN, IMAGE_ROW))
center_and_paste(base, right_image, (LEFT_MARGIN_COLUMN+CONTENT_COLUMN+MIDDLE_MARGIN_COLUMN,TOP_MARGIN_ROW), (CONTENT_COLUMN, IMAGE_ROW))
#Text regions
add_text_box(base,
caption1,
(CONTENT_COLUMN, TEXT_ROW),
(LEFT_MARGIN_COLUMN, TOP_MARGIN_ROW+IMAGE_ROW+MIDDLE_MARGIN_ROW),
init_font_size=50,
align="cht",
font="impact.ttf",
color=ColorScheme.WHITE_WITH_BLACK_BORDER)
add_text_box(base,
caption2,
(CONTENT_COLUMN, TEXT_ROW),
(LEFT_MARGIN_COLUMN+CONTENT_COLUMN+MIDDLE_MARGIN_COLUMN, TOP_MARGIN_ROW+IMAGE_ROW+MIDDLE_MARGIN_ROW),
init_font_size=50,
align="cht",
font="impact.ttf",
color=ColorScheme.WHITE_WITH_BLACK_BORDER)
return add_watermark(base)
def create_classic_meme(image: Image, top_caption : str, bottom_caption : str):
image_x_size, image_y_size = image.size
UNIT = 5
caption_size = int(image_y_size/UNIT)
add_text_box(image, top_caption, (image_x_size, caption_size), (0,0), "impact.ttf", 60, align="cvch", color=ColorScheme.WHITE_WITH_BLACK_BORDER)
add_text_box(image, bottom_caption, (image_x_size, caption_size), (0,int((UNIT-1)*(image_y_size/UNIT))), "impact.ttf", 60, align="cvch", color=ColorScheme.WHITE_WITH_BLACK_BORDER)
return image
def create_classic_meme_from_url(url : str, top_caption : str, bottom_caption : str):
return create_classic_meme(get_image_file_from_url(url), top_caption, bottom_caption)
def create_classic_meme_from_emoji(emoji : str, top_caption : str, bottom_caption : str):
EMOJI_SIZE = 400
BORDER_SIZE = 100
marsey = get_emoji_from_rdrama(emoji)
marsey = ImageOps.contain(marsey, (EMOJI_SIZE, EMOJI_SIZE))
base = Image.new(mode="RGB", size=(EMOJI_SIZE+2*BORDER_SIZE, EMOJI_SIZE+2*BORDER_SIZE), color=(255,255,255))
base.paste(marsey, (BORDER_SIZE, BORDER_SIZE), marsey)
return create_classic_meme(base, top_caption, bottom_caption)
def create_modern_meme(image : Image, caption : str):
CAPTION_SIZE = 150
image_x_size, image_y_size = image.size
base = Image.new(mode="RGB", size=(image_x_size,image_y_size+CAPTION_SIZE), color=(255,255,255))
base.paste(image, (0, CAPTION_SIZE))
add_text_box(base, caption, (image_x_size, CAPTION_SIZE), (0,0), font="intreb.ttf",align="chcv")
return base
def create_modern_meme_from_url(url : str, caption : str):
return create_modern_meme(get_image_file_from_url(url), caption)
def create_modern_meme_from_emoji(emoji: str, caption: str):
EMOJI_SIZE = 400
BORDER_SIZE = 10
marsey = get_emoji_from_rdrama(emoji)
marsey = ImageOps.contain(marsey, (EMOJI_SIZE, EMOJI_SIZE))
base = Image.new(mode="RGB", size=(EMOJI_SIZE+2*BORDER_SIZE, EMOJI_SIZE+2*BORDER_SIZE), color=(255,255,255))
base.paste(marsey, (BORDER_SIZE, BORDER_SIZE), marsey)
return create_modern_meme(base, caption)
class WebcomicPanel():
PANEL_SIZE = 400
FONT = "Little Story.ttf"
def __init__(self):
pass
def create_image(self) -> Image:
return Image.new(mode="RGB", size=(self.PANEL_SIZE,self.PANEL_SIZE), color=(255,255,255))
class OneCharacterWebcomicPanel(WebcomicPanel):
def __init__(self, emoji, caption, words_in_background):
self.emoji = emoji
self.caption = caption
self.words_in_background = words_in_background
def create_image(self) -> Image:
base = super().create_image()
panel_size_x, panel_size_y = base.size
# We put the text in the background of the panel.
text_region_x_size = int(panel_size_x)
text_region_y_size = int(panel_size_y if self.words_in_background else panel_size_y/2)
add_text(base, self.caption, (text_region_x_size, text_region_y_size), (0,0), font=super().FONT)
# We put marsey in the bottom left quadrant
emoji_region_x_size = int(panel_size_x)
emoji_region_y_size = int(panel_size_y/2)
emoji_placement_position_x = 0
emoji_placement_position_y = int(panel_size_y/2)
emoji = get_emoji_from_rdrama(self.emoji)
center_and_paste(base, emoji, (emoji_placement_position_x, emoji_placement_position_y), (emoji_region_x_size, emoji_region_y_size))
return add_border_to_image(base)
class TwoCharacterWebcomicPanel(WebcomicPanel):
def __init__(self, left_emoji, left_caption, right_emoji, right_caption):
self.left_emoji = left_emoji
self.left_caption = left_caption
self.right_emoji = right_emoji
self.right_caption = right_caption
def create_image(self) -> Image:
base = super().create_image()
panel_size_x, panel_size_y = base.size
# We put the left marsey in the bottom left quadrant
left_emoji_region_x_size = int(panel_size_x/2)
left_emoji_region_y_size = int(panel_size_y/2)
left_emoji_placement_position_x = 0
left_emoji_placement_position_y = int(panel_size_y/2)
left_emoji = get_emoji_from_rdrama(self.left_emoji)
center_and_paste(base, left_emoji, (left_emoji_placement_position_x, left_emoji_placement_position_y), (left_emoji_region_x_size, left_emoji_region_y_size))
# We put the right marsey in the bottom right quadrant
right_emoji_region_x_size = int(panel_size_x/2)
right_emoji_region_y_size = int(panel_size_y/2)
right_emoji_placement_position_x = int(panel_size_x/2)
right_emoji_placement_position_y = int(panel_size_y/2)
right_emoji = get_emoji_from_rdrama(self.right_emoji)
center_and_paste(base, right_emoji, (right_emoji_placement_position_x, right_emoji_placement_position_y), (right_emoji_region_x_size, right_emoji_region_y_size))
#Each text caption will get 5/8 of the width, and 1/4 of the height of the panel.
#The left caption will be all the way to the left. The right caption will be 3/8 to the right.
CAPTION_UNITS = 5
CAPTION_DIVISOR = 8
# We put the text in the top half of the panel.
left_text_region_x_size = int(CAPTION_UNITS*(panel_size_x/CAPTION_DIVISOR))
left_text_region_y_size = int(panel_size_y/4)
left_text_region_x_position = 0
left_text_region_y_position = 0
add_text_box(base, self.left_caption, (left_text_region_x_size, left_text_region_y_size), (left_text_region_x_position,left_text_region_y_position), font=super().FONT, align="bl")
# We put the text in the top half of the panel.
right_text_region_x_size = int(CAPTION_UNITS*(panel_size_x/CAPTION_DIVISOR))
right_text_region_y_size = int(panel_size_y/4)
right_text_region_x_position = int((CAPTION_DIVISOR-CAPTION_UNITS)*(panel_size_x/8))
right_text_region_y_position = int(panel_size_y/4)
add_text_box(base, self.right_caption, (right_text_region_x_size, right_text_region_y_size), (right_text_region_x_position,right_text_region_y_position), font=super().FONT, align="br")
return add_border_to_image(base)
class TitleCardWebcomicPanel(WebcomicPanel):
def __init__(self, caption):
self.caption = caption
def create_image(self) -> Image:
base = super().create_image()
add_text_box(base, self.caption, base.size, (0,0), font=super().FONT, init_font_size=90, align="cvch")
return add_border_to_image(base)
def create_webcomic(layout : 'list[WebcomicPanel]'):
assumed_panel_x_size, assumed_panel_y_size = layout[0].create_image().size
total_image_x_size = assumed_panel_x_size * 2
total_image_y_size = assumed_panel_x_size * math.ceil(len(layout)/2)
image = Image.new(mode="RGB", size=(total_image_x_size, total_image_y_size), color=(255,255,255))
for i in range(len(layout)):
panel = layout[i]
x = i%2
y = math.floor(i/2)
image.paste(panel.create_image(), (x*assumed_panel_x_size, y*assumed_panel_y_size))
return add_watermark(image)
def add_text_box(base : Image, caption : str, region_size : tuple[int, int], coordinates : tuple[int, int], font : str= "arial.ttf", init_font_size = 45, align :str = "", color = ColorScheme.BLACK):
if caption == "":
return
if init_font_size == 0:
print("Retard moment")
return
region_x_size, region_y_size = region_size
line_image = ImageText((region_x_size, region_y_size))
if color == ColorScheme.BLACK:
fill_color = (0,0,0)
stroke = None
stroke_size = 0
if color == ColorScheme.WHITE_WITH_BLACK_BORDER:
fill_color = (255,255,255)
stroke = (0,0,0)
stroke_size = 3
place = "left"
if "ch" in align:
place = "center"
actual_text_box_size = line_image.write_text_box((0,0), caption, region_x_size, font_size=init_font_size, font_filename=font, color=fill_color, stroke_color=stroke, stroke_size=stroke_size, place=place)
_, actual_text_box_y_size, input_text_block_x_size, actual_text_box_x_size = actual_text_box_size
if actual_text_box_y_size <= region_y_size:
actual_paste_x_coordinates, actual_paste_y_coordinates = coordinates
if align != "":
y_difference = region_y_size - actual_text_box_y_size
x_difference = region_x_size - actual_text_box_x_size
# Horizontal Align
if "t" in align:
#This is the default
pass
elif "b" in align:
actual_paste_y_coordinates+=y_difference
elif "cv" in align:
actual_paste_y_coordinates += int(y_difference/2)
if "l" in align:
#This is the default
pass
elif "r" in align:
actual_paste_x_coordinates+=x_difference
# elif "ch" in align:
# actual_paste_x_coordinates += int(x_difference/2)
if HIGHLIGHT_MODE:
image_draw = ImageDraw.Draw(base)
image_draw.rectangle((coordinates, (coordinates[0]+region_size[0], coordinates[1]+region_size[1])), fill="blue")
image_draw.rectangle(((actual_paste_x_coordinates, actual_paste_y_coordinates), (actual_paste_x_coordinates+actual_text_box_x_size, actual_text_box_y_size+actual_paste_y_coordinates)), fill="tan")
base.paste(line_image.image, (actual_paste_x_coordinates, actual_paste_y_coordinates), line_image.image)
else:
add_text_box(base, caption, region_size, coordinates, font=font, init_font_size=init_font_size-1, align=align, color=color)
def add_text(base : Image, caption : str, region_size : tuple[int, int], coordinates : tuple[int, int], font : str= "arial.ttf"):
if caption == "":
return
region_x_size, region_y_size = region_size
line_image = ImageText((region_x_size, region_y_size))
line_image.fill_text_box((0,0), caption, region_x_size, region_y_size, font_filename=font)
base.paste(line_image.image, coordinates, line_image.image)
def add_watermark(image : Image):
WATERMARK_HEIGHT = 30
image_size_x, image_size_y = image.size
base = Image.new(mode="RGB", size=(image_size_x, image_size_y + WATERMARK_HEIGHT), color=(255,255,255))
base.paste(image)
marsey = get_emoji_from_rdrama("marseyjamming")
marsey = ImageOps.contain(marsey, (WATERMARK_HEIGHT, WATERMARK_HEIGHT))
base.paste(marsey, (0, image_size_y), marsey)
text_line_size = int(WATERMARK_HEIGHT/2)
add_text(base, "A meme by HeyMoon and Foo", (image_size_x, text_line_size), (WATERMARK_HEIGHT, image_size_y))
add_text(base, "For instructions on how to legally build a pipe bomb, go to rdrama.net", (image_size_x, text_line_size), (WATERMARK_HEIGHT, image_size_y+text_line_size))
return base
def center_and_paste(base : Image, to_paste : Image, coordinates: tuple[int, int], box_size : tuple[int, int]):
to_paste = ImageOps.contain(to_paste, box_size)
image_size_x, image_size_y = to_paste.size
box_size_x, box_size_y = box_size
extra_space_x = box_size_x - image_size_x
extra_space_y = box_size_y - image_size_y
offset_x = int(extra_space_x/2)
offset_y = int(extra_space_y/2)
box_coordinate_x, box_coordinate_y = coordinates
x, y = offset_x + box_coordinate_x, offset_y + box_coordinate_y
base.paste(to_paste, (x, y), to_paste)
def add_border_to_image(image : Image, thickness : int = 5):
inner_image_x_size, inner_image_y_size = image.size
outer_image_x_size, outer_image_y_size = inner_image_x_size + 2*thickness, inner_image_y_size + 2*thickness
outside_image = Image.new(mode="RGB", size=(outer_image_x_size,outer_image_y_size), color=(0,0,0))
outside_image.paste(image, (thickness, thickness))
return outside_image
def get_emoji_from_rdrama(emoji_name):
cleaned_emoji_name : str = emoji_name
should_flip = False
if '!' in emoji_name:
cleaned_emoji_name = cleaned_emoji_name.replace("!", "")
should_flip = True
if (exists(f"emoji_cache/{cleaned_emoji_name}.webp")):
image = Image.open(f"emoji_cache/{cleaned_emoji_name}.webp")
else:
image = get_image_file_from_url(f"https://www.rdrama.net/e/{cleaned_emoji_name}.webp")
image.save(f"emoji_cache/{cleaned_emoji_name}.webp")
if should_flip:
image = ImageOps.mirror(image)
return image
def get_image_file_from_url(url):
r = requests.get(url)
image_file = io.BytesIO(r.content)
im = Image.open(image_file)
return im
#create_soy_vs_chad_meme("bigsmilesoyjak", "!marseyshooting", "I have fun new toys and games for your children", "Die").show()
# create_webcomic([
# TwoCharacterWebcomicPanel("soyjak", "Black people deserve the rope", "marseyconfused", "Why?"),
# TwoCharacterWebcomicPanel("seethejak", "Because they are degenerate!!!", "marseysmug", "Kinda like you?"),
# OneCharacterWebcomicPanel("soycry", "No!! I am a pure aryan white boy and I am special Hitler told me so, so fuck off you nigger cunt. God I hate you so much, if I commit suicide its gonna be your fault, fuck you, its not fair, why do you always have to bully me around, you are such a bitch, i hate you so much, hitler was right and six million wasnt nearly enough, the jews are responsible for this and they will be punished on the day of the rope, youll be sorry then, plus i am armed and dangerous and i have a gun and i will shoot you if you keep making fun of me plus youll be in troulbe if I kill myself so how do you like that you stupid nigger bitch. fuck", words_in_background=True),
# TitleCardWebcomicPanel("One Hour Later..."),
# TwoCharacterWebcomicPanel("marseytombstone", "", "!marseycry", "He had so much to live for"),
# OneCharacterWebcomicPanel("marseylaugh", "Just Kidding!", False)
# ]).show()
#create_classic_meme_from_url("https://rdrama.net/images/16603133970578706.webp", "in all seriousness it probably isn't worth the effort because this is just one of many ways they could goad the bot into saying something innapropriate. Like who cares lol its just one of many things they could say.", "also there isn't really any specific harm done to anyone by a bot saying pedophile nonsense, it's offensive at worst and funny at best. i laughed at least. also also this legit is something that only happens every 2500 comments or so (there was another comment a while back where bbbb said something similar)").show()
#create_modern_meme_from_url("https://cdn.discordapp.com/attachments/1007776259910152292/1007833711540174885/unknown.png", "and then heymoon says the imposter is among us").show()
#create_classic_meme_from_emoji("marseycock", "I WANT TO PUT MY DICK", "INSIDE OF MARSEY").show()
#create_modern_meme_from_emoji("rdramajanny", "youll be sorry when i get my mop you BITCH").show()