protovac/main.py

821 lines
30 KiB
Python
Raw Normal View History

2022-09-01 20:05:54 +00:00
#!/home/tanner/protovac/env/bin/python
2022-09-01 07:32:53 +00:00
2022-09-03 20:46:11 +00:00
import os, logging
DEBUG = os.environ.get('DEBUG')
logging.basicConfig(
2022-09-04 21:28:11 +00:00
filename='protovax.log',
2022-09-03 20:46:11 +00:00
format='[%(asctime)s] %(levelname)s %(module)s/%(funcName)s - %(message)s',
level=logging.DEBUG if DEBUG else logging.INFO)
logging.info('')
logging.info('Boot up')
2022-10-02 04:00:44 +00:00
os.system('stty -ixon')
2022-09-01 20:05:54 +00:00
import curses
2022-09-01 01:34:44 +00:00
import requests
2022-09-01 21:00:56 +00:00
import pytz
2022-09-01 21:55:55 +00:00
import re
2022-09-04 21:28:11 +00:00
import os
import time
2022-10-03 01:07:30 +00:00
import json
import textwrap
2022-09-01 21:00:56 +00:00
from datetime import datetime
2022-09-01 01:34:44 +00:00
2022-09-01 21:55:55 +00:00
try:
import secrets
wa_api_key = secrets.wa_api_key
except:
wa_api_key = None
2022-10-03 01:07:30 +00:00
try:
import secrets
character_ai_token = secrets.character_ai_token
except:
character_ai_token = None
2022-09-04 21:55:36 +00:00
KEY_ESCAPE = 27
KEY_ENTER = 10
2022-09-15 23:10:47 +00:00
KEY_SPACE = 32
2022-09-01 01:34:44 +00:00
2022-09-01 21:00:56 +00:00
TIMEZONE_CALGARY = pytz.timezone('America/Edmonton')
2022-09-04 21:28:11 +00:00
location = os.path.dirname(os.path.realpath(__file__))
2022-09-15 22:49:48 +00:00
2022-09-04 21:28:11 +00:00
with open(location + '/info.txt') as f:
2022-09-04 20:48:25 +00:00
PROTO_INFO = f.read()
2022-09-04 21:36:03 +00:00
for num, line in enumerate(PROTO_INFO.split('\n')):
try:
line.encode('ascii')
except UnicodeEncodeError:
print('non-ascii found in line:', num+1)
raise
2022-09-15 22:49:48 +00:00
with open(location + '/lastquestion.txt') as f:
LAST_QUESTION = f.read()
2022-09-01 21:00:56 +00:00
def format_date(datestr):
2022-09-18 20:29:15 +00:00
if not datestr: return 'None'
2022-09-01 21:00:56 +00:00
d = datetime.strptime(datestr, '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.UTC)
d = d.astimezone(TIMEZONE_CALGARY)
return d.strftime('%a %b %-d, %Y %-I:%M %p')
2022-09-01 20:05:54 +00:00
2022-09-01 01:34:44 +00:00
def sign_send(to_send):
try:
2022-09-03 20:46:11 +00:00
logging.info('Sending to sign: %s', to_send)
2022-09-01 01:34:44 +00:00
data = dict(sign=to_send, on_behalf_of='protovac')
r = requests.post('https://api.my.protospace.ca/stats/sign/', data=data, timeout=5)
r.raise_for_status()
return 'Success!'
2022-09-03 20:46:11 +00:00
except BaseException as e:
logging.exception(e)
2022-09-02 01:16:33 +00:00
return 'Error'
2022-09-01 01:34:44 +00:00
def fetch_stats():
try:
2022-09-03 20:46:11 +00:00
logging.info('Fetching status...')
2022-09-01 01:34:44 +00:00
r = requests.get('https://api.my.protospace.ca/stats/', timeout=5)
r.raise_for_status()
return r.json()
2022-09-03 20:46:11 +00:00
except BaseException as e:
logging.exception(e)
2022-09-02 01:16:33 +00:00
return 'Error'
2022-09-01 01:34:44 +00:00
2022-09-01 21:00:56 +00:00
def fetch_classes():
try:
2022-09-03 20:46:11 +00:00
logging.info('Fetching classes...')
2022-09-01 21:00:56 +00:00
r = requests.get('https://api.my.protospace.ca/sessions/', timeout=5)
r.raise_for_status()
return r.json()
2022-09-03 20:46:11 +00:00
except BaseException as e:
logging.exception(e)
2022-09-02 01:16:33 +00:00
return 'Error'
2022-09-01 21:00:56 +00:00
2022-09-01 23:15:27 +00:00
def fetch_protocoin():
try:
2022-09-03 20:46:11 +00:00
logging.info('Fetching protocoin...')
2022-09-02 01:06:38 +00:00
r = requests.get('https://api.my.protospace.ca/protocoin/transactions/', timeout=5)
2022-09-01 23:15:27 +00:00
r.raise_for_status()
return r.json()
2022-09-03 20:46:11 +00:00
except BaseException as e:
logging.exception(e)
2022-09-02 01:16:33 +00:00
return 'Error'
2022-09-01 23:15:27 +00:00
2022-10-03 01:07:30 +00:00
def message_protovac(message):
try:
2022-10-03 19:49:00 +00:00
logging.info('Message to Protovac: %s', message)
2022-10-03 01:07:30 +00:00
cookies = secrets.character_ai_cookies
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://beta.character.ai/chat?char=u77cm99PcKBRaczQcJEKLqD99JrT0wxK-RAOKHgFEYo',
'Authorization': 'Token ' + character_ai_token,
'Origin': 'https://beta.character.ai',
'DNT': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
}
json_data = {
'history_external_id': 'Mfdn894zdyDsWvQ3XVZurjW_CPE5SNmEsjPTUNR_nC8',
'character_external_id': 'u77cm99PcKBRaczQcJEKLqD99JrT0wxK-RAOKHgFEYo',
'text': message,
'tgt': 'internal_id:61666:c5e98052-6704-4725-838a-7432ab01fa5b',
'ranking_method': 'random',
'faux_chat': False,
'staging': False,
'model_server_address': None,
'override_prefix': None,
'override_rank': None,
'rank_candidates': None,
'filter_candidates': None,
'enable_tti': None,
'initial_timeout': None,
'insert_beginning': None,
'translate_candidates': None,
'stream_every_n_steps': 16,
'chunks_to_pad': 1,
'is_proactive': False,
}
r = requests.post(
'https://beta.character.ai/chat/streaming/',
cookies=cookies,
headers=headers,
json=json_data,
2022-10-03 01:26:53 +00:00
timeout=30,
2022-10-03 01:07:30 +00:00
)
r.raise_for_status()
2022-10-03 19:49:00 +00:00
reply = json.loads(r.text.split('\n')[-2])['replies'][0]['text'].replace('\n\n', ' ')
logging.info('Message reply: %s', reply)
return reply
2022-10-03 01:07:30 +00:00
except BaseException as e:
logging.exception(e)
return 'Error'
2022-10-03 01:26:53 +00:00
def print_messages(messages):
try:
with open('/dev/usb/lp0', 'w') as f:
for m in messages:
f.write(' ' + m + '\n')
f.write('\n')
except BaseException as e:
logging.exception(e)
2022-10-03 01:07:30 +00:00
2022-09-01 21:55:55 +00:00
if wa_api_key:
import wolframalpha
wa_client = wolframalpha.Client(wa_api_key)
def think_send(query):
result = ''
try:
2022-10-02 04:00:44 +00:00
res = wa_client.query(query, timeout=10)
2022-09-01 21:55:55 +00:00
except BaseException as e:
logging.error('Error hitting W|A API: {} - {}\n'.format(e.__class__.__name__, e))
return 'Network error'
if 'didyoumeans' in res:
try:
guess = res['didyoumeans']['didyoumean']['#text']
except TypeError:
guess = res['didyoumeans']['didyoumean'][0]['#text']
2022-09-02 04:56:26 +00:00
next_result = think_send(guess)
2022-09-01 21:55:55 +00:00
result += 'Confused, using \'' + guess + '\'\n' + next_result
elif 'pod' in res:
pods = res['pod'] if isinstance(res['pod'], list) else [res['pod']]
for pod in pods:
title = pod['@title']
subpods = pod['subpod'] if isinstance(pod['subpod'], list) else [pod['subpod']]
plaintexts = []
for subpod in subpods:
if subpod['plaintext']:
plaintexts.append(subpod['plaintext'])
plaintext = '; '.join(plaintexts)
if any([x in title.lower() for x in ['input', 'conversion', 'corresponding', 'comparison', 'interpretation']]):
pass
elif 'definition' in title.lower():
if plaintext[0] == '1':
definition = plaintext.split('\n')[0].split(' | ', 1)[1]
else:
definition = plaintext
result += 'Definition: ' + definition + '\n'
elif 'result' in title.lower():
if re.match(r'^\d+/\d+$', plaintext):
2022-09-02 04:56:26 +00:00
plaintext += '\n' + think_send(plaintext + '.0')
2022-09-01 21:55:55 +00:00
if 'base' in query.lower() and '_' in plaintext:
plaintext = '(Base conversion) "' + plaintext + '"'
if '(irreducible)' in plaintext and '/' in plaintext:
2022-09-02 04:56:26 +00:00
result = think_send(query + '.0')
2022-09-01 21:55:55 +00:00
break
else:
result += 'Result: ' + plaintext + '\n'
break
elif plaintext:
result += title + ': ' + plaintext + '\n'
break
else:
result = 'Error'
result = result.strip()
if len(result) > 500:
result = result[:500] + '... truncated.'
2022-09-09 22:16:31 +00:00
elif len(result) == 0:
2022-09-01 21:55:55 +00:00
result = 'Error'
2022-09-07 00:39:01 +00:00
result = result.replace('Wolfram|Alpha', 'Protovac')
2022-09-01 21:55:55 +00:00
result = result.replace('Stephen Wolfram', 'Tanner') # lol
result = result.replace('and his team', '')
2022-09-09 22:34:41 +00:00
for word in ['according to', 'asked', 'although', 'approximately']:
idx = result.lower().find('('+word)
if idx > 0:
result = result[:idx-1]
2022-09-07 00:39:01 +00:00
2022-09-09 22:16:31 +00:00
if result == 'Error':
result = 'INSUFFICIENT DATA FOR A MEANINGFUL ANSWER.'
2022-09-01 21:55:55 +00:00
return result
2022-09-01 01:34:44 +00:00
skip_input = False
current_screen = 'home'
2022-09-01 20:05:54 +00:00
prev_screen = current_screen
2022-09-01 01:34:44 +00:00
2022-09-01 20:05:54 +00:00
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(True)
curses.curs_set(0)
2022-09-01 01:34:44 +00:00
highlight_keys = False
highlight_debounce = time.time()
2022-09-01 01:34:44 +00:00
sign_to_send = ''
2022-10-03 01:07:30 +00:00
messages = ['']*15
message_to_send = ''
2022-09-01 21:55:55 +00:00
think_to_send = ''
think_result = ''
2022-09-01 01:34:44 +00:00
stats = {}
2022-09-01 21:00:56 +00:00
classes = {}
classes_start = 0
2022-09-01 23:15:27 +00:00
protocoin = {}
protocoin_line = 0
2022-09-15 22:49:48 +00:00
text_line = 0
2022-09-01 01:34:44 +00:00
2022-09-03 20:46:11 +00:00
logging.info('Starting main loop...')
2022-09-19 01:23:26 +00:00
last_key = time.time()
def ratelimit_key():
global last_key
2022-10-03 01:07:30 +00:00
if think_to_send or sign_to_send or message_to_send or time.time() > last_key + 1:
2022-09-19 01:23:26 +00:00
last_key = time.time()
return False
else:
return True
2022-09-01 01:34:44 +00:00
while True:
2022-09-14 21:03:39 +00:00
if current_screen != 'debug':
c = 0
2022-09-01 01:34:44 +00:00
if current_screen == 'home':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, ' _______ _______ ___ _________ ___ ____ ____ _ ______ ')
stdscr.addstr(1, 1, '|_ __ \|_ __ \ .\' `. | _ _ | .\' `.|_ _| |_ _|/ \ .\' ___ |')
stdscr.addstr(2, 1, ' | |__) | | |__) | / .-. \|_/ | | \_|/ .-. \ \ \ / / / _ \ / .\' \_|')
stdscr.addstr(3, 1, ' | ___/ | __ / | | | | | | | | | | \ \ / / / ___ \ | | ')
stdscr.addstr(4, 1, ' _| |_ _| | \ \_\ `-\' / _| |_ \ `-\' / \ \' /_/ / \ \_\ `.___.\'\\')
stdscr.addstr(5, 1, '|_____| |____| |___|`.___.\' |_____| `.___.\' \_/|____| |____|`.____ .\'')
2022-09-07 00:22:00 +00:00
stdscr.addstr(6, 1, '')
2022-09-02 04:56:26 +00:00
stdscr.addstr(7, 1, ' UNIVERSAL COMPUTER')
2022-09-07 00:22:00 +00:00
stdscr.addstr(8, 1, '')
2022-09-15 23:10:47 +00:00
menupos = 5
2022-10-03 01:07:30 +00:00
stdscr.addstr(7, menupos+4, '[I]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(7, menupos+8, 'Info')
stdscr.addstr(9, menupos+4, '[S]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(9, menupos+8, 'Stats')
stdscr.addstr(11, menupos+4, '[N]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(11, menupos+8, 'Sign')
stdscr.addstr(13, menupos+4, '[C]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(13, menupos+8, 'Classes')
stdscr.addstr(15, menupos+4, '[P]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(15, menupos+8, 'Protocoin')
if character_ai_token:
stdscr.addstr(17, menupos+4, '[M]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(17, menupos+8, 'Message')
2022-10-03 19:49:00 +00:00
stdscr.addstr(17, 4, 'NEW')
2022-09-01 21:55:55 +00:00
if wa_api_key:
2022-09-15 23:10:47 +00:00
stdscr.addstr(19, menupos+4, '[T]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(19, menupos+8, 'Think')
stdscr.addstr(21, menupos+4, '[A]', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(21, menupos+8, 'About')
stdscr.addstr(23, 1, ' Copyright (c) 1985 Bikeshed Computer Systems Ltd.')
stars = (8, 34)
stdscr.addstr(stars[0]+0 , stars[1], " . * - )- ")
2022-09-14 21:03:39 +00:00
stdscr.addstr(stars[0]+1 , stars[1], " . * o . * ")
stdscr.addstr(stars[0]+2 , stars[1], " | ")
stdscr.addstr(stars[0]+3 , stars[1], " . -O- ")
stdscr.addstr(stars[0]+4 , stars[1], ". | * . -0- ")
stdscr.addstr(stars[0]+5 , stars[1], " * o . ' * . o")
stdscr.addstr(stars[0]+6 , stars[1], " . . | * ")
stdscr.addstr(stars[0]+7 , stars[1], " * * -O- .")
stdscr.addstr(stars[0]+8 , stars[1], " . * | , ")
stdscr.addstr(stars[0]+9 , stars[1], " . o ")
stdscr.addstr(stars[0]+10, stars[1], " .---. ")
2022-09-15 22:49:48 +00:00
stdscr.addstr(stars[0]+11, stars[1], " = _/__[0]\_ . * o ' ")
2022-09-14 21:03:39 +00:00
stdscr.addstr(stars[0]+12, stars[1], " = = (_________) . ")
stdscr.addstr(stars[0]+13, stars[1], " . * ")
stdscr.addstr(stars[0]+14, stars[1], " * - ) - * ")
2022-09-01 20:05:54 +00:00
stdscr.clrtoeol()
stdscr.refresh()
2022-09-01 01:34:44 +00:00
elif current_screen == 'debug':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 22:18:06 +00:00
stdscr.addstr(2, 1, 'Debug Mode')
stdscr.addstr(3, 1, '==========')
stdscr.addstr(5, 1, str.format('Character pressed = {0}', c))
2022-09-01 20:05:54 +00:00
stdscr.clrtoeol()
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 20:05:54 +00:00
stdscr.clrtoeol()
stdscr.refresh()
2022-09-01 01:34:44 +00:00
elif current_screen == 'stats':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 21:00:56 +00:00
stdscr.addstr(2, 1, 'Protospace Stats')
stdscr.addstr(3, 1, '================')
2022-09-02 01:16:33 +00:00
if stats == 'Error':
stdscr.addstr(5, 1, 'Error. Go back and try again.')
elif stats:
2022-09-01 21:00:56 +00:00
stdscr.addstr(5 , 1, 'Next meeting: {}'.format(format_date(stats['next_meeting'])))
stdscr.addstr(7 , 1, 'Next clean: {}'.format(format_date(stats['next_clean'])))
stdscr.addstr(9, 1, 'Next class: {}'.format(stats['next_class']['name']))
stdscr.addstr(10, 1, ' {}'.format(format_date(stats['next_class']['datetime'])))
stdscr.addstr(12, 1, 'Last class: {}'.format(stats['prev_class']['name']))
stdscr.addstr(13, 1, ' {}'.format(format_date(stats['prev_class']['datetime'])))
stdscr.addstr(15, 1, 'Member count: {} Green: {} Paused / expired: {}'.format(
2022-09-01 01:34:44 +00:00
stats['member_count'],
stats['green_count'],
stats['paused_count'],
))
2022-09-01 21:00:56 +00:00
stdscr.addstr(17, 1, 'Card scans: {}'.format(stats['card_scans']))
2022-09-01 01:34:44 +00:00
else:
2022-09-01 21:00:56 +00:00
stdscr.addstr(5, 1, 'Loading...')
2022-09-01 01:34:44 +00:00
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 20:05:54 +00:00
stdscr.clrtoeol()
stdscr.refresh()
2022-09-01 01:34:44 +00:00
if not stats:
stats = fetch_stats()
2022-09-01 21:00:56 +00:00
stdscr.erase()
skip_input = True
elif current_screen == 'classes':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 21:00:56 +00:00
stdscr.addstr(2, 1, 'Protospace Classes')
2022-09-02 02:32:05 +00:00
stdscr.addstr(3, 1, '================== Instructor Cost Students')
2022-09-02 01:16:33 +00:00
if classes == 'Error':
stdscr.addstr(5, 1, 'Error. Go back and try again.')
elif classes:
2022-09-01 21:00:56 +00:00
classes_in_view = classes['results'][classes_start:6+classes_start]
lines = []
2022-09-02 02:32:05 +00:00
2022-09-01 21:00:56 +00:00
for session in classes_in_view:
lines.append(session['course_data']['name'])
2022-09-02 02:32:05 +00:00
lines.append('{:<30} {:<12} {:<7} {:<7}'.format(
2022-09-01 21:00:56 +00:00
format_date(session['datetime']),
'Protospace' if session['course_data']['id'] in [413, 317, 273] else session['instructor_name'],
'Free' if session['cost'] == '0.00' else '$' + session['cost'],
str(session['student_count']) + (' / ' + str(session['max_students']) if session['max_students'] else ''),
))
lines.append('')
offset = 5
for num, line in enumerate(lines):
stdscr.addstr(num + offset, 1, line)
else:
stdscr.addstr(5, 1, 'Loading...')
stdscr.addstr(23, 1, '[B] Back [J] Down [K] Up', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 21:00:56 +00:00
stdscr.clrtoeol()
stdscr.refresh()
if not classes:
classes = fetch_classes()
stdscr.erase()
2022-09-01 01:34:44 +00:00
skip_input = True
2022-09-15 22:49:48 +00:00
elif current_screen == 'asimov':
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
lines = LAST_QUESTION.split('\n')
offset = 2
for num, line in enumerate(lines[text_line:text_line+20]):
stdscr.addstr(num + offset, 1, line)
stdscr.addstr(23, 1, '[B] Back [J] Down [K] Up', curses.A_REVERSE if highlight_keys else 0)
2022-09-15 23:10:47 +00:00
stdscr.addstr(23, 67, 'Page {:>2} / {:>2}'.format((text_line // 19)+1, (len(lines) // 19)+1))
2022-09-15 22:49:48 +00:00
stdscr.clrtoeol()
stdscr.refresh()
2022-09-04 20:48:25 +00:00
elif current_screen == 'info':
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
lines = PROTO_INFO.split('\n')
offset = 2
2022-09-15 22:49:48 +00:00
for num, line in enumerate(lines[text_line:text_line+20]):
2022-09-04 20:48:25 +00:00
stdscr.addstr(num + offset, 1, line)
stdscr.addstr(23, 1, '[B] Back [J] Down [K] Up', curses.A_REVERSE if highlight_keys else 0)
2022-09-15 23:10:47 +00:00
stdscr.addstr(23, 67, 'Page {:>2} / {:>2}'.format((text_line // 19)+1, (len(lines) // 19)+1))
2022-09-04 20:48:25 +00:00
stdscr.clrtoeol()
stdscr.refresh()
2022-09-01 23:15:27 +00:00
elif current_screen == 'protocoin':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 23:15:27 +00:00
stdscr.addstr(2, 1, 'Protocoin')
stdscr.addstr(3, 1, '=========')
2022-09-02 01:16:33 +00:00
if protocoin == 'Error':
stdscr.addstr(5, 1, 'Error. Go back and try again.')
elif protocoin:
2022-09-01 23:15:27 +00:00
txs = protocoin['transactions']
lines = []
lines.append('Protocoin is used to buy things from Protospace\'s vending machines.')
lines.append('')
lines.append('Total in circulation: {}'.format(protocoin['total_protocoin']))
lines.append('')
lines.append('Transactions:')
lines.append('')
lines.append('ID Date Method Amount Category')
for tx in txs:
lines.append('{} {} {:<11} {:<6} {:<11}'.format(
tx['id'],
tx['date'],
tx['account_type'],
tx['protocoin'],
'Transfer' if tx['category'] == 'Other' else tx['category'],
))
offset = 5
for num, line in enumerate(lines[protocoin_line:protocoin_line+17]):
stdscr.addstr(num + offset, 1, line)
else:
stdscr.addstr(5, 1, 'Loading...')
stdscr.addstr(23, 1, '[B] Back [J] Down [K] Up', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 23:15:27 +00:00
stdscr.clrtoeol()
stdscr.refresh()
if not protocoin:
protocoin = fetch_protocoin()
stdscr.erase()
skip_input = True
2022-09-01 01:34:44 +00:00
elif current_screen == 'sign':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 21:00:56 +00:00
stdscr.addstr(2, 1, 'Protospace Sign')
stdscr.addstr(3, 1, '===============')
stdscr.addstr(5, 1, 'Send a message to the sign in the welcome room and classroom.')
2022-09-02 02:32:05 +00:00
stdscr.addstr(6, 1, 'After sending, turn your head right and wait 5 seconds.')
2022-09-01 01:34:44 +00:00
if sign_to_send:
2022-09-01 21:00:56 +00:00
stdscr.addstr(8, 4, sign_to_send)
2022-09-01 20:05:54 +00:00
stdscr.clrtoeol()
2022-09-15 23:10:47 +00:00
stdscr.addstr(23, 1, '[RETURN] Send [ESC] Cancel')
2022-09-01 01:34:44 +00:00
else:
2022-09-09 23:55:04 +00:00
stdscr.addstr(8, 4, '[E] Edit message', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 20:05:54 +00:00
2022-10-03 01:07:30 +00:00
stdscr.clrtoeol()
stdscr.refresh()
elif current_screen == 'message':
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
stdscr.addstr(2, 1, 'Message Protovac')
stdscr.addstr(3, 1, '===============')
stdscr.addstr(5, 1, 'Send a message to Protovac, the universal computer.')
offset = 7
for num, line in enumerate(messages[-13:]):
stdscr.addstr(num + offset, 1, line)
if message_to_send:
stdscr.addstr(21, 21, message_to_send)
stdscr.clrtoeol()
stdscr.addstr(23, 1, '[RETURN] Send [ESC] Cancel')
else:
stdscr.addstr(21, 21, '[E] Edit message', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 20:05:54 +00:00
stdscr.clrtoeol()
stdscr.refresh()
2022-09-01 21:55:55 +00:00
elif current_screen == 'think':
stdscr.erase()
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 21:55:55 +00:00
stdscr.addstr(2, 1, 'Think')
stdscr.addstr(3, 1, '=====')
stdscr.addstr(5, 1, 'Give Protovac something to think about.')
if think_to_send:
stdscr.addstr(7, 4, think_to_send)
stdscr.clrtoeol()
2022-09-15 23:10:47 +00:00
stdscr.addstr(23, 1, '[RETURN] Send [ESC] Cancel')
2022-09-01 21:55:55 +00:00
else:
2022-09-09 23:55:04 +00:00
stdscr.addstr(7, 4, '[E] Edit prompt', curses.A_REVERSE if highlight_keys else 0)
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
2022-09-01 21:55:55 +00:00
if think_result:
2022-09-07 01:20:54 +00:00
for _ in range(100):
try:
stdscr.addstr(9, 4, think_result)
break
except:
think_result = think_result[:-5]
stdscr.addstr(22, 1, '')
stdscr.clrtoeol()
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
2022-09-07 01:20:54 +00:00
stdscr.clrtoeol()
2022-09-01 21:55:55 +00:00
if not think_result and not think_to_send:
stdscr.addstr(9, 1, 'Examples:')
stdscr.addstr(11, 4, '42 + 69')
stdscr.addstr(12, 4, '55 kg to lbs')
stdscr.addstr(13, 4, 'density of lead')
stdscr.addstr(14, 4, 'if x = 4, what is 3x + 50?')
stdscr.addstr(15, 4, 'force m=150g, a=50cm/s^2')
stdscr.addstr(16, 4, 'boiling point of benzene at 550 torr')
stdscr.addstr(17, 4, 'goats with highest milk yield')
stdscr.addstr(18, 4, 'how long did the Aztec empire last?')
stdscr.refresh()
2022-09-01 22:18:06 +00:00
elif current_screen == 'about':
2022-09-02 01:06:38 +00:00
stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
2022-09-01 22:18:06 +00:00
stdscr.addstr(2, 1, 'About')
stdscr.addstr(3, 1, '=====')
stdscr.addstr(5, 1, 'Protovac is a universal mainframe computer accessible by terminal.')
stdscr.addstr(7, 1, 'License')
stdscr.addstr(8, 1, '-------')
stdscr.addstr(10, 1, 'This program is free and open-source software licensed under the MIT License.')
stdscr.addstr(11, 1, 'Please see the LICENSE file for details. This means you have the right to')
stdscr.addstr(12, 1, 'study, change, and distribute the software and source code to anyone and for')
stdscr.addstr(13, 1, 'any purpose.')
stdscr.addstr(15, 1, 'Source code: github.com/Protospace/protovac')
stdscr.addstr(17, 1, 'Acknowledgements')
stdscr.addstr(18, 1, '----------------')
stdscr.addstr(20, 1, 'Thanks to Peter for lending the Morrow MTD-60 terminal and Jamie for the Pi.')
stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if highlight_keys else 0)
stdscr.refresh()
2022-09-01 01:34:44 +00:00
2022-09-01 20:05:54 +00:00
stdscr.move(23, 79)
2022-09-01 01:34:44 +00:00
if highlight_keys:
time.sleep(0.5)
highlight_keys = False
continue
2022-09-01 01:34:44 +00:00
if skip_input:
skip_input = False
else:
2022-09-19 01:23:26 +00:00
curses.flushinp()
if ratelimit_key(): continue
2022-09-01 01:34:44 +00:00
try:
2022-09-01 20:05:54 +00:00
c = stdscr.getch()
2022-09-01 01:34:44 +00:00
except KeyboardInterrupt:
2022-09-02 02:32:05 +00:00
pass
#break
2022-09-01 01:34:44 +00:00
2022-09-02 02:32:05 +00:00
try:
button = chr(c).lower()
except:
button = None
2022-09-01 01:34:44 +00:00
def try_highlight():
global c, highlight_debounce, highlight_keys
if c and time.time() - highlight_debounce > 0.6:
highlight_debounce = time.time()
highlight_keys = True
2022-09-19 01:23:26 +00:00
curses.beep()
2022-09-01 01:34:44 +00:00
if current_screen == 'home':
2022-09-02 01:06:38 +00:00
if button == 's':
2022-09-01 01:34:44 +00:00
current_screen = 'stats'
2022-09-04 20:48:25 +00:00
elif button == 'i':
current_screen = 'info'
2022-09-15 22:49:48 +00:00
elif button == '0':
current_screen = 'asimov'
2022-09-02 01:06:38 +00:00
elif button == 'n':
2022-09-01 01:34:44 +00:00
current_screen = 'sign'
2022-09-01 21:00:56 +00:00
elif button == 'c':
current_screen = 'classes'
2022-10-03 01:07:30 +00:00
elif button == 'm':
current_screen = 'message'
messages = ['']*15
2022-09-02 01:06:38 +00:00
elif button == 't' and wa_api_key:
2022-09-01 21:55:55 +00:00
current_screen = 'think'
2022-09-01 01:34:44 +00:00
elif button == 'd':
current_screen = 'debug'
2022-09-01 22:18:06 +00:00
elif button == 'a':
current_screen = 'about'
2022-09-01 23:15:27 +00:00
elif button == 'p':
current_screen = 'protocoin'
else:
try_highlight()
2022-09-01 21:55:55 +00:00
elif current_screen == 'debug':
2022-09-05 20:01:26 +00:00
if button == 'b' or c == KEY_ESCAPE:
2022-09-01 21:55:55 +00:00
current_screen = 'home'
2022-09-02 02:32:05 +00:00
if button == 'x':
break
else:
try_highlight()
2022-09-01 01:34:44 +00:00
elif current_screen == 'stats':
2022-09-05 20:01:26 +00:00
if button == 'b' or c == KEY_ESCAPE:
2022-09-01 01:34:44 +00:00
current_screen = 'home'
stats = {}
else:
try_highlight()
2022-09-01 22:18:06 +00:00
elif current_screen == 'about':
2022-09-05 20:01:26 +00:00
if button == 'b' or c == KEY_ESCAPE:
2022-09-01 22:18:06 +00:00
current_screen = 'home'
else:
try_highlight()
2022-09-01 21:00:56 +00:00
elif current_screen == 'classes':
2022-09-05 20:01:26 +00:00
if button == 'b' or c == KEY_ESCAPE:
2022-09-01 21:00:56 +00:00
current_screen = 'home'
classes = {}
classes_start = 0
2022-09-15 23:10:47 +00:00
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
2022-09-01 21:00:56 +00:00
classes_start += 1
stdscr.erase()
2022-09-04 21:28:11 +00:00
elif button == 'k' or c == curses.KEY_UP:
2022-09-01 21:00:56 +00:00
if classes_start > 0:
classes_start -= 1
stdscr.erase()
else:
try_highlight()
2022-09-15 22:49:48 +00:00
elif current_screen == 'asimov':
if button == 'b' or c == KEY_ESCAPE:
current_screen = 'home'
protocoin = {}
text_line = 0
2022-09-15 23:10:47 +00:00
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
if text_line+19 < len(lines):
text_line += 19
stdscr.erase()
2022-09-15 22:49:48 +00:00
elif button == 'k' or c == curses.KEY_UP:
if text_line > 0:
text_line -= 19
stdscr.erase()
else:
try_highlight()
2022-09-04 20:48:25 +00:00
elif current_screen == 'info':
2022-09-05 20:01:26 +00:00
if button == 'b' or c == KEY_ESCAPE:
2022-09-04 20:48:25 +00:00
current_screen = 'home'
protocoin = {}
2022-09-15 22:49:48 +00:00
text_line = 0
2022-09-15 23:10:47 +00:00
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
if text_line+19 < len(lines):
text_line += 19
stdscr.erase()
2022-09-04 21:28:11 +00:00
elif button == 'k' or c == curses.KEY_UP:
2022-09-15 22:49:48 +00:00
if text_line > 0:
text_line -= 19
2022-09-04 20:48:25 +00:00
stdscr.erase()
else:
try_highlight()
2022-09-01 23:15:27 +00:00
elif current_screen == 'protocoin':
2022-09-05 20:01:26 +00:00
if button == 'b' or c == KEY_ESCAPE:
2022-09-01 23:15:27 +00:00
current_screen = 'home'
protocoin = {}
protocoin_line = 0
2022-09-15 23:10:47 +00:00
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
2022-09-01 23:15:27 +00:00
protocoin_line += 1
stdscr.erase()
2022-09-04 21:28:11 +00:00
elif button == 'k' or c == curses.KEY_UP:
2022-09-01 23:15:27 +00:00
if protocoin_line > 0:
protocoin_line -= 1
stdscr.erase()
else:
try_highlight()
2022-09-01 01:34:44 +00:00
elif current_screen == 'sign':
if sign_to_send:
2022-09-04 21:28:11 +00:00
if c == curses.KEY_BACKSPACE:
2022-09-01 01:34:44 +00:00
sign_to_send = sign_to_send[:-2] + '_'
2022-09-04 21:55:36 +00:00
elif c == KEY_ESCAPE:
2022-09-01 01:34:44 +00:00
sign_to_send = ''
2022-09-01 21:00:56 +00:00
stdscr.erase()
2022-09-04 21:55:36 +00:00
elif c == KEY_ENTER:
2022-09-01 01:34:44 +00:00
if len(sign_to_send) > 1:
2022-09-01 20:05:54 +00:00
stdscr.addstr(15, 4, 'Sending...')
stdscr.refresh()
2022-09-01 01:34:44 +00:00
sign_send(sign_to_send[:-1])
2022-09-01 20:05:54 +00:00
stdscr.erase()
2022-09-01 01:34:44 +00:00
sign_to_send = ''
else:
if c < 127 and c > 31:
sign_to_send = sign_to_send[:-1] + chr(c) + '_'
2022-09-05 20:01:26 +00:00
elif button == 'b' or c == KEY_ESCAPE:
2022-09-01 01:34:44 +00:00
current_screen = 'home'
elif button == 'e':
sign_to_send = '_'
else:
try_highlight()
2022-10-03 01:07:30 +00:00
elif current_screen == 'message':
if message_to_send:
if c == curses.KEY_BACKSPACE:
message_to_send = message_to_send[:-2] + '_'
elif c == KEY_ESCAPE:
message_to_send = ''
stdscr.erase()
elif c == KEY_ENTER:
if len(message_to_send) > 1:
stdscr.addstr(22, 21, 'Sending...')
stdscr.refresh()
message_to_send = message_to_send[:-1]
lines = textwrap.wrap(
message_to_send,
width=80,
initial_indent=' '*20,
subsequent_indent=' '*20,
)
2022-10-03 01:26:53 +00:00
print_messages(lines)
2022-10-03 01:07:30 +00:00
messages.append('')
messages.extend(lines)
reply = message_protovac(message_to_send)
lines = textwrap.wrap(
reply,
width=60,
)
2022-10-03 01:26:53 +00:00
print_messages(lines)
2022-10-03 01:07:30 +00:00
messages.append('')
messages.extend(lines)
stdscr.erase()
2022-10-03 19:49:00 +00:00
message_to_send = '_'
2022-10-03 01:07:30 +00:00
else:
if c < 127 and c > 31:
message_to_send = message_to_send[:-1] + chr(c) + '_'
elif button == 'b' or c == KEY_ESCAPE:
current_screen = 'home'
elif button == 'e':
message_to_send = '_'
else:
try_highlight()
2022-09-01 21:55:55 +00:00
elif current_screen == 'think':
if think_to_send:
2022-09-04 21:28:11 +00:00
if c == curses.KEY_BACKSPACE:
2022-09-01 21:55:55 +00:00
think_to_send = think_to_send[:-2] + '_'
2022-09-04 21:55:36 +00:00
elif c == KEY_ESCAPE:
2022-09-01 21:55:55 +00:00
think_to_send = ''
stdscr.erase()
2022-09-04 21:55:36 +00:00
elif c == KEY_ENTER:
2022-09-01 21:55:55 +00:00
if len(think_to_send) > 1:
stdscr.addstr(9, 4, 'Thinking...')
stdscr.clrtoeol()
stdscr.refresh()
2022-09-03 20:46:11 +00:00
query = think_to_send[:-1]
logging.info('Thinking about: %s', query)
think_result = think_send(query)
logging.info('Think result: %s', think_result)
2022-09-01 21:55:55 +00:00
stdscr.erase()
think_to_send = ''
else:
if c < 127 and c > 31:
think_to_send = think_to_send[:-1] + chr(c) + '_'
2022-09-05 20:01:26 +00:00
elif button == 'b' or c == KEY_ESCAPE:
2022-09-01 21:55:55 +00:00
current_screen = 'home'
think_result = ''
elif button == 'e':
think_to_send = '_'
else:
try_highlight()
2022-09-01 01:34:44 +00:00
2022-09-01 20:05:54 +00:00
if current_screen != prev_screen:
prev_screen = current_screen
2022-09-03 20:46:11 +00:00
logging.info('Switching to screen: %s', current_screen)
2022-09-01 20:05:54 +00:00
stdscr.erase()
curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.endwin()
2022-09-04 06:20:42 +00:00
logging.info('Exiting.')