from io import BytesIO
from datetime import datetime
import PIL
import aiohttp
import aiofiles
from PIL import Image as img
from .http import HTTPClient
from .errors import ImageNotGenerated
[docs]class BaseImage:
"""
Base class for all images
-------------------------
Methods
-------
save(path : str) : Saves the file to a path
"""
def __init__(self, image_bytes=None) -> None:
self.image_bytes = image_bytes
[docs] async def save(self, path: str) -> None:
"""
Saves an image
"""
if self.image_bytes is None:
raise ImageNotGenerated
async with aiofiles.open(path, "wb") as f:
await f.write(self.image_bytes)
[docs] async def show(self) -> None:
"""
Shows an image
"""
if self.image_bytes is None:
raise ImageNotGenerated
image = img.open(BytesIO(self.image_bytes))
image.show()
return None
[docs] async def save_bytesio(self) -> BytesIO:
"""
Saves the image to BytesIO
Returns
-------
:class:`BytesIO`
"""
if self.image_bytes is None:
raise ImageNotGenerated
image = BytesIO(self.image_bytes)
return image
[docs] async def pil(self) -> PIL.Image.Image:
"""
Converts the image to a PIL.Image.Image object and returns it
Returns
-------
:class:`PIL.Image.Image`
"""
image = img.open(BytesIO(self.image_bytes))
return image
[docs]class RandomMeme(BaseImage):
"""
Random Meme
-----------
Example
-------
>>> meme = await Image.random_meme()
>>> await meme.save('meme.png')
Attrbutes
---------
image_bytes (bytes) : The image in bytes
title (str) : Title of the post
upvotes (str) : How many upvotes the meme has
author (str) : Author of the meme
url (str) : Url to the reddit post
ext (str) : The file extension (eg: png)
json (Dict) : The json response from the api
created_at (datetime.datetime) : The time when the class was made
"""
def __init__(self, json, image_bytes) -> None:
self.json = json
super().__init__(image_bytes=image_bytes)
self.created_at = datetime.now()
@property
def title(self) -> str:
"""The title of the meme"""
if self.image_bytes is None:
raise ImageNotGenerated
return self.json["title"]
@property
def upvotes(self) -> str:
"""How many upvotes the meme has"""
if self.image_bytes is None:
raise ImageNotGenerated
return self.json["upvotes"]
@property
def author(self) -> str:
"""Author of the post"""
if self.image_bytes is None:
raise ImageNotGenerated
return self.json["author"]
@property
def url(self) -> str:
"""Url to the reddit post"""
if self.image_bytes is None:
raise ImageNotGenerated
return self.json["url"]
@property
def ext(self) -> str:
"""The file extension"""
if self.image_bytes is None:
raise ImageNotGenerated
return self.json["url"].split(".")[-1]
[docs]class QRCode(BaseImage):
"""
QR Code
-------
Example
-------
>>> qrcode = Image.qrcode("https://google.com")
>>> await meme.save('qrcode.png')
Attrbutes
---------
url (str) : The url that your making the meme for
image_bytes (bytes) : The image in bytes
created_at (datetime) : The time when the class was made
"""
def __init__(self, url, image_bytes):
self.url = url
self.created_at = datetime.now()
super().__init__(image_bytes=image_bytes)
[docs]class FontImage(BaseImage):
"""
FontConvertedImage
------------------
Attributes
----------
created_at (datetime) : The time when the class was made
"""
def __init__(self, image_bytes):
self.created_at = datetime.now()
super().__init__(image_bytes=image_bytes)
[docs]class Image:
"""
Group of non meme generating image function
-------------------------------------------
Methods
-------
random_meme()
qrcode(url : str)
get_colors(filepath : str, show_hex : bool = True)
"""
[docs] @classmethod
async def random_meme(cls) -> RandomMeme:
"""
Gets a random meme from the subreddit: r/memes
Returns
-------
:class:`RandomMeme` : The meme
"""
while True:
image = await HTTPClient().get_json(url="meme?reddit_json_info=True")
if "." in image["url"]:
break
image_url = image["url"]
image_bytes = await HTTPClient().get_url_image(image_url)
return RandomMeme(json=image, image_bytes=image_bytes)
[docs] @classmethod
async def qrcode(cls, url: str) -> QRCode:
"""
Generates a qr code
Returns
-------
:class:`QRCode` : The qrcode
"""
qrcode = await HTTPClient().get_image(f"qrcode?link={url}")
return QRCode(url, qrcode)
[docs] @classmethod
async def get_colors(cls, filepath: str, show_hex=True) -> dict:
"""
Gets the most dominant color and color palette of an image
Parameters
----------
filepath (str) : The path to the file
show_hex (bool) : By default the api will return hex values but if you want rgb set this to False
Example
-------
>>> await Image.get_colors("snail.png", False)
"""
try:
with open(filepath, "rb") as f:
image_in_bytes = f.read()
except FileNotFoundError:
return "File not found"
async with aiohttp.ClientSession() as session:
async with session.post(
f"https://api.fusionsid.xyz/api/get_colors/?show_hex={show_hex}",
data={"image": image_in_bytes},
) as resp:
data = await resp.json()
return data
[docs] @classmethod
async def font_convert(
cls, text: str, font_name: str, color: str = "black"
) -> FontImage:
"""
Converts text to a font you choose
Parameters
----------
text (str): The text you are converting
font_name (str): The font you are converting to,
Use the Image.font_list() function to get a list of them
color (str, Optional): The color of the text, Defaults to black
Returns
-------
:class:`FontImage`: The image of the font
"""
list_of_fonts = await HTTPClient().get_json("fontconvert/list")
list_of_fonts = list_of_fonts["Font_List"]
if font_name not in list_of_fonts:
url = "https://api.fusionsid.xyz/api/fontconvert/list"
return print(
f"Invalid font, go to {url} to get a list of them or use the font list function"
)
url = f"""fontconvert?text={text}&font={font_name}&color={color}"""
image_bytes = await HTTPClient().get_image(url)
return FontImage(image_bytes)
[docs] @classmethod
async def font_list(cls, print_all: bool = False) -> list:
"""
Prints a list of all the fonts that the api supports converting to
Parameters
----------
print_all (bool, Optional): setting this to true will print all the fonts in console
Returns
-------
:class:`List` : The list of fonts
"""
list_of_fonts = await HTTPClient().get_json("fontconvert/list")
list_of_fonts = list_of_fonts["Font_List"]
if print_all:
print("\n".join(list_of_fonts))
return list_of_fonts
[docs]class Meme(BaseImage):
"""
Meme
----
Attributes
----------
created_at (datetime) : The time when the class was made
"""
def __init__(self, image_bytes):
self.created_at = datetime.now()
super().__init__(image_bytes=image_bytes)
[docs]class GenerateMeme:
"""
Generate Memes
--------------
"""
[docs] @classmethod
async def abandon(cls, text: str) -> Meme:
"""
Generates the abandon meme
Parameters
----------
text (str) : The text you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"abandon?text={text}"
)
return Meme(image_bytes)
[docs] @classmethod
async def armor(cls, text: str) -> Meme:
"""
Generates the armor meme
Parameters
----------
text (str) : The text you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"armor?text={text}"
)
return Meme(image_bytes)
[docs] @classmethod
async def surprised(cls, text: str) -> Meme:
"""
Generates the surprised meme
Parameters
----------
text (str) : The text you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"surprised?text={text}"
)
return Meme(image_bytes)
[docs] @classmethod
async def violence(cls, text: str) -> Meme:
"""
Generates the violence meme
Parameters
----------
text (str) : The text you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"violence?text={text}"
)
return Meme(image_bytes)
[docs] @classmethod
async def change_my_mind(cls, text: str) -> Meme:
"""
Generates the change my mind meme
Parameters
----------
text (str) : The text you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"changemymind?text={text}"
)
return Meme(image_bytes)
[docs] @classmethod
async def balloon(cls, balloon_text: str, arrow_text: str) -> Meme:
"""
Generates the balloon meme
Parameters
----------
balloon_text (str) : The text you want to use for the ballon part of the meme
arrow_text (str) : The text you want to use for the arrow part of the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"balloon?text1={balloon_text}&text2={arrow_text}"
)
return Meme(image_bytes)
[docs] @classmethod
async def boo(cls, text_1: str, text_2: str) -> Meme:
"""
Generates the boo meme
Parameters
----------
text_1 (str) : The text you want to use for the first part of the meme
text_2 (str) : The text you want to use for the second part of the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"boo?text_1={text_1}&text_2={text_2}"
)
return Meme(image_bytes)
[docs] @classmethod
async def brain(cls, text_1: str, text_2: str, text_3 : str, text_4 : str) -> Meme:
"""
Generates the brain meme
Parameters
----------
text_1 (str): The text you want to use for the first box
text_2 (str): The text you want to use for the second box
text_3 (str): The text you want to use for the third box
text_4 (str): The text you want to use for the forth box
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"brain?text_1={text_1}&text_2={text_2}&text_3={text_3}&text_4={text_4}"
)
return Meme(image_bytes)
[docs] @classmethod
async def expanding_wwe(cls, text_1: str, text_2: str, text_3 : str, text_4 : str, text_5 : str) -> Meme:
"""
Generates the expanding wwe meme
Parameters
----------
text_1 (str): The text you want to use for the first box
text_2 (str): The text you want to use for the second box
text_3 (str): The text you want to use for the third box
text_4 (str): The text you want to use for the forth box
text_5 (str): The text you want to use for the fifth box
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(
f"expandingwwe?text_1={text_1}&text_2={text_2}&text_3={text_3}&text_4={text_4}&text_5={text_5}"
)
return Meme(image_bytes)
[docs] @classmethod
async def bongocat(cls, image_url: str) -> Meme:
"""
Generates the bongocat meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"bongocat?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def brazzers(cls, image_url: str) -> Meme:
"""
Generates the brazzers meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"brazzers?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def gun(cls, image_url: str) -> Meme:
"""
Generates the gun meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"gun?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def trash(cls, image_url: str) -> Meme:
"""
Generates the trash meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"trash?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def aborted(cls, image_url: str) -> Meme:
"""
Generates the aborted meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"aborted?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def affect(cls, image_url: str) -> Meme:
"""
Generates the aborted meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"affect?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def wanted(cls, image_url: str) -> Meme:
"""
Generates the wanted meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"wanted?image_url={image_url}")
return Meme(image_bytes)
[docs] @classmethod
async def delete(cls, image_url: str) -> Meme:
"""
Generates the delete meme
Parameters
----------
image_url (str) : The image you want to use for the meme
Returns
-------
Meme
"""
image_bytes = await HTTPClient().get_image(f"delete?image_url={image_url}")
return Meme(image_bytes)