Files
ivatar/ivatar/utils.py
2022-12-05 16:15:30 +01:00

184 lines
4.7 KiB
Python

# -*- coding: utf-8 -*-
"""
Simple module providing reusable random_string function
"""
import random
import string
from io import BytesIO
from PIL import Image, ImageDraw, ImageSequence
from urllib.parse import urlparse
def random_string(length=10):
"""
Return some random string with default length 10
"""
return "".join(
random.SystemRandom().choice(string.ascii_lowercase + string.digits)
for _ in range(length)
)
def openid_variations(openid):
"""
Return the various OpenID variations, ALWAYS in the same order:
- http w/ trailing slash
- http w/o trailing slash
- https w/ trailing slash
- https w/o trailing slash
"""
# Make the 'base' version: http w/ trailing slash
if openid.startswith("https://"):
openid = openid.replace("https://", "http://")
if openid[-1] != "/":
openid = openid + "/"
# http w/o trailing slash
var1 = openid[0:-1]
var2 = openid.replace("http://", "https://")
var3 = var2[0:-1]
return (openid, var1, var2, var3)
def mm_ng(
idhash, size=80, add_red=0, add_green=0, add_blue=0
): # pylint: disable=too-many-locals
"""
Return an MM (mystery man) image, based on a given hash
add some red, green or blue, if specified
"""
# Make sure the lightest bg color we paint is e0, else
# we do not see the MM any more
if idhash[0] == "f":
idhash = "e0"
# How large is the circle?
circlesize = size * 0.6
# Coordinates for the circle
start_x = int(size * 0.2)
end_x = start_x + circlesize
start_y = int(size * 0.05)
end_y = start_y + circlesize
# All are the same, based on the input hash
# this should always result in a "gray-ish" background
red = idhash[0:2]
green = idhash[0:2]
blue = idhash[0:2]
# Add some red (i/a) and make sure it's not over 255
red = hex(int(red, 16) + add_red).replace("0x", "")
if int(red, 16) > 255:
red = "ff"
if len(red) == 1:
red = "0%s" % red
# Add some green (i/a) and make sure it's not over 255
green = hex(int(green, 16) + add_green).replace("0x", "")
if int(green, 16) > 255:
green = "ff"
if len(green) == 1:
green = "0%s" % green
# Add some blue (i/a) and make sure it's not over 255
blue = hex(int(blue, 16) + add_blue).replace("0x", "")
if int(blue, 16) > 255:
blue = "ff"
if len(blue) == 1:
blue = "0%s" % blue
# Assemable the bg color "string" in webnotation. Eg. '#d3d3d3'
bg_color = "#" + red + green + blue
# Image
image = Image.new("RGB", (size, size))
draw = ImageDraw.Draw(image)
# Draw background
draw.rectangle(((0, 0), (size, size)), fill=bg_color)
# Draw MMs head
draw.ellipse((start_x, start_y, end_x, end_y), fill="white")
# Draw MMs 'body'
draw.polygon(
(
(start_x + circlesize / 2, size / 2.5),
(size * 0.15, size),
(size - size * 0.15, size),
),
fill="white",
)
return image
def is_trusted_url(url, url_filters):
"""
Check if a URL is valid and considered a trusted URL.
If the URL is malformed, returns False.
Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/events/UrlFilter
"""
(scheme, netloc, path, params, query, fragment) = urlparse(url)
for filter in url_filters:
if "schemes" in filter:
schemes = filter["schemes"]
if scheme not in schemes:
continue
if "host_equals" in filter:
host_equals = filter["host_equals"]
if netloc != host_equals:
continue
if "host_suffix" in filter:
host_suffix = filter["host_suffix"]
if not netloc.endswith(host_suffix):
continue
if "path_prefix" in filter:
path_prefix = filter["path_prefix"]
if not path.startswith(path_prefix):
continue
if "url_prefix" in filter:
url_prefix = filter["url_prefix"]
if not url.startswith(url_prefix):
continue
return True
return False
def resize_animated_gif(input_pil: Image, size: list) -> BytesIO:
def _thumbnail_frames(image):
for frame in ImageSequence.Iterator(image):
new_frame = frame.copy()
new_frame.thumbnail(size)
yield new_frame
frames = list(_thumbnail_frames(input_pil))
output = BytesIO()
output_image = frames[0]
output_image.save(
output,
format="gif",
save_all=True,
optimize=False,
append_images=frames[1:],
disposal=input_pil.disposal_method,
**input_pil.info,
)
return output