agent registration and viewing
This commit is contained in:
parent
c4fd87008c
commit
288edab17c
31
api.py
Normal file
31
api.py
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import requests
|
||||||
|
|
||||||
|
BASE_URL = "https://api.spacetraders.io/v2"
|
||||||
|
|
||||||
|
def handleResponse(res:requests.Response):
|
||||||
|
code = res.status_code
|
||||||
|
try:
|
||||||
|
data = res.json()
|
||||||
|
except:
|
||||||
|
data = None
|
||||||
|
return code, data
|
||||||
|
|
||||||
|
def newAgent(accToken, callsign, faction='COSMIC'):
|
||||||
|
header = {
|
||||||
|
"Authorization": f"Bearer {accToken}",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
}
|
||||||
|
params = {
|
||||||
|
"symbol" : callsign,
|
||||||
|
"faction" : faction
|
||||||
|
}
|
||||||
|
url = f"{BASE_URL}/register"
|
||||||
|
return handleResponse(requests.post(url, json=params, headers=header))
|
||||||
|
|
||||||
|
def viewAgent(agentToken):
|
||||||
|
header = {
|
||||||
|
"Authorization": f"Bearer {agentToken}",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
}
|
||||||
|
url = f"{BASE_URL}/my/agent"
|
||||||
|
return handleResponse(requests.get(url, headers=header))
|
||||||
127
mainwindow.py
Normal file
127
mainwindow.py
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
#builtins
|
||||||
|
import tkinter as Tk
|
||||||
|
from tkinter import ttk as Ttk
|
||||||
|
from tkinter import font
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
#packages
|
||||||
|
from PIL import ImageTk, Image
|
||||||
|
|
||||||
|
#custom stuff
|
||||||
|
from storage import readSave, save
|
||||||
|
import api, ui
|
||||||
|
|
||||||
|
#load icon
|
||||||
|
icoPng = Image.open(path.join("assets","babynet.png"))
|
||||||
|
|
||||||
|
#initialize root
|
||||||
|
root = Tk.Tk()
|
||||||
|
root.title("SPASESHUPS")
|
||||||
|
ico = ImageTk.PhotoImage(icoPng)
|
||||||
|
root.wm_iconphoto(False, ico)
|
||||||
|
|
||||||
|
#add the three main sections
|
||||||
|
#header contains auth keys and such
|
||||||
|
headerFrame = ui.Container(root, freezeCols=1)
|
||||||
|
headerFrame.widget.grid(row=0, column=0, sticky='new')
|
||||||
|
|
||||||
|
#requestFrame is the main body where the request buttons will be
|
||||||
|
requestFrame = ui.Container(root)
|
||||||
|
requestFrame.widget.grid(row=1, column=0, sticky='nesw')
|
||||||
|
|
||||||
|
#response frame is where the output lives
|
||||||
|
responseFrame = ui.Container(root)
|
||||||
|
responseFrame.widget.grid(row=2, column=0, sticky="snew")
|
||||||
|
|
||||||
|
#populate the header
|
||||||
|
accToken = Tk.StringVar()
|
||||||
|
accAuthBox = ui.SavedEntryBox(headerFrame.widget, 'acc_token', accToken)
|
||||||
|
Ttk.Label(headerFrame.widget, text="ACCOUNT TOKEN:").grid(row=0, column=0, sticky='e')
|
||||||
|
accAuthBox.widget.grid(row=0, column=1, columnspan=5, sticky='ew')
|
||||||
|
|
||||||
|
agentToken = Tk.StringVar()
|
||||||
|
agentAuthBox = ui.SavedEntryBox(headerFrame.widget, 'active_agent_token', agentToken)
|
||||||
|
Ttk.Label(headerFrame.widget, text="AGENT TOKEN:").grid(row=1, column=0, sticky='e')
|
||||||
|
agentAuthBox.widget.grid(row=1, column=1, columnspan=5, sticky='ew')
|
||||||
|
#freeze the label column
|
||||||
|
headerFrame.widget.columnconfigure(0, weight=0)
|
||||||
|
|
||||||
|
#populate and style the response frame
|
||||||
|
resLabel = Tk.Text(responseFrame.widget, background='grey17', foreground='white')
|
||||||
|
resLabel.grid(row=0, column=0, sticky='news')
|
||||||
|
resLabel.insert('1.0', "Awaiting call...")
|
||||||
|
resLabel['state'] = 'disabled'
|
||||||
|
resScrollbarV = Ttk.Scrollbar(responseFrame.widget, orient='vertical', command=resLabel.yview)
|
||||||
|
resLabel.configure(yscrollcommand=resScrollbarV.set)
|
||||||
|
resScrollbarV.grid(row=0, column=1, rowspan=2, sticky='ns')
|
||||||
|
|
||||||
|
def updateResponse(newText):
|
||||||
|
resLabel['state'] = 'normal'
|
||||||
|
resLabel.delete('1.0', 'end')
|
||||||
|
resLabel.insert('1.0', newText)
|
||||||
|
resLabel['state'] = 'disabled'
|
||||||
|
|
||||||
|
Ttk.Style().configure('Shaded.TFrame', background='grey17')
|
||||||
|
responseFrame.widget.configure(borderwidth=2, relief='groove', style='Shaded.TFrame')
|
||||||
|
|
||||||
|
#populate the request frame
|
||||||
|
makeFrame = ui.RequesterFrame(requestFrame.widget, 'CREATE')
|
||||||
|
makeFrame.widget.grid(row=0, column=0, sticky='nsew')
|
||||||
|
|
||||||
|
#new agent
|
||||||
|
callsignVar = Tk.StringVar()
|
||||||
|
factionVar = Tk.StringVar()
|
||||||
|
ui.FieldLabel(makeFrame.widget, 'Callsign:', 1)
|
||||||
|
ui.EntryBox(makeFrame.widget, callsignVar).widget.grid(row=1, column=2, sticky='ew')
|
||||||
|
ui.FieldLabel(makeFrame.widget, 'Faction Name:', 2)
|
||||||
|
ui.EntryBox(makeFrame.widget, factionVar).widget.grid(row=2, column=2, sticky='ew')
|
||||||
|
def newAgent(args):
|
||||||
|
resCode, resData = api.newAgent(*args)
|
||||||
|
updateResponse(ui.formatResponse(resCode, resData))
|
||||||
|
try:
|
||||||
|
agentToken.set(resData['token'])
|
||||||
|
if int(resCode) < 300:
|
||||||
|
agentAuthBox.saveValue()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return resCode, resData
|
||||||
|
newAgentButton = ui.ApiButton(makeFrame.widget, 'NEW AGENT', 3, newAgent, (accToken, callsignVar, factionVar))
|
||||||
|
|
||||||
|
viewFrame = ui.RequesterFrame(requestFrame.widget, 'VIEW')
|
||||||
|
viewFrame.widget.grid(row=0, column=1, sticky='nesw')
|
||||||
|
|
||||||
|
#view agent
|
||||||
|
def viewAgent(args):
|
||||||
|
resCode, resData = api.viewAgent(*args)
|
||||||
|
updateResponse(ui.formatResponse(resCode, resData))
|
||||||
|
return resCode, resData
|
||||||
|
viewAgentButton = ui.ApiButton(viewFrame.widget, 'VIEW AGENT', 2, viewAgent, (agentToken))
|
||||||
|
|
||||||
|
useFrame = ui.RequesterFrame(requestFrame.widget, 'USE')
|
||||||
|
useFrame.widget.grid(row=0, column=2, sticky='nsew')
|
||||||
|
|
||||||
|
|
||||||
|
#finalize the layout
|
||||||
|
makeFrame.finalize()
|
||||||
|
useFrame.finalize()
|
||||||
|
viewFrame.finalize()
|
||||||
|
|
||||||
|
headerFrame.finalize()
|
||||||
|
requestFrame.finalize()
|
||||||
|
|
||||||
|
#response frame finalize doesnt help much so do it manually
|
||||||
|
responseFrame.widget.grid_rowconfigure(0, weight=1)
|
||||||
|
responseFrame.widget.grid_columnconfigure(0, weight=1)
|
||||||
|
responseFrame.widget.grid_columnconfigure(1, weight=0)
|
||||||
|
|
||||||
|
for child in root.winfo_children():
|
||||||
|
child.grid_configure(padx = 5, pady = 5)
|
||||||
|
|
||||||
|
#sort out scaling for the top 3 frames
|
||||||
|
root.columnconfigure(0, weight=1)
|
||||||
|
root.rowconfigure(0, weight=0)
|
||||||
|
root.rowconfigure(1, weight=1)
|
||||||
|
root.rowconfigure(2, weight=1, minsize=300)
|
||||||
|
|
||||||
|
#aaaand go
|
||||||
|
root.mainloop()
|
||||||
35
storage.py
Normal file
35
storage.py
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
from os import path
|
||||||
|
import json
|
||||||
|
|
||||||
|
SAVE_FILE = path.join("data", "save.dat")
|
||||||
|
|
||||||
|
def readSave(*fields):
|
||||||
|
try:
|
||||||
|
with open(SAVE_FILE, 'r') as f:
|
||||||
|
out = {}
|
||||||
|
obj = json.load(f)
|
||||||
|
for field in fields:
|
||||||
|
try:
|
||||||
|
out[field] = obj[field]
|
||||||
|
except KeyError:
|
||||||
|
out[field] = None
|
||||||
|
return out
|
||||||
|
except FileNotFoundError:
|
||||||
|
with open(SAVE_FILE, 'w') as f:
|
||||||
|
json.dump({'acc_token': 0}, f, indent=4)
|
||||||
|
return readSave(*fields)
|
||||||
|
|
||||||
|
def save(fieldsDic):
|
||||||
|
try:
|
||||||
|
obj = None
|
||||||
|
with open(SAVE_FILE, 'r') as f:
|
||||||
|
out = {}
|
||||||
|
obj = json.load(f)
|
||||||
|
obj.update(fieldsDic)
|
||||||
|
with open(SAVE_FILE, 'w') as f:
|
||||||
|
json.dump(obj, f, indent=4)
|
||||||
|
return True
|
||||||
|
except FileNotFoundError:
|
||||||
|
with open(SAVE_FILE, 'w') as f:
|
||||||
|
json.dump(fieldsDic, f, indent=4)
|
||||||
|
return True
|
||||||
128
ui.py
Normal file
128
ui.py
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
import tkinter as Tk
|
||||||
|
from tkinter import ttk as Ttk
|
||||||
|
from tkinter import font
|
||||||
|
from pprint import pformat
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from storage import readSave, save
|
||||||
|
|
||||||
|
class FieldLabel():
|
||||||
|
"""
|
||||||
|
Label to set alongside a text box.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent, text, rowNum):
|
||||||
|
self.widget = Ttk.Label(parent, text=text)
|
||||||
|
self.widget.grid(row=rowNum, column=1, sticky='e')
|
||||||
|
|
||||||
|
class EntryBox():
|
||||||
|
"""
|
||||||
|
Basic entry box class.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent, textVar=None):
|
||||||
|
if textVar is None:
|
||||||
|
self.textVar = Tk.StringVar()
|
||||||
|
else:
|
||||||
|
self.textVar = textVar
|
||||||
|
self.widget = Ttk.Entry(parent, width=12, textvariable=self.textVar)
|
||||||
|
|
||||||
|
class SavedEntryBox(EntryBox):
|
||||||
|
"""
|
||||||
|
Entry box that saves values to file with a given field name. Reads from that field on launch.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent, fieldName, textVar, saveOnEnter=True, saveOnChange=False):
|
||||||
|
self.textVar = textVar
|
||||||
|
super().__init__(parent, self.textVar)
|
||||||
|
self.fieldName = fieldName
|
||||||
|
|
||||||
|
value = readSave(fieldName)[fieldName]
|
||||||
|
if value is not None:
|
||||||
|
self.textVar.set(value)
|
||||||
|
else:
|
||||||
|
self.textVar.set(fieldName)
|
||||||
|
|
||||||
|
if saveOnEnter:
|
||||||
|
self.widget.bind("<Return>", self.saveValue)
|
||||||
|
|
||||||
|
if saveOnChange:
|
||||||
|
self.textVar.trace_add("write", self.saveValue)
|
||||||
|
|
||||||
|
def saveValue(self, *args):
|
||||||
|
save({self.fieldName: self.textVar.get()})
|
||||||
|
|
||||||
|
|
||||||
|
class Container():
|
||||||
|
def __init__(self, parent, freezeCols=0):
|
||||||
|
self.widget = Ttk.Frame(parent, padding=(3))
|
||||||
|
self.freezeCols = freezeCols
|
||||||
|
|
||||||
|
def finalize(self):
|
||||||
|
cols, rows = self.widget.grid_size()
|
||||||
|
if self.freezeCols > 0:
|
||||||
|
for i in range(self.freezeCols):
|
||||||
|
self.widget.grid_columnconfigure(i, weight=0)
|
||||||
|
for i in range(self.freezeCols, cols):
|
||||||
|
self.widget.grid_columnconfigure(i, weight=1, uniform='column')
|
||||||
|
|
||||||
|
for i in range(rows):
|
||||||
|
self.widget.grid_rowconfigure(i, weight=0)
|
||||||
|
|
||||||
|
|
||||||
|
class RequesterFrame(Container):
|
||||||
|
"""
|
||||||
|
Top-level frame for classes of manipulations.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent, label):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.widget.configure(height=480, width=330, borderwidth=3, relief="raised")
|
||||||
|
self.widget.bind('<Enter>', lambda e: self.widget.configure(relief="sunken"))
|
||||||
|
self.widget.bind('<Leave>', lambda e: self.widget.configure(relief="raised"))
|
||||||
|
|
||||||
|
self.label = Ttk.Label(self.widget, text=label, font=font.nametofont('TkHeadingFont'))
|
||||||
|
self.label.grid(row=0, column=0, sticky='nw')
|
||||||
|
|
||||||
|
def finalize(self):
|
||||||
|
cols, rows = self.widget.grid_size()
|
||||||
|
self.widget.grid_columnconfigure(0, weight=0)
|
||||||
|
self.widget.grid_columnconfigure(1, weight=0)
|
||||||
|
self.widget.grid_columnconfigure(2, weight=1, minsize=150)
|
||||||
|
|
||||||
|
for i in range(rows):
|
||||||
|
self.widget.grid_rowconfigure(i, weight=1, minsize=5)
|
||||||
|
|
||||||
|
|
||||||
|
class ApiButton():
|
||||||
|
"""
|
||||||
|
Button which triggers an API call when clicked.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent, label, rowNum, apiFunc, args):
|
||||||
|
self.call = apiFunc
|
||||||
|
self.args = args
|
||||||
|
self.row = rowNum
|
||||||
|
self.parent = parent
|
||||||
|
self.widget = Ttk.Button(parent, command=self.pressed, text=label)
|
||||||
|
self.widget.grid(row=rowNum, column=1, columnspan=2, sticky='nsew')
|
||||||
|
|
||||||
|
def pressed(self, *args):
|
||||||
|
progbar = Ttk.Progressbar(self.parent, orient='horizontal', mode='indeterminate', length=10)
|
||||||
|
progbar.grid(row=self.row, column=0)
|
||||||
|
threading.Thread(target=self.thread, args=(progbar,)).start()
|
||||||
|
|
||||||
|
def thread(self, progbar):
|
||||||
|
toPass = []
|
||||||
|
if isinstance(self.args, (list, tuple)):
|
||||||
|
for arg in self.args:
|
||||||
|
if type(arg) is Tk.StringVar:
|
||||||
|
toPass.append(arg.get())
|
||||||
|
else:
|
||||||
|
toPass.append(arg)
|
||||||
|
else:
|
||||||
|
if type(self.args) is Tk.StringVar:
|
||||||
|
toPass.append(self.args.get())
|
||||||
|
else:
|
||||||
|
toPass.append(self.args)
|
||||||
|
self.resCode, self.resData = self.call(toPass)
|
||||||
|
progbar.grid_forget()
|
||||||
|
|
||||||
|
def formatResponse(resCode, resData):
|
||||||
|
return f"""Response {resCode}:
|
||||||
|
{pformat(resData)}"""
|
||||||
Loading…
Reference in a new issue