def __upload_to_imgur(path, caption): log_debug('__upload started') if not isfile(path): log_warn('File to be uploaded not found') return # TODO: Convert to GIF and upload. if path[-3:] == 'mp4': remove(path) log_warn('Skipping mp4 upload') return log_debug('Authorizing imgur client') im = Imgur(environ.get('IMGUR_CLIENT_ID'), environ.get('IMGUR_CLIENT_KEY'), environ.get('IMGUR_ACCESS_TOKEN'), environ.get('IMGUR_REFRESH_TOKEN')) for _ in range(5): try: im.upload_image(path=abspath(path), title=caption, album=environ.get('IMGUR_ALBUM')) log_debug('Image successfully uploaded') break except Exception: log_warn('Upload failed, refreshing token') im.refresh_access_token() sleep(10) continue else: log_error('Upload failed, proceeding') log_debug('Deleting file') remove(path) return
async def send_image(message, img, filename, caption): bio = BytesIO() img.save(bio, 'PNG', optimize=True) bio.seek(0) file = File(bio, filename) try: await message.channel.send(caption, file=file) return True, 100 except HTTPException: log_warn('Discord HTTP Exception') log_warn('Trying Compressed versions') for quality in range(90, 69, -5): bio = BytesIO() img.save(bio, 'JPEG', optimize=True, quality=quality) bio.seek(0) file = File(bio, filename) try: await message.channel.send(caption, file=file) return False, quality except: log_error(f'Discord HTTP Exception ({quality}% quality)') return False, 0
def __get_image(url): for _ in range(5): try: return 1, Image.open(BytesIO(urlopen(url).read())) except (HTTPError, URLError): sleep(1) except (OSError, UnboundLocalError): log_error('OSError while retrieving image') return 0, None log_warn('Quitting loop while retrieving image') return 0, None
def __download_gif(url, filepath): for _ in range(5): try: urlretrieve(url, f'{filepath}.mp4') return 1 except (HTTPError, URLError): sleep(1) except (OSError, UnboundLocalError): log_error("OSError while retrieving gif") return 0 log_warn("Quitting loop while retrieving gif") return 0
async def fry_image(message, attachment, number_of_cycles, args, index): log_info('Starting Image Fry') try: data = await attachment.read() img = Image.open(BytesIO(data)) except Exception: log_error('Image download failed') return if img.mode != 'RGB': img = img.convert('RGB') # img.save(filepath) log_info('Image successfully downloaded') number_of_emojis = (3 if args['high-fat'] else 1 if args['low-fat'] else 0 if args['no-fat'] else 2) bulge_probability = (0.75 if args['heavy'] else 0 if args['light'] else 0.45) magnitude = 4 if args['deep'] else 1 if args['shallow'] else 2 caption = __get_caption(message.author.name, number_of_cycles, args) img = __fry(img, number_of_cycles, number_of_emojis, bulge_probability, not args['no-chilli'], args['vitamin-b']) log_info('Frying effects starting') fs = [__posterize, __sharpen, __increase_contrast, __colorize] for _ in range(number_of_cycles): shuffle(fs) for f in fs: img = f(img, magnitude) log_info('Frying effects applied') png, quality = await send_image(message, img, attachment.filename, caption) if not quality: return filename = '%s_%s_%s_%s.' % (message.guild.id if message.guild else 'NONE', message.author.name, message.id, index) + 'png' if png else 'jpg' filepath = path_join(bin_path, 'temp', filename) if png: img.save(filepath, 'PNG', optimize=True) else: img.save(filepath, 'JPEG', optimize=True, quality=quality) log_info('Image saved and replied') await __upload_to_imgur(filepath, caption) log_info('Image frying process completed')
def drake(update, top, bottom): meme_format = ('drake', 'drake', 'robbie', 'babushka')[randint(0, 3)] img_path = path_join(bin_path, 'resources/drake/', f'{meme_format}.png') bio = BytesIO() img = Image.open(img_path) draw = ImageDraw.Draw(img) # Top, bottom y coordinates y1, y2 = 129, 387 if not (__draw_text(draw, top, y1) and __draw_text(draw, bottom, y2)): log_error('Drake meme generation failed!') update.message.reply_photo(Files.drake, quote=True) return img.save(bio, 'PNG') bio.seek(0) update.message.reply_photo(bio, quote=True) log_command(update, 'DRAKE')
def fry_image(update, url, number_of_cycles, args): log_debug('Starting Image Fry') number_of_emojis = (3 if args['high-fat'] else 1 if args['low-fat'] else 0 if args['no-fat'] else 2) bulge_probability = (0.75 if args['heavy'] else 0 if args['light'] else 0.45) magnitude = (4 if args['deep'] else 1 if args['shallow'] else 2) bio = BytesIO() name = update.message.from_user.first_name bio.name = filename = '%s_%s_%s.png' % (update.message.chat_id, name, update.message.message_id) filepath = f'{bin_path}/temp/{filename}' caption = __get_caption(name, number_of_cycles, args) success, img = __get_image(url) if not success: log_error('Image download failed') return log_debug('Image successfully downloaded') img = __fry(img, number_of_cycles, number_of_emojis, bulge_probability, not args['no-chilli'], args['vitamin-b']) log_debug('Frying effects starting') fs = [__posterize, __sharpen, __increase_contrast, __colorize] for _ in range(number_of_cycles): shuffle(fs) for f in fs: img = f(img, magnitude) log_debug('Frying effects applied') img.save(bio, 'PNG') bio.seek(0) update.message.reply_photo(bio, caption=caption, quote=True) log_debug('Image saved and replied') img.save(filepath, 'PNG') __upload_to_imgur(filepath, caption) log_debug('Image frying process completed')
def fry_gif(update, url, number_of_cycles, args): log_debug('Starting GIF Fry') number_of_emojis = (1.5 if args['high-fat'] else 1 if args['low-fat'] else 0) bulge_probability = (0.3 if args['heavy'] else 0.15 if args['light'] else 0) magnitude = (4 if args['deep'] else 1 if args['shallow'] else 2) name = update.message.from_user.first_name filename = '%s_%s_%s' % (update.message.chat_id, name, update.message.message_id) filepath = f'{bin_path}/temp/{filename}' caption = __get_caption(name, number_of_cycles, args) output = f'{bin_path}/temp/out_{filename}.mp4' gif_bio = BytesIO() gif_bio.name = f'{filename}.gif' if not __download_gif(url, filepath): log_error('GIF download failed') return log_debug('GIF successfully downloaded') fvs = FileVideoStream(f'{filepath}.mp4').start() frame = fvs.read() height, width, _ = frame.shape try: fps = fvs.get(CAP_PROP_FPS) log_debug(f'Detected FPS: {fps}') except: log_warn('FPS Detection failed, defaulting to 30.') fps = 30 out = VideoWriter(output, VideoWriter_fourcc(*'mp4v'), fps, (width, height)) fs = [__posterize, __sharpen, __increase_contrast, __colorize] shuffle(fs) log_debug(f'Frying first frame') out.write( fry_frame(frame, number_of_cycles, fs, number_of_emojis, bulge_probability, magnitude, args)) i = 2 while fvs.more() or fvs.more(): try: log_debug(f'Frying frame {i}') temp = fry_frame(fvs.read(), number_of_cycles, fs, number_of_emojis, bulge_probability, magnitude, args) out.write(temp) log_debug(f'Frame {i} fried successfully') i += 1 except Exception: log_error(f'Encountered error while frying frame {i}') break log_debug(f'All frames fried.') fvs.stop() fvs.stream.release() out.release() update.message.reply_animation(open(output, 'rb'), caption=caption, quote=True) log_debug(f'GIF saved and replied') try: __upload_to_imgur(output, caption) except (Exception, BaseException) as e: print(e) try: remove(f'{filepath}.mp4') except: pass log_debug('Image frying process completed')