You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
16 KiB
433 lines
16 KiB
import os, logging |
|
DEBUG = os.environ.get('DEBUG') |
|
logging.basicConfig( |
|
#filename='protovax.log', encoding='utf-8', |
|
format='[%(asctime)s] %(levelname)s %(module)s/%(funcName)s - %(message)s', |
|
level=logging.DEBUG if DEBUG else logging.INFO) |
|
|
|
import asyncio |
|
import requests |
|
import random |
|
import json |
|
import base64 |
|
import time |
|
import re |
|
import pytz |
|
from PIL import Image |
|
from datetime import datetime, timezone, timedelta |
|
from io import BytesIO |
|
from telethon import TelegramClient, events |
|
|
|
import secrets |
|
|
|
TANNERCOIN = -1001394158904 |
|
SANDBOX = -1001258001846 |
|
PROTOSPACE = -1001298858490 |
|
JASON = 172033414 |
|
TANNER = 79316791 |
|
TANNERBOT_MICROSCOPY = -1001886549266 |
|
|
|
TIMEZONE_TANNER = pytz.timezone('America/Edmonton') |
|
|
|
scope_subject = '' |
|
scope_zoom = '' |
|
|
|
client = TelegramClient('data/dreamer.session', secrets.TG_API_ID, secrets.TG_API_HASH) |
|
|
|
def snap_size(size): |
|
VALID_SIZES = [512, 576, 640, 704, 768, 832, 896, 960, 1024] |
|
for s in VALID_SIZES: |
|
if s >= size: |
|
return s |
|
|
|
def dreamer(prompt, negative_prompt='', steps=30, seed=1234, height=512, width=512): |
|
url = secrets.DREAM_API |
|
|
|
sd_settings = dict( |
|
prompt=prompt, |
|
negative_prompt=negative_prompt, |
|
steps=steps, |
|
seed=seed, |
|
height=snap_size(height), |
|
width=snap_size(width), |
|
save_images=True, |
|
) |
|
|
|
if width > 512 or height > 512: |
|
# highres fix |
|
sd_settings['enable_hr'] = True |
|
|
|
logging.info('Dreaming of: %s', prompt) |
|
|
|
try: |
|
res = requests.post(url, json=sd_settings, timeout=40) |
|
res.raise_for_status() |
|
res = res.json() |
|
return res |
|
except BaseException as e: |
|
logging.error('Problem dreaming {}: {} - {}'.format(url, e.__class__.__name__, str(e))) |
|
return None |
|
|
|
async def message_handler(event): |
|
global scope_subject, scope_zoom |
|
|
|
text = event.raw_text |
|
chat = event.chat_id |
|
|
|
sender = await event.get_sender() |
|
if not event.sender: |
|
return |
|
|
|
if event.message.fwd_from: |
|
return |
|
|
|
name = getattr(sender, 'first_name', None) |
|
if not name: |
|
return |
|
|
|
command = '' |
|
data = '' |
|
reply = '' |
|
reply_file = None |
|
|
|
if event.message.is_reply and 'plz type it' in text.lower(): |
|
text = '!transcribe' |
|
|
|
if text.startswith('! '): |
|
text = text[2:] |
|
elif text.startswith('!'): |
|
text = text[1:] |
|
else: |
|
return |
|
|
|
if ' ' in text: |
|
command = text.split(' ', 1)[0] |
|
data = text.split(' ', 1)[1] |
|
else: |
|
command = text |
|
|
|
command = command.lower() |
|
|
|
|
|
#!chat |
|
if command in ['chat', 'yarr', 'hwhat']: |
|
await client.send_read_acknowledge(event.chat, message=event.message, clear_mentions=True) |
|
return |
|
|
|
|
|
#!transacribe |
|
if command == 'transcribe': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
if not reply and not event.message.is_reply: |
|
reply = '> reply to the voice message you want transcribed' |
|
await event.reply(reply, link_preview=False) |
|
|
|
if not reply: |
|
reply_message = await event.get_reply_message() |
|
try: |
|
if 'audio' in reply_message.media.document.mime_type: |
|
audio = BytesIO() |
|
await client.download_media(reply_message, file=audio) |
|
audio.seek(0) |
|
else: |
|
raise |
|
except: |
|
reply = '> reply to a voice message' |
|
await event.reply(reply, link_preview=False) |
|
|
|
if not reply: |
|
try: |
|
url = secrets.WHISPER_API |
|
res = requests.post(url, files={'audio': audio.getvalue()}, timeout=30) |
|
res.raise_for_status() |
|
res = res.json() |
|
|
|
logging.info('Whisper response: %s', str(res)) |
|
|
|
reply = '> audio transcription: "{}"'.format(res['text'].strip()) |
|
await event.reply(reply, link_preview=False) |
|
except: |
|
reply = '> error' |
|
await event.reply(reply, link_preview=False) |
|
|
|
|
|
#!dumpster |
|
if command == 'dumpster': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
headers = {'Authorization': 'Basic YWRtaW46NXFoaDM0ZHFqMzRx'} |
|
try: |
|
res = requests.get('http://cameras.dns.t0.vc/image/Dump?&w=9999', headers=headers, timeout=4) |
|
res.raise_for_status() |
|
with open('tmp.jpg', 'wb') as f: |
|
f.write(res.content) |
|
|
|
await event.reply('', file='tmp.jpg', link_preview=False) |
|
except: |
|
reply = '> error' |
|
await event.reply(reply, link_preview=False) |
|
|
|
#!dumpstervid |
|
if command == 'dumpstervid': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
reply_file = await client.upload_file('dumpster.mp4') |
|
|
|
await event.reply('', file=reply_file, link_preview=False) |
|
|
|
|
|
#!garden |
|
if command == 'garden': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
headers = {'Authorization': 'Basic YWRtaW46NXFoaDM0ZHFqMzRx'} |
|
try: |
|
res = requests.get('http://cameras.dns.t0.vc/image/G-1?&w=9999', headers=headers, timeout=4) |
|
res.raise_for_status() |
|
with open('tmp.jpg', 'wb') as f: |
|
f.write(res.content) |
|
|
|
start = datetime(2023, 3, 5, 19, 0, tzinfo=TIMEZONE_TANNER) |
|
delta = datetime.now(pytz.utc) - start |
|
reply = '> secret garden #3 day {}'.format(delta.days + 1) |
|
reply += '\n> iceberg lettuce' |
|
await event.reply(reply, file='tmp.jpg', link_preview=False) |
|
except: |
|
reply = '> error' |
|
await event.reply(reply, link_preview=False) |
|
|
|
#!gardenvid |
|
if command == 'gardenvid': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
reply_file = await client.upload_file('garden.mp4') |
|
|
|
start = datetime(2023, 3, 5, 19, 0, tzinfo=TIMEZONE_TANNER) |
|
delta = datetime.now(pytz.utc) - start |
|
reply = '> secret garden #3 day {}'.format(delta.days + 1) |
|
reply += '\n> iceberg lettuce' |
|
await event.reply(reply, file=reply_file, link_preview=False) |
|
|
|
|
|
|
|
#!setscope |
|
if command == 'setscope' and data: |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
if not reply and sender.id != TANNER: |
|
reply = '> do !scope to look under the microscope' |
|
await event.reply(reply) |
|
|
|
if not reply: |
|
scope_subject = data |
|
|
|
for zoom in ['4x', '10x', '40x']: |
|
if zoom in scope_subject: |
|
scope_zoom = zoom |
|
scope_subject = scope_subject.replace(zoom, '') |
|
|
|
now = datetime.now(tz=timezone.utc) - timedelta(seconds=1) |
|
reply = '> ' + scope_subject |
|
file_name = 'frames/' + now.strftime('image%S.jpg') |
|
frame = Image.open(file_name) |
|
if scope_zoom: |
|
label = Image.open(scope_zoom + '_label.png') |
|
frame.paste(label, (0,0), label) |
|
frame.save('tmp.jpg') |
|
reply_msg = await event.reply(reply, file='tmp.jpg', link_preview=False) |
|
|
|
await reply_msg.forward_to(TANNERBOT_MICROSCOPY) |
|
|
|
#!scope |
|
if command == 'scope': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
if not reply: |
|
|
|
now = datetime.now(tz=timezone.utc) - timedelta(seconds=1) |
|
if scope_subject: |
|
reply = '> ' + scope_subject |
|
file_name = 'frames/' + now.strftime('image%S.jpg') |
|
frame = Image.open(file_name) |
|
if scope_zoom: |
|
label = Image.open(scope_zoom + '_label.png') |
|
frame.paste(label, (0,0), label) |
|
frame.save('tmp.jpg') |
|
reply_msg = await event.reply(reply, file='tmp.jpg', link_preview=False) |
|
|
|
|
|
#!dream |
|
if command == 'dream': |
|
logging.info('Chat: {:<14} | ID: {:<6} | User: {} {} | Command: {} | Data: {}'.format(chat, event.id, name, sender.id, command, data or 'None')) |
|
|
|
if not reply and chat == PROTOSPACE: |
|
reply = '> please join {} to dream'.format(secrets.PROTODREAM_URL) |
|
|
|
#if not reply and sender.id == JASON: |
|
# reply = '> no.' |
|
|
|
to_send = '' |
|
if not reply and data: |
|
to_send = data |
|
|
|
if not reply and not to_send and event.message.is_reply: |
|
reply_msg = await event.get_reply_message() |
|
to_send = reply_msg.raw_text |
|
|
|
if not reply and '> ' in to_send: |
|
reply = '> sounds like a bad !dream' |
|
|
|
if not reply and len(to_send) > 500: |
|
reply = '> impressive. very nice. let\'s see Paul Allen\'s prompt.' |
|
|
|
if not reply and not to_send: |
|
reply = '> usage: !dream [prompt] [options]' |
|
reply += '\n> or reply to someone with !dream' |
|
reply += '\n> default options:' |
|
reply += '\n> steps:30 (20-40)' |
|
reply += '\n> height:512 (512-1024)' |
|
reply += '\n> width:512 (512-1024)' |
|
reply += '\n> seed:number' |
|
reply += '\n> negative_prompt:text,words (no spaces)' |
|
reply += '\n> favourites: https://t.me/+UyMF3ArBe4pmYzQ5' |
|
|
|
if not reply: |
|
settings = { |
|
'steps': 30, |
|
'height': 512, |
|
'width': 512, |
|
'negative_prompt': 'text,words', |
|
'seed': random.randint(11111, 19999), |
|
} |
|
|
|
maximums = { |
|
'steps': 40, |
|
'height': 1024, |
|
'width': 1024, |
|
} |
|
|
|
minimums = { |
|
'steps': 20, |
|
'height': 512, |
|
'width': 512, |
|
} |
|
|
|
for match in re.findall('((\w+)[:=](\d+))', to_send): |
|
whole = match[0] |
|
setting = match[1] |
|
value = int(match[2]) |
|
|
|
to_send = to_send.replace(whole, '').replace(' ', ' ') |
|
|
|
if setting in maximums and value > maximums[setting]: |
|
reply = '> {} should be <= {}'.format(setting, maximums[setting]) |
|
break |
|
|
|
if setting in minimums and value < minimums[setting]: |
|
reply = '> {} should be >= {}'.format(setting, minimums[setting]) |
|
break |
|
|
|
if setting in settings: |
|
settings[setting] = value |
|
|
|
|
|
if not reply: |
|
try: |
|
to_send = to_send.replace('@', '') |
|
to_send = to_send.replace('!', '') |
|
to_send = to_send.strip() |
|
prompt = to_send |
|
|
|
if len(str(settings['seed'])) == 4: |
|
enhancements1 = [ |
|
', fantasy, intricate, elegant, digital painting, concept art, sharp focus, illustration by greg rutkowski, 4k', |
|
', synthwave style, artstation, detailed, award winning, dramatic lighting, miami vice, oil on canvas', |
|
', highly detailed painting by dustin nguyen, akihiko yoshida, greg tocchini, 4 k, trending on artstation, 8 k', |
|
', cinematic lighting, insanely detailed, intricate, artstation, cgsociety, painted by simon stalenhag, concept art, illustration, sharp focus', |
|
', photorealistic, highly detailed, illustration, lifelike, highly detailed, intricate, octane render, sharp focus, cyberpunk', |
|
', by ghibli, makoto shinkai, bright and transparent animation style, anime art wallpaper 4 k, trending on artstation', |
|
', painterly, sharp focus, illustration, art by lois royo', |
|
', in the style of gta cover art, by stephen bliss, trending on artstation, pixiv, 8 k', |
|
', d & d, fantasy concept art, octane render, 8 k', |
|
', peter mohrbacher, charlie bowater, artstation, craig mullins, cinematic, digital painting, deviantart, cinematic lighting, 4 k', |
|
', tristan eaton, victo ngai, maxfield parrish, artgerm, koons, ryden, intricated details', |
|
', by soul bass, kawase hasui, moebius and edward hopper, colorful flat surreal design, xray hd, 8 k', |
|
', manga cover art, detailed color portrait, artstation trending, 8 k', |
|
', a hacker hologram by penny patricia poppycock, pixabay contest winner, holography, irridescent, photoillustration, maximalist vaporwave - n 9', |
|
', breathtaking, epic, stunning, gorgeous, much detail, much wow, cgsociety, wlop, pixiv, behance, deviantart, masterpiece', |
|
', sharp focus, dynamic lighting, elegant, harmony, beauty, masterpiece, by roberto ferry, illustration, blue background', |
|
', ultradetailed environment, sharp focus, cinematic lighting, by alphonse maria mucha and kim jung gi', |
|
', concept art by jama jurabaev, cinematic shot, trending on artstation, high quality, brush stroke, hyperspace, vibrant colors', |
|
', hyper detailed, sharp focus, bokeh, unreal engine, ray tracing, cute, fantasy, sci fi, purple lights, tiny, small', |
|
', fancy, ultra detailed, brush strokes, digital painting, cinematic, yoshitaka amano, andy warhol, ultra realistic', |
|
', by tsuyoshi nagano, illustration, cinematic lighting, hyperdetailed, 8 k, symmetrical, frostbite 3 engine, cryengine, dof, trending on artstation, digital art, crepuscular ray', |
|
', retrowave, tonal separation, black background, neon, black, glitch, strong contrast, pinterest, trending on artstation', |
|
', basic background, krenz cushart, mucha, ghibli, by joaquin sorolla rhads leyendecker, by ohara koson', |
|
] |
|
|
|
if ',' not in prompt: |
|
prompt += enhancements1[settings['seed'] % len(enhancements1)] |
|
elif str(settings['seed'])[0] == '1': |
|
pass |
|
|
|
start = time.time() |
|
dream_res = dreamer(prompt, **settings) |
|
finish = time.time() |
|
|
|
b64_str = dream_res['images'][0] |
|
|
|
reply_file = base64.decodebytes(bytes(b64_str, 'utf-8')) |
|
|
|
latency = finish - start |
|
reply = '> generated "{}" for {} in {} s with seed:{} steps:{}'.format( |
|
to_send, |
|
name, |
|
str(latency)[:3], |
|
settings['seed'], |
|
settings['steps'] |
|
) |
|
|
|
except BaseException as e: |
|
logging.exception(e) |
|
reply = '> error' |
|
|
|
await event.reply(reply, file=reply_file, link_preview=False) |
|
|
|
|
|
@client.on(events.MessageEdited) |
|
async def message_edited(event): |
|
await message_handler(event) |
|
|
|
@client.on(events.NewMessage) |
|
async def new_message(event): |
|
await message_handler(event) |
|
|
|
@client.on(events.NewMessage) |
|
async def detect_cats(event): |
|
chat = event.chat_id |
|
|
|
if chat not in [PROTOSPACE, TANNERCOIN, SANDBOX]: |
|
return |
|
|
|
if not event.photo: |
|
return |
|
|
|
try: |
|
photo = BytesIO() |
|
await client.download_media(event.photo, photo) |
|
photo.seek(0) |
|
|
|
res = requests.post("http://192.168.0.105:32168/v1/vision/detection", files={'image': photo}).json() |
|
print(res) |
|
|
|
for prediction in res['predictions']: |
|
if prediction['label'] == 'cat' and prediction['confidence'] > 0.70: |
|
logging.info('Found a cat!') |
|
await event.reply('Cat.') |
|
return |
|
except: |
|
logging.info('Failed to try and find a cat.') |
|
|
|
client.start() |
|
client.run_until_disconnected()
|
|
|