a big-brained Twitter bot that replies to mentions with Rick and Morty quotes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
6.1 KiB

from .abc import Meme
from PIL import Image, ImageDraw, ImageFont
import typing
from pseudbot.meme.post import Post
from pseudbot.util import (
alpha_comp_prep,
circle_pfp,
get_iphone_time_s,
text_wrap,
tuple_add,
)
class PhoneScreenshot(Meme):
from .post_styles import styles, time_style
def __init__(
self,
top_text: dict = None,
bottom_text: str = None,
style: str = "discord",
width: int = 1200,
height: int = 2340,
notification: str = None,
):
self.top_text = top_text
self.bottom_text = bottom_text
self.style = style
self.width = width
self.height = height
self.notification = notification
self.style_methods = {"discord": self.mk_pixmap}
self.init_style_posts()
if self.notification is not None:
self.notification_style = {
"offset": (102, 91),
"no_text_img": "templates/iphone/iphone-noti-grindr-text.png",
"icon": {
"offset": (26, 34),
"size": (62, 62),
"files": {
"grindr": "templates/iphone/icons/notification/grindr.png"
},
},
"text": {
"app_name": {
"font": "phone_sans",
"style": "Regular",
"size": 35,
"offset": (106, 53),
},
"heading": {
"font": "phone_sans",
"style": "Regular",
"size": 35,
"offset": (34, 128),
},
"body": {
"font": "phone_sans",
"style": "Regular",
"size": 35,
"offset": (34, 181),
},
},
}
def overlay_noti(base_img: Image) -> Image:
return base_img
def mk_bars(self) -> Image:
base_img = Image.new("RGBA", (self.width, self.height), (0, 0, 0, 0))
for bar in self.styles[self.style]["bars"]:
is_top = False
is_bottom = False
do_time = False
bg_img_path = bar["bg_img"]
if "top" in bar:
if bar["top"] is True:
is_top = True
do_time = True
if self.notification is not None:
do_time = False
if "alt_bg_img" in bar:
bg_img_path = self.bar["alt_bg_img"]
if "bottom" in bar:
if bar["bottom"] is True:
is_bottom = True
with Image.open(bg_img_path).convert("RGBA") as _bar_img:
with alpha_comp_prep(
Image.open(bg_img_path).convert("RGBA"),
size=base_img.size,
offset=bar["offset"],
) as bar_img:
if "text" in bar:
try:
if bar["text"]["content"] in self.top_text:
if "format" in bar["text"]:
bar_text = bar["text"]["format"].replace(
"%%%",
self.top_text[bar["text"]["content"]],
)
else:
bar_text = self.top_text[
bar["text"]["content"]
]
else:
bar_text = bar["text"]["default"]
except KeyError:
bar_text = "default text"
bar_img = self.draw_text(
img=bar_img,
text=bar_text,
offset=tuple_add(
bar["text"]["offset"], bar["offset"]
),
size=bar["text"]["size"],
fill=bar["text"]["color"],
variation=bar["text"]["style"],
fontname=bar["text"]["font"],
)
if do_time is True:
bar_img = self.draw_text(
img=bar_img,
text=get_iphone_time_s(),
offset=self.time_style["offset"],
size=self.time_style["size"],
fill=self.time_style["fill"][self.style],
variation=self.time_style["style"],
fontname=self.time_style["font"],
)
base_img = Image.alpha_composite(base_img, bar_img)
if is_bottom is True:
self.bottom_y_offset = 0 - _bar_img.size[1]
if self.notification is not None:
base_img = self.overlay_noti(base_img)
return base_img
def arrange_posts(self) -> Image:
post_base = Image.new(
"RGBA",
(self.width, self.height),
self.styles[self.style]["background"],
)
x_offset = 33
y_offset = self.height
if hasattr(self, "bottom_y_offset"):
y_offset = y_offset + self.bottom_y_offset
for post in reversed(self.posts):
p = Post(
top_text={"posts": [post]},
bottom_text=self.bottom_text,
style=self.style,
)
post_img = p.get_pixmap()
y_offset = y_offset - post_img.size[1]
post_base.paste(post_img, box=(x_offset, y_offset))
if y_offset < 0:
break
return post_base
def mk_pixmap(self):
bars = self.mk_bars() # Must be done before making posts!
posts = self.arrange_posts()
self.image = Image.alpha_composite(posts, bars)