__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 ""
),
)