randydev commited on
Commit
25d6320
·
verified ·
1 Parent(s): a480cfd

Upload 2 files

Browse files
Files changed (2) hide show
  1. Akeno/utils/handler.py +11 -0
  2. Akeno/utils/images.py +310 -0
Akeno/utils/handler.py CHANGED
@@ -16,3 +16,14 @@ modules_help = ModuleHelp()
16
  scheduler_jobs = []
17
  scheduler = AsyncIOScheduler()
18
  bot_uptime = perf_counter()
 
 
 
 
 
 
 
 
 
 
 
 
16
  scheduler_jobs = []
17
  scheduler = AsyncIOScheduler()
18
  bot_uptime = perf_counter()
19
+
20
+ async def input_user(message: Message) -> str:
21
+ """Get the input from the user"""
22
+ if len(message.command) < 2:
23
+ output = ""
24
+ else:
25
+ try:
26
+ output = message.text.split(" ", 1)[1].strip() or ""
27
+ except IndexError:
28
+ output = ""
29
+ return output
Akeno/utils/images.py ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import calendar
2
+ import logging
3
+ import os
4
+ import random
5
+ import textwrap
6
+ import time
7
+
8
+ import httpx
9
+ from icrawler.builtin import BingImageCrawler
10
+ from PIL import Image, ImageDraw, ImageEnhance, ImageFont, ImageOps
11
+ from unidecode import unidecode
12
+
13
+ from Akeno.utils.formatter import format_text, limit_per_page
14
+
15
+ def convert_to_png(image: str) -> str:
16
+ output_img = f"png_{round(time.time())}.png"
17
+ img = Image.open(image)
18
+ img.save(output_img, "PNG")
19
+ img.close()
20
+ os.remove(image)
21
+ return output_img
22
+
23
+ def add_rounded_corners(img: Image.Image, radius: int = 80):
24
+ circle = Image.new("L", (radius * 2, radius * 2), 0)
25
+ draw = ImageDraw.Draw(circle)
26
+ draw.ellipse((0, 0, radius * 2, radius * 2), fill=255)
27
+ alpha = Image.new("L", img.size, 255)
28
+ w, h = img.size
29
+ alpha.paste(circle.crop((0, 0, radius, radius)), (0, 0))
30
+ alpha.paste(circle.crop((radius, 0, radius * 2, radius)), (w - radius, 0))
31
+ alpha.paste(circle.crop((0, radius, radius, radius * 2)), (0, h - radius))
32
+ alpha.paste(
33
+ circle.crop((radius, radius, radius * 2, radius * 2)), (w - radius, h - radius)
34
+ )
35
+ img.putalpha(alpha)
36
+ return img
37
+
38
+ def generate_alive_image(
39
+ username: str, profile_pic: str, del_img: bool, font_path: str
40
+ ) -> str:
41
+ if not profile_pic.endswith(".png"):
42
+ profile_pic = convert_to_png(profile_pic)
43
+ img = Image.open(profile_pic).convert("RGBA")
44
+ img_rotated = img.rotate(45, expand=True)
45
+ width, height = img_rotated.size
46
+ left = width / 2 - 480 / 2
47
+ top = height / 2 - 480 / 2
48
+ right = width / 2 + 480 / 2
49
+ bottom = height / 2 + 480 / 2
50
+ cropped_img = img_rotated.crop((left, top, right, bottom))
51
+ img_rotated = ImageOps.fit(
52
+ cropped_img, (480, 480), method=0, bleed=0.0, centering=(0.5, 0.5)
53
+ )
54
+ img_rounded = add_rounded_corners(img_rotated)
55
+ img = img_rounded.rotate(-45, expand=True)
56
+ background = Image.open("resources/images/alive.png").convert(
57
+ "RGBA"
58
+ )
59
+ background.paste(img, (383, 445), img)
60
+ draw = ImageDraw.Draw(background)
61
+ text = format_text(username[:25] + ("..." if len(username) > 25 else ""))
62
+ font_size = width // 15
63
+ font = ImageFont.truetype(font_path, font_size, encoding="utf-8")
64
+ text_length = draw.textlength(text, font)
65
+ position = ((background.width - text_length) / 2, background.height - 145)
66
+ draw.text(
67
+ position,
68
+ unidecode(text),
69
+ (255, 255, 255),
70
+ font,
71
+ )
72
+ output_img = f"alive_{int(time.time())}.png"
73
+ background.save(output_img, "PNG")
74
+ background.close()
75
+ if del_img:
76
+ os.remove(profile_pic)
77
+ return output_img
78
+
79
+ async def get_wallpapers(
80
+ access: str,
81
+ limit: int,
82
+ query: str = "",
83
+ isRandom: bool = False,
84
+ ) -> list[str]:
85
+ headers = {"Authorization": f"Client-ID {access}"}
86
+ if isRandom:
87
+ api = f"https://api.unsplash.com/photos/random?count={limit}"
88
+ response = httpx.get(api, headers=headers)
89
+ results = response.json()
90
+ urls = [i["urls"]["raw"] for i in results]
91
+ else:
92
+ api = f"https://api.unsplash.com/search/photos?query={query}&page={limit_per_page(limit)}"
93
+ response = httpx.get(api, headers=headers)
94
+ result = response.json()
95
+ urls = [i["urls"]["raw"] for i in result["results"]]
96
+ random.shuffle(urls)
97
+ return urls[:limit]
98
+
99
+ async def deep_fry(img: Image.Image) -> Image.Image:
100
+ colours = (
101
+ (random.randint(50, 200), random.randint(40, 170), random.randint(40, 190)),
102
+ (random.randint(190, 255), random.randint(170, 240), random.randint(180, 250)),
103
+ )
104
+ img = img.copy().convert("RGB")
105
+ img = img.convert("RGB")
106
+ width, height = img.width, img.height
107
+ img = img.resize(
108
+ (
109
+ int(width ** random.uniform(0.8, 0.9)),
110
+ int(height ** random.uniform(0.8, 0.9)),
111
+ ),
112
+ resample=Image.LANCZOS,
113
+ )
114
+ img = img.resize(
115
+ (
116
+ int(width ** random.uniform(0.85, 0.95)),
117
+ int(height ** random.uniform(0.85, 0.95)),
118
+ ),
119
+ resample=Image.BILINEAR,
120
+ )
121
+ img = img.resize(
122
+ (
123
+ int(width ** random.uniform(0.89, 0.98)),
124
+ int(height ** random.uniform(0.89, 0.98)),
125
+ ),
126
+ resample=Image.BICUBIC,
127
+ )
128
+ img = img.resize((width, height), resample=Image.BICUBIC)
129
+ img = ImageOps.posterize(img, random.randint(3, 7))
130
+ overlay = img.split()[0]
131
+ overlay = ImageEnhance.Contrast(overlay).enhance(random.uniform(1.0, 2.0))
132
+ overlay = ImageEnhance.Brightness(overlay).enhance(random.uniform(1.0, 2.0))
133
+ overlay = ImageOps.colorize(overlay, colours[0], colours[1])
134
+ img = Image.blend(img, overlay, random.uniform(0.1, 0.4))
135
+ img = ImageEnhance.Sharpness(img).enhance(random.randint(5, 300))
136
+ return img
137
+
138
+ async def make_logo(background: str, text: str, font_path: str) -> str:
139
+ if not background.endswith(".png"):
140
+ background = convert_to_png(background)
141
+ bg = Image.open(background).convert("RGBA")
142
+ bgWidth, bgHeight = bg.size
143
+ text = format_text(text)
144
+ font_size = bgWidth // len(text)
145
+ font = ImageFont.truetype(font_path, font_size, encoding="utf-8")
146
+ draw = ImageDraw.Draw(bg)
147
+ text_length = draw.textlength(text, font)
148
+ x = (bgWidth - text_length) // 2
149
+ y = (bgHeight - font_size) // 2
150
+
151
+ draw.text(
152
+ (x, y),
153
+ unidecode(text),
154
+ (255, 255, 255),
155
+ font,
156
+ stroke_fill=(0, 0, 0),
157
+ stroke_width=2,
158
+ )
159
+ output_img = f"logo_{int(time.time())}.png"
160
+ bg.save(output_img, "PNG")
161
+ bg.close()
162
+ os.remove(background)
163
+ return output_img
164
+
165
+ async def draw_meme(
166
+ image_path: str, upper_text: str = "", lower_text: str = ""
167
+ ) -> list[str]:
168
+ image = Image.open(image_path)
169
+ width, height = image.size
170
+ draw = ImageDraw.Draw(image)
171
+ font_size = int((30 / 500) * width)
172
+ font = ImageFont.truetype("resources/fonts/Montserrat.ttf", font_size)
173
+ curr_height, padding = 20, 5
174
+ for utext in textwrap.wrap(upper_text, 25):
175
+ upper_width = draw.textlength(utext, font=font)
176
+ draw.text(
177
+ ((width - upper_width) / 2, curr_height),
178
+ unidecode(utext),
179
+ (255, 255, 255),
180
+ font,
181
+ stroke_width=3,
182
+ stroke_fill=(0, 0, 0),
183
+ )
184
+ curr_height += font_size + padding
185
+ curr_height = height - font_size
186
+ for ltext in reversed(textwrap.wrap(lower_text, 25)):
187
+ lower_width = draw.textlength(ltext, font=font)
188
+ draw.text(
189
+ ((width - lower_width) / 2, curr_height - font_size),
190
+ ltext,
191
+ (255, 255, 255),
192
+ font,
193
+ stroke_width=3,
194
+ stroke_fill=(0, 0, 0),
195
+ )
196
+ curr_height -= font_size + padding
197
+ filename = f"meme_{int(time.time())}"
198
+ image.save(f"{filename}.png", "PNG", optimize=True)
199
+ image.save(f"{filename}.webp", "WEBP", optimize=True)
200
+ image.close()
201
+ return [f"{filename}.png", f"{filename}.webp"]
202
+
203
+ async def remove_bg(api_key: str, image: str) -> str:
204
+ response = httpx.post(
205
+ "https://api.remove.bg/v1.0/removebg",
206
+ files={"image_file": open(image, "rb")},
207
+ data={"size": "auto"},
208
+ headers={"X-Api-Key": api_key},
209
+ )
210
+ filename = f"removedbg_{int(time.time())}.png"
211
+ if response.is_success:
212
+ with open(filename, "wb") as f:
213
+ f.write(response.content)
214
+ else:
215
+ raise Exception(
216
+ f"RemoveBGError: [{response.status_code}] {response.content.decode('utf-8')}"
217
+ )
218
+ return filename
219
+
220
+ def create_gradient(
221
+ size: tuple[int, int],
222
+ color_start: tuple[int, int, int],
223
+ color_end: tuple[int, int, int],
224
+ ) -> Image.Image:
225
+ gradient = Image.new("RGB", (size))
226
+ draw = ImageDraw.Draw(gradient)
227
+ for x in range(size[0]):
228
+ r = int(color_start[0] + (color_end[0] - color_start[0]) * (x / size[0]))
229
+ g = int(color_start[1] + (color_end[1] - color_start[1]) * (x / size[0]))
230
+ b = int(color_start[2] + (color_end[2] - color_start[2]) * (x / size[0]))
231
+ draw.line([(x, 0), (x, size[1])], fill=(r, g, b))
232
+ return gradient
233
+
234
+ async def create_calendar(year: int, month: int) -> str:
235
+ cal = calendar.monthcalendar(year, month)
236
+ month_name = calendar.month_name[month]
237
+ calendar_image = create_gradient((500, 500), (140, 200, 250), (0, 150, 200))
238
+ draw = ImageDraw.Draw(calendar_image)
239
+ month_font = ImageFont.truetype("resources/fonts/Montserrat.ttf", 40)
240
+ month_x = (
241
+ calendar_image.width - draw.textlength(f"{month_name} {year}", month_font)
242
+ ) // 2
243
+ month_y = 30
244
+ draw.text(
245
+ (month_x, month_y),
246
+ f"{month_name} {year}",
247
+ (43, 255, 136),
248
+ month_font,
249
+ stroke_width=2,
250
+ stroke_fill=(255, 40, 40),
251
+ )
252
+ week_font = ImageFont.truetype("./Hellbot/resources/fonts/Montserrat.ttf", 23)
253
+ weekdays_text = " ".join([day[:3] for day in calendar.day_name])
254
+ textsize = draw.textlength(weekdays_text, week_font)
255
+ draw.text(
256
+ ((calendar_image.width - textsize) // 2, month_y + 80),
257
+ weekdays_text,
258
+ (150, 190, 200),
259
+ week_font,
260
+ stroke_width=2,
261
+ stroke_fill=(200, 150, 250),
262
+ )
263
+ scale_factor = 1.5
264
+ cell_size = 30
265
+ padding = 15
266
+ font = ImageFont.truetype("resources/fonts/Montserrat.ttf", 30)
267
+ for week_num, week in enumerate(cal):
268
+ for day_num, day in enumerate(week):
269
+ x = int(day_num * (cell_size + padding) * scale_factor)
270
+ y = int((week_num + 3) * (cell_size + padding) * scale_factor)
271
+ cell_width = int(cell_size * scale_factor)
272
+ cell_height = int(cell_size * scale_factor)
273
+ text_x = (
274
+ int(x + (cell_width - draw.textlength(str(day), font=font)) // 2)
275
+ + cell_size
276
+ )
277
+ text_y = (
278
+ int(y + (cell_height - draw.textlength(str(day), font=font)) // 2) - 55
279
+ )
280
+ if day != 0:
281
+ draw.text(
282
+ (text_x, text_y),
283
+ str(day),
284
+ (240, 200, 100),
285
+ font,
286
+ stroke_width=1,
287
+ stroke_fill=(0, 0, 0),
288
+ )
289
+ filename = f"calendar_{int(time.time())}.png"
290
+ calendar_image.save(filename, "PNG")
291
+ calendar_image.close()
292
+ return filename
293
+
294
+ async def create_thumbnail(photo: str, xy: tuple[int, int], file_size: int):
295
+ img = Image.open(photo)
296
+ img.thumbnail(xy)
297
+ size_in_bytes = file_size * 1024
298
+ quality = 90
299
+ while True:
300
+ img.save(photo, "JPEG", quality=quality, optimize=True)
301
+ if os.path.getsize(photo) <= size_in_bytes:
302
+ break
303
+ quality -= 5
304
+ return photo
305
+
306
+ async def download_images(query: str, limit: int) -> list[str]:
307
+ offset = random.randint(0, 20)
308
+ crawler = BingImageCrawler(log_level=logging.ERROR)
309
+ crawler.crawl(query, offset=offset, max_num=limit)
310
+ return [os.path.join("images", image) for image in os.listdir("images")]