Coverage for ivatar/utils.py: 49%

85 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-26 00:11 +0000

1# -*- coding: utf-8 -*- 

2""" 

3Simple module providing reusable random_string function 

4""" 

5import random 

6import string 

7from io import BytesIO 

8from PIL import Image, ImageDraw, ImageSequence 

9from urllib.parse import urlparse 

10 

11 

12def random_string(length=10): 

13 """ 

14 Return some random string with default length 10 

15 """ 

16 return "".join( 

17 random.SystemRandom().choice(string.ascii_lowercase + string.digits) 

18 for _ in range(length) 

19 ) 

20 

21 

22def openid_variations(openid): 

23 """ 

24 Return the various OpenID variations, ALWAYS in the same order: 

25 - http w/ trailing slash 

26 - http w/o trailing slash 

27 - https w/ trailing slash 

28 - https w/o trailing slash 

29 """ 

30 

31 # Make the 'base' version: http w/ trailing slash 

32 if openid.startswith("https://"): 

33 openid = openid.replace("https://", "http://") 

34 if openid[-1] != "/": 

35 openid = openid + "/" 

36 

37 # http w/o trailing slash 

38 var1 = openid[0:-1] 

39 var2 = openid.replace("http://", "https://") 

40 var3 = var2[0:-1] 

41 return (openid, var1, var2, var3) 

42 

43 

44def mm_ng( 

45 idhash, size=80, add_red=0, add_green=0, add_blue=0 

46): # pylint: disable=too-many-locals 

47 """ 

48 Return an MM (mystery man) image, based on a given hash 

49 add some red, green or blue, if specified 

50 """ 

51 

52 # Make sure the lightest bg color we paint is e0, else 

53 # we do not see the MM any more 

54 if idhash[0] == "f": 

55 idhash = "e0" 

56 

57 # How large is the circle? 

58 circlesize = size * 0.6 

59 

60 # Coordinates for the circle 

61 start_x = int(size * 0.2) 

62 end_x = start_x + circlesize 

63 start_y = int(size * 0.05) 

64 end_y = start_y + circlesize 

65 

66 # All are the same, based on the input hash 

67 # this should always result in a "gray-ish" background 

68 red = idhash[0:2] 

69 green = idhash[0:2] 

70 blue = idhash[0:2] 

71 

72 # Add some red (i/a) and make sure it's not over 255 

73 red = hex(int(red, 16) + add_red).replace("0x", "") 

74 if int(red, 16) > 255: 

75 red = "ff" 

76 if len(red) == 1: 

77 red = "0%s" % red 

78 

79 # Add some green (i/a) and make sure it's not over 255 

80 green = hex(int(green, 16) + add_green).replace("0x", "") 

81 if int(green, 16) > 255: 

82 green = "ff" 

83 if len(green) == 1: 

84 green = "0%s" % green 

85 

86 # Add some blue (i/a) and make sure it's not over 255 

87 blue = hex(int(blue, 16) + add_blue).replace("0x", "") 

88 if int(blue, 16) > 255: 

89 blue = "ff" 

90 if len(blue) == 1: 

91 blue = "0%s" % blue 

92 

93 # Assemable the bg color "string" in webnotation. Eg. '#d3d3d3' 

94 bg_color = "#" + red + green + blue 

95 

96 # Image 

97 image = Image.new("RGB", (size, size)) 

98 draw = ImageDraw.Draw(image) 

99 

100 # Draw background 

101 draw.rectangle(((0, 0), (size, size)), fill=bg_color) 

102 

103 # Draw MMs head 

104 draw.ellipse((start_x, start_y, end_x, end_y), fill="white") 

105 

106 # Draw MMs 'body' 

107 draw.polygon( 

108 ( 

109 (start_x + circlesize / 2, size / 2.5), 

110 (size * 0.15, size), 

111 (size - size * 0.15, size), 

112 ), 

113 fill="white", 

114 ) 

115 

116 return image 

117 

118 

119def is_trusted_url(url, url_filters): 

120 """ 

121 Check if a URL is valid and considered a trusted URL. 

122 If the URL is malformed, returns False. 

123 

124 Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/events/UrlFilter 

125 """ 

126 (scheme, netloc, path, params, query, fragment) = urlparse(url) 

127 

128 for filter in url_filters: 

129 if "schemes" in filter: 

130 schemes = filter["schemes"] 

131 

132 if scheme not in schemes: 

133 continue 

134 

135 if "host_equals" in filter: 

136 host_equals = filter["host_equals"] 

137 

138 if netloc != host_equals: 

139 continue 

140 

141 if "host_suffix" in filter: 

142 host_suffix = filter["host_suffix"] 

143 

144 if not netloc.endswith(host_suffix): 

145 continue 

146 

147 if "path_prefix" in filter: 

148 path_prefix = filter["path_prefix"] 

149 

150 if not path.startswith(path_prefix): 

151 continue 

152 

153 if "url_prefix" in filter: 

154 url_prefix = filter["url_prefix"] 

155 

156 if not url.startswith(url_prefix): 

157 continue 

158 

159 return True 

160 

161 return False 

162 

163 

164def resize_animated_gif(input_pil: Image, size: list) -> BytesIO: 

165 def _thumbnail_frames(image): 

166 for frame in ImageSequence.Iterator(image): 

167 new_frame = frame.copy() 

168 new_frame.thumbnail(size) 

169 yield new_frame 

170 

171 frames = list(_thumbnail_frames(input_pil)) 

172 output = BytesIO() 

173 output_image = frames[0] 

174 output_image.save( 

175 output, 

176 format="gif", 

177 save_all=True, 

178 optimize=False, 

179 append_images=frames[1:], 

180 disposal=input_pil.disposal_method, 

181 **input_pil.info, 

182 ) 

183 return output