qcs-python/main.py

148 lines
4.9 KiB
Python
Raw Normal View History

2023-04-30 22:13:02 +00:00
2023-05-01 00:46:08 +00:00
import os
2023-04-30 22:13:02 +00:00
import json
import logging
2023-05-01 00:46:08 +00:00
import toml
2023-05-01 01:58:02 +00:00
import getpass
2023-05-01 04:34:56 +00:00
import textwrap
import readchar
from colorama import Fore, Back, Style, init as colorama_init
2023-05-01 01:58:02 +00:00
import contentapi
2023-05-01 01:03:03 +00:00
import myutils
2023-05-01 00:46:08 +00:00
CONFIGFILE="config.toml"
2023-04-30 22:13:02 +00:00
# The entire config object with all defaults
config = {
2023-04-30 22:49:30 +00:00
"api" : "https://oboy.smilebasicsource.com/api",
2023-05-01 01:12:14 +00:00
"default_loglevel" : "WARNING",
2023-05-01 04:34:56 +00:00
"default_room" : 0, # Zero means it will ask you for a room
2023-05-01 01:03:03 +00:00
"expire_seconds" : 31536000, # 365 days in seconds, expiration for token
2023-05-01 04:34:56 +00:00
"appear_in_global" : False,
2023-04-30 22:49:30 +00:00
"tokenfile" : ".qcstoken"
2023-04-30 22:13:02 +00:00
}
2023-05-01 04:34:56 +00:00
class WebsocketContext:
def __init__(self, api_context, user_info):
self.api_context = api_context
self.current_room = 0
self.user_info = user_info
self.connected = False # Should this be a var? IDK
self.pause
2023-04-30 22:13:02 +00:00
def main():
print("Program start")
2023-05-01 04:34:56 +00:00
colorama_init() # colorama init
2023-05-01 00:46:08 +00:00
load_or_create_global_config()
2023-05-01 01:12:14 +00:00
logging.info("Config: " + json.dumps(config, indent = 2))
2023-04-30 22:57:50 +00:00
context = contentapi.ApiContext(config["api"], logging)
2023-05-01 01:58:02 +00:00
logging.info("Testing connection to API at " + config["api"])
logging.debug(json.dumps(context.api_status(), indent = 2))
authenticate(config, context)
2023-05-01 04:34:56 +00:00
ws_context = WebsocketContext(context, context.user_me())
ws_context.current_room = config["default_room"]
# - Connect to websocket, be ready to receive junk
# - Alert user they're not connected to any room, maybe have a status line that lists controls + room
# - Enter input loop, but check room number on "input" mode, don't let messages send in room 0
# - h to help
# - s to search rooms, enter #1234 to connect directly, empty string to quit
# - g to list global users
# - u to list users in room
# - i to input
# - q to quit entirely
printstatus = True
# The infinite input loop! Or something!
while True:
if printstatus:
print_statusline(ws_context)
printstatus = True
key = readchar.readkey()
if key == "h":
print("not yet")
elif key == "s":
print("not yet")
elif key == "g":
print("not yet")
elif key == "u":
print("not yet")
elif key == "i":
print("not yet")
elif key == "q":
break
else:
printstatus = False
# TODO: Will the websocket end if the program just ends?
2023-04-30 22:18:25 +00:00
print("Program end")
2023-05-01 00:46:08 +00:00
# Loads the config from file into the global config var. If the file
# doesn't exist, the file is created from the defaults in config.
# The function returns nothing
def load_or_create_global_config():
global config
# Check if the config file exists
2023-05-01 01:58:02 +00:00
if os.path.isfile(CONFIGFILE):
2023-05-01 00:46:08 +00:00
# Read and deserialize the config file
with open(CONFIGFILE, 'r', encoding='utf-8') as f:
2023-05-01 01:12:14 +00:00
temp_config = toml.load(f)
myutils.merge_dictionary(temp_config, config)
2023-05-01 00:46:08 +00:00
else:
# Serialize and write the config dictionary to the config file
logging.warn("No config found at " + CONFIGFILE + ", creating now")
with open(CONFIGFILE, 'w', encoding='utf-8') as f:
toml.dump(config, f)
2023-05-01 01:12:14 +00:00
myutils.set_logging_level(config["default_loglevel"])
2023-05-01 00:46:08 +00:00
2023-05-01 01:58:02 +00:00
# Either pull the token from a file, or get the login from the command
# line if that doesn't work. WILL test your token against the real API
# even if it's pulled from file!
def authenticate(config, context: contentapi.ApiContext):
message = "No token file found"
if os.path.isfile(config["tokenfile"]):
with open(config["tokenfile"], 'r') as f:
token = f.read()
logging.debug("Token from file: " + token)
2023-05-01 02:13:01 +00:00
context.token = token
if context.is_token_valid():
2023-05-01 01:58:02 +00:00
logging.info("Logged in using token file " + config["tokenfile"])
return
else:
message = "Token file expired"
message += ", Please enter login for " + config["api"]
2023-05-01 01:58:02 +00:00
while True:
print(message)
2023-05-01 01:58:02 +00:00
username = input("Username: ")
password = getpass.getpass("Password: ")
try:
token = context.login(username, password, config["expire_seconds"])
with open(config["tokenfile"], 'w') as f:
f.write(token)
logging.info("Token accepted, written to " + config["tokenfile"])
context.token = token
return
2023-05-01 01:58:02 +00:00
except Exception as ex:
print("ERROR: %s" % ex)
message = "Please try logging in again:"
2023-05-01 01:58:02 +00:00
2023-05-01 04:34:56 +00:00
def print_statusline(ws_context: WebsocketContext):
if ws_context.connected:
bg = Back.GREEN
else:
bg = Back.RED
print(bg + Fore.BLACK + "\n User: " + ws_context.user_info["username"] + " CTRL: h s g u i q " + Style.RESET_ALL)
2023-05-01 01:58:02 +00:00
2023-04-30 22:18:25 +00:00
# Because python reasons
if __name__ == "__main__":
main()