__version__ = (1, 0, 7) # ©️ Dan Gazizullin, 2021-2023 # This file is a part of Hikka Userbot # Code is licensed under CC-BY-NC-ND 4.0 unless otherwise specified. # 🌐 https://github.com/hikariatama/Hikka # 🔑 https://creativecommons.org/licenses/by-nc-nd/4.0/ # + attribution # + non-commercial # + no-derivatives # You CANNOT edit this file without direct permission from the author. # You can redistribute this file without any changes. # meta pic: https://img.icons8.com/fluency/512/artificial-intelligence.png # meta banner: https://mods.hikariatama.ru/badges/anything.jpg # meta developer: @hikarimods # scope: hikka_only # scope: hikka_min 1.6.2 import asyncio import io import json import logging import random import re import time import requests from hikkatl.types import Message from .. import loader, utils logger = logging.getLogger(__name__) @loader.tds class Anything(loader.Module): """Draws ANYTHING using artificial intelligence. No API key required. 18+ only.""" strings = { "name": "Anything", "args": ( " Arguments are" " required" ), "fail": ( " Failed to generate" " image" ), "drawing": ( "🎨 Drawing {}" " picture(-s)" " using {}..." ), "ready": ( " Image" " generated!{}" ), "debug": ( "\n\nModel: {model}, CFG: {cfg}, Steps: {steps}, Prompt:" " {prompt}, Negative: {negative}, {took:.2f}s" ), } strings_ru = { "args": ( " Требуются" " аргументы" ), "fail": ( " Не удалось" " сгенерировать изображение" ), "drawing": ( "🎨 Рисую {}" " картинку(-ок) с помощью {}..." ), "ready": ( " Изображение" " сгенерировано!{}" ), "debug": ( "\n\nМодель: {model}, CFG: {cfg}, Шаги: {steps}, Запрос:" " {prompt}, Отрицательный запрос: {negative}, {took:.2f}s" ), } strings_es = { "args": ( " Se requieren" " argumentos" ), "fail": ( " No se" " pudo generar la imagen" ), "drawing": ( "🎨 Dibujando {}" " imagen(-es) usando {}..." ), "ready": ( " ¡Imagen" " generada!{}" ), "debug": ( "\n\nModelo: {model}, CFG: {cfg}, Pasos: {steps}, Solicitud:" " {prompt}, Solicitud negativa: {negative}, {took:.2f}s" ), } strings_it = { "args": ( " Sono richiesti" " argomenti" ), "fail": ( " Impossibile" " generare l'immagine" ), "drawing": ( "🎨 Disegno {}" " immagine(-i) usando {}..." ), "ready": ( " Immagine" " generata!{}" ), "debug": ( "\n\nModello: {model}, CFG: {cfg}, Passi: {steps}, Richiesta:" " {prompt}, Richiesta negativa: {negative}, {took:.2f}s" ), } strings_fr = { "args": ( " Des arguments" " sont requis" ), "fail": ( " Impossible" " de générer l'image" ), "drawing": ( "🎨 Dessin {}" " image(-s) en utilisant {}..." ), "ready": ( " Image générée!{}" ), "debug": ( "\n\nModèle: {model}, CFG: {cfg}, Étapes: {steps}, Demande:" " {prompt}, Demande négative: {negative}, {took:.2f}s" ), } strings_de = { "args": ( " Argumente" " werden benötigt" ), "fail": ( " Konnte das" " Bild nicht generieren" ), "drawing": ( "🎨 Zeichne {}" " Bild(-er) mit {}..." ), "ready": ( " Bild generiert!{}" ), "debug": ( "\n\nModell: {model}, CFG: {cfg}, Schritte: {steps}, Anfrage:" " {prompt}, Negative Anfrage: {negative}, {took:.2f}s" ), } strings_tr = { "args": ( " Gerekli" " argümanlar" ), "fail": ( " Görüntü" " oluşturulamadı" ), "drawing": ( "🎨 Çiziyorum {}" " görüntü(-leri) {} kullanarak..." ), "ready": ( " Görüntü" " oluşturuldu!{}" ), "debug": ( "\n\nModel: {model}, CFG: {cfg}, Adımlar: {steps}, Talep:" " {prompt}, Talep reddedildi: {negative}, {took:.2f}s" ), } strings_uz = { "args": ( " Talab qilinadi" ), "fail": ( " Rasm" " yaratib bo'lmadi" ), "drawing": ( "🎨 Rasm(-lar)" " chizilmoqda {} orqali..." ), "ready": ( " Rasm yaratildi!{}" ), "debug": ( "\n\nModel: {model}, CFG: {cfg}, Qadam: {steps}, Talab:" " {prompt}, Talab qilinmadi: {negative}, {took:.2f}s" ), } strings_kk = { "args": " Талап келеді", "fail": ( " Сурет" " жасап болмады" ), "drawing": ( "🎨 Сурет(-тер)" " жасалуда {} арқылы..." ), "ready": ( " Сурет жасалды!{}" ), "debug": ( "\n\nМодель: {model}, CFG: {cfg}, Қадам: {steps}, Сұрақ:" " {prompt}, Сұрақ жасалмады: {negative}, {took:.2f}s" ), } strings_tt = { "args": " Талап киләнә", "fail": ( " Рәсем ясап" " булмады" ), "drawing": ( "🎨 Рәсем(-ләр)" " ясалуда {} арҗылы..." ), "ready": ( " Рәсем ясалды!{}" ), "debug": ( "\n\nМодель: {model}, CFG: {cfg}, Адым: {steps}, Сорау:" " {prompt}, Сорау ясалмады: {negative}, {took:.2f}s" ), } def __init__(self): self.config = loader.ModuleConfig( loader.ConfigValue( "model", "auto", "Model to use - For anime characters use Anything-4.5", validator=loader.validators.Choice(["auto"]), ), loader.ConfigValue( "steps", 30, "Steps - The higher the number, the more the image will be detailed", validator=loader.validators.Integer(minimum=1, maximum=50), ), loader.ConfigValue( "cfg", 6, ( "CFG Scale Factor - The higher the number, the more the image will" " follow the prompt" ), validator=loader.validators.Integer(minimum=1, maximum=20), ), loader.ConfigValue( "sampler", "Euler a", "Sampler used", validator=loader.validators.Choice( ["Euler", "Euler a", "Heun", "DPM++ 2M Karras"] ), ), loader.ConfigValue( "debug", False, "Debug mode", validator=loader.validators.Boolean(), ), loader.ConfigValue( "default_negative", ( "(bad_prompt:0.8), multiple persons, multiple views, extra hands," " ugly, lowres, bad quality, blurry, disfigured, extra limbs," " missing limbs, deep fried, cheap art, missing fingers, out of" " frame, cropped, bad art, face hidden, text, speech bubble," " stretched, bad hands, error, extra digit, fewer digits, worst" " quality, low quality, normal quality, mutated, mutation," " deformed, severed, dismembered, corpse, pubic, poorly drawn," " (((deformed hands))), (((more than two hands))), (((deformed" " body))), ((((mutant))))" ), "Default negative prompt", ), loader.ConfigValue( "default_quantity", 1, "Default quantity of images to generate", validator=loader.validators.Integer(minimum=1, maximum=10), ), ) async def client_ready(self): self._models = json.loads( re.search( r"VUE_APP_AI_MODELS:'(.*?)',VUE_APP_STATS_STREAMS", ( await utils.run_sync( requests.get, "https://app.prodia.com" + re.search( ( r'defer="defer"' r' src="(\/js\/app\.[^.]*?\.js)"><\/script> [-n ] [-comp] [-neg ]""" if not (args := utils.get_args_raw(message)): await utils.answer(message, self.strings("args")) return negative = "" quantity = self.config["default_quantity"] if "-n " in args: quantity = int(args.split("-n ")[1].split()[0]) args = args.replace(f"-n {quantity}", "") if "-neg" in args: args, negative = args.split("-neg") comp = False if "-comp" in args: args = args.replace("-comp", "") comp = True args, negative = args.strip(), negative.strip() if not args: await utils.answer(message, self.strings("args")) return model = ( next( model for model in self._models.values() if model.startswith("anything-v4.5") ) if self.config["model"] == "auto" else self.config["model"] ) message = await utils.answer( message, self.strings("drawing").format( len(self._models) if comp else quantity, utils.escape_html("many" if comp else model), ), ) images = [] negative = negative or self.config["default_negative"] m = list(self._models.values()) start = time.time() async def create_job(): return ( await utils.run_sync( requests.get, "https://arran.fly.dev/generate", params={ "prompt": args, "model": m.pop() if comp else model, "negative_prompt": negative, "steps": self.config["steps"], "cfg": self.config["cfg"], "seed": random.randint(0, 1000000), "sampler": self.config["sampler"], "aspect_ratio": "square", }, ) ).json()["job"] async def create_job_ex(): try: return await create_job() except Exception as e: logger.error(e) await asyncio.sleep(5) return await create_job_ex() for _ in range(len(m) if comp else quantity): job = await create_job_ex() q = 0 while ( status := ( await utils.run_sync( requests.get, f"https://arran.fly.dev/job/{job}", ) ).json()["status"] ) != "succeeded" and q < 20: await asyncio.sleep(5) q += 1 if status != "succeeded": await utils.answer(message, self.strings("fail")) return image = io.BytesIO( ( await utils.run_sync( requests.get, f"https://images.prodia.xyz/{job}.png?download=1", stream=True, ) ).content ) image.name = "hahahahahhaah.png" images.append(image) await asyncio.sleep(10) await utils.answer_file( message, images, self.strings("ready").format( self.strings("debug").format( model=utils.escape_html("many" if comp else model), cfg=self.config["cfg"], steps=self.config["steps"], prompt=utils.escape_html(args), negative=utils.escape_html(negative), took=time.time() - start, ) if self.config["debug"] else "" ), )