Compare commits

...

11 Commits
main ... Dev

Author SHA1 Message Date
7f5cf9e8a4 Upload files to "cache/items/icons" 2025-03-07 20:39:28 -08:00
d80a137ba6 Upload files to "subfiles" 2025-03-07 20:38:10 -08:00
bf1ea6b0f8 Delete customtk.py 2025-03-07 20:37:44 -08:00
9da204da1d Upload files to "/" 2025-03-07 20:37:38 -08:00
0970e28f0c Update README.md 2025-02-23 18:09:09 -08:00
957dd73e59 Update README.md 2025-02-21 16:33:20 -08:00
61acd551ea Update README.md 2025-02-21 16:32:38 -08:00
cc433a5bbf Upload files to "subfiles" 2025-02-21 16:23:52 -08:00
37f33f49ca Yea
g
2025-02-21 16:23:18 -08:00
ee9e2c1de3 Delete requirements.txt
will be updated when 'final' update comes out
2025-02-21 16:21:36 -08:00
87d0d92f4d Delete __main__.py
old file, will be replaced
2025-02-21 16:21:18 -08:00
9 changed files with 1008 additions and 427 deletions

View File

@ -1,5 +1,7 @@
# spaceningui
Simple Gui Program to help install SNS and the bootstrapper.
Simple Gui Program to help install and manage SNS and the bootstrapper.
Make sure to have python3 installed, and to install all the requirents listed in the .txt. Mongo, git, and Node.js are also required.
Make sure to have python3 installed, and to install all the requirents listed in the .txt *(When updated). Mongo, git, and Node.js are also required.
This branch is the majorly rewritten dev branch. I wasn't happy on how I managed the inital project, especially regarding the gui. The current version will hopefully fix much of that

View File

@ -1,455 +1,548 @@
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox, font
from ttkthemes import ThemedTk
from tkinter.scrolledtext import ScrolledText
from os.path import isfile, join, exists
import customtkinter
from CTkMessagebox import CTkMessagebox
from subfiles import helpers, install, savetools, themes, comunic
import json
import webbrowser
from subprocess import Popen, PIPE
from pathlib import Path
import threading
from pathlib import Path
from sys import platform
import requests
from hashlib import sha256
from os import listdir
from os.path import isfile, join, exists
import shutil
logarr = []
with open('lang.json') as f: lang=json.load(f)
class menus:
def clientmenu(file, mainframe):
for child in mainframe.winfo_children(): child.destroy()
checkclient = str(helpers.check4client(helpers.getclientpath(file)))
clientdetect = ttk.Label(mainframe, text=f"Was Bootstrapper found: {checkclient}", anchor=tk.W)
clientdetect.grid(row=0, sticky=tk.W)
#not threading this prob stalls the gui, but it's not like the server, where I actually need it to run in the background; in otherwords, I do not care :)
dlldownload = ttk.Button(mainframe, text="Download Latest Bootstrapper", command=lambda: helpers.downloadlatestdll(helpers.getclientpath(file)))
dlldownload.grid(row=1, sticky=tk.W)
#menu for pluto scripts; running them is not currently implemented
def plutomenu(file, mainframe):
for child in mainframe.winfo_children(): child.destroy()
openwfpath = helpers.getclientpath(file) + "/OpenWF/scripts/"
def openfolder(folder):
Popen(['xdg-open', folder])
onlyfiles = [f for f in listdir(openwfpath) if isfile(join(openwfpath, f))]
i = 0
for file in onlyfiles:
filelabel = ttk.Label(mainframe, text=file, anchor=tk.W)
filelabel.grid(row = i, column = 0, sticky = tk.W, pady = 2)
plutorun = ttk.Button(mainframe, text="Running not implemented yet", command=lambda: runpluto(file))
plutorun.grid(row = i, column = 1, sticky = tk.W, pady = 2, padx=10)
i += 1
# Input would be a json file
def settingsmenu(file, mainframe, vcmd):
for child in mainframe.winfo_children(): child.destroy()
if Path(file).is_file():
with open(file) as f:
settings = json.load(f)
i = 0
frameunder = ttk.Frame(mainframe)
tempsettings = {}
print(settings)
for key in settings.keys():
if key in lang.keys():
item = ttk.Label(frameunder, text=(lang[key] + " : "))
else:
item = ttk.Label(frameunder, text=(key + " : "))
item.grid(row = i, column = 0, sticky = tk.W, pady = 2)
print (type(settings[key]))
if type(settings[key]) is str:
value = ttk.Entry(frameunder, width=50)
value.insert(0,settings[key])
elif type(settings[key]) not in [str, bool, int, dict]:
value = ttk.Label(frameunder, text="N/A")
elif type(settings[key]) is bool:
boeol = tk.StringVar()
value = ttk.OptionMenu(frameunder, boeol, settings[key], True, False)
elif type(settings[key]) is int:
value = ttk.Entry(frameunder, width=50, validate='key', validatecommand=(vcmd, '%P'))
value.insert(0,settings[key])
#stupid ass nested dicts eat my whole balls
elif type(settings[key]) is dict:
value = {}
for k in settings[key].keys():
value[k] ={}
if type(settings[key][k]) is str:
value[k]["value"] = ttk.Entry(frameunder, width=50)
value[k]["value"].insert(0,settings[key][k])
elif type(settings[key][k]) not in [str, bool, int]:
value[k]["value"] = ttk.Label(frameunder, text="N/A")
elif type(settings[key][k]) is bool:
boeol = tk.BooleanVar()
value[k]["value"] = ttk.OptionMenu(frameunder, boeol, settings[key][k], True, False)
boeol.set(settings[key][k])
value[k]["valueop"] = boeol
elif type(settings[key][k]) is int:
value[k]["value"] = ttk.Entry(frameunder, width=50, validate='key', validatecommand=(vcmd, '%P'))
value[k]["value"].insert(0,settings[key][k])
value[k]["type"] = type(settings[key][k])
from websockets.sync.client import connect
if type(value) is not dict:
value.grid(row = i, column = 1, sticky = tk.W, pady = 2)
i += 1
else:
i+=1
sp1=ttk.Separator(mainframe,orient='horizontal')
sp1.grid(row=i,column=1,sticky='ew')
i+=1
for k in value.keys():
print(k)
dictlabel = ttk.Label(frameunder, text=(k + " : "))
dictlabel.grid(row = i, column = 0, sticky = tk.E, pady = 2)
value[k]["value"].grid(row = i, column = 1, sticky = tk.W, pady = 2)
i+=1
ttk.Separator(mainframe, orient=tk.HORIZONTAL).grid(row=i)
i+=1
if type(settings[key]) is bool:
tempsettings[key] = {
"value" : boeol,
"type" : type(settings[key])
}
else:
tempsettings[key] = {
"value" : value,
"type" : type(settings[key])
}
customtkinter.set_appearance_mode("System")
customtkinter.set_window_scaling(1)
customtkinter.set_widget_scaling(1)
save = ttk.Button(frameunder, command=lambda: helpers.savefile(file, tempsettings), text="SAVE")
save.grid(row=i, column=2, sticky=tk.E, pady=2)
frameunder.grid()
def placeholder():
print("placeholder called")
pass
class menuTools:
def selectFromList(self, itemList, iconList, textvar):
#there is a LOT here, I really should make a "menus" file lol
self.truePath=''
print(textvar.get())
self.threadRunning=False
currentOption= customtkinter.StringVar()
currentOption.set("Current Option: None")
def servermenu(mainframe, configfile):
for child in mainframe.winfo_children(): child.destroy() #oneline to destroy everything in the main frame
side1 = ttk.Frame(mainframe)
side2 = ttk.Frame(mainframe)
# Side one of the 'server' menu
logarea = ScrolledText(side2,
wrap = tk.WORD,
state="disabled")
self.currentImage = helpers.getIcon(self, "NA", "/placeholder.png")
startb = ttk.Button(side1, text="Start Server", command=lambda: [helpers.bgthread(helpers.serverbackground, [helpers.getsnpath(configfile), logarea])])
startb.grid(row = 0, column = 0, sticky = tk.W, pady = 2)
# Side two of the 'server' menu
currentLimit = customtkinter.StringVar()
logarea.grid(row = 0, column = 0, sticky = tk.E, pady = 2)
newWindow = customtkinter.CTkToplevel(self.root)
newWindow.title("Select An Option")
newWindow.geometry("600x400")
side1.grid(row = 0, column = 0, sticky = tk.N, pady = 2)
side2.grid(row = 0, column = 1, sticky = tk.N, pady = 2)
customtkinter.CTkLabel(newWindow, text="Please Choose an Option", anchor='center').grid(row=0, column=0, sticky="we")
class helpers:
def downloadlatestdll(filepath):
x = requests.get('https://openwf.io/supplementals/client%20drop-in/meta')
meta = json.loads(x.text)
url = f"https://openwf.io/supplementals/client%20drop-in/{meta['version']}/dwmapi.dll"
centerFrame = customtkinter.CTkFrame(newWindow, width=600, height=200, fg_color="transparent")
centerFrame.pack_propagate(False)
content = requests.get(url, stream=True).content
hashofdll = sha256()
hashofdll.update(content)
listFrame= customtkinter.CTkScrollableFrame(centerFrame, height=200, width=300, bg_color="transparent")
self.listFrameInner = customtkinter.CTkFrame(listFrame)
self.listFrameInner.pack()
def submit(self, truePath, textvar, window):
if hashofdll.hexdigest() == meta['sha256']:
with open(filepath + "dwmapi.dll", "wb") as out_file:
out_file.write(content)
messagebox.showinfo(title="Bootstrapper Downloaded", message="Bootstrapper Downloaded!")
else:
messagebox.showerror(title="Unknown Error.", message="SpaceninGUI could not verify the hash of the Bootstrapper. Sorry :(")
def check4client(clientpath):
onlyfiles = [f for f in listdir(clientpath) if isfile(join(clientpath, f))]
if "dwmapi.dll" in onlyfiles:
return True
else:
return False
# Not implemented yet lol
def runpluto(name):
pass
def is_number(data):
"""Validate the contents of an entry widget as a int."""
if data == '':
return True
try:
rv = int(data)
except ValueError:
return False
return True
def savefile(file, save):
if Path(file).is_file:
with open(file) as f:
data = json.load(f)
for key in save.keys():
if save[key]["type"] is bool:
if save[key]['value'].get() == '1':
data[key] = True
else:
data[key] = False
print(save[key]['value'].get())
elif save[key]["type"] is str:
data[key] = str(save[key]["value"].get())
elif save[key]["type"] is int:
data[key] = int(save[key]["value"].get())
elif save[key]["type"] is dict:
for k in save[key]['value'].keys():
if save[key]['value'][k]["type"] is bool:
data[key][k] = bool(save[key]['value'][k]["valueop"].get())
elif save[key]['value'][k]["type"] is str:
data[key][k] = str(save[key]['value'][k]["value"].get())
elif save[key]['value'][k]["type"] is int:
data[key][k] = int(save[key]['value'][k]["value"].get())
with open(file, "w") as f:
json.dump(data, f, indent=2)
def getclientpath(file):
if Path(file).is_file():
with open(file) as f:
d = json.load(f)
return d["wfpath"]
else:
return False
# Grabs the serverpath, returns false if non-existant
def getsnpath(file):
if Path(file).is_file():
with open(file) as f:
d = json.load(f)
return d["spaceninjapath"]
else:
return False
def getlogmax():
file = 'sngconfig.json'
if Path(file).is_file():
with open(file) as f:
d = json.load(f)
return int(d["maxlogsize"])
else:
return False
def bgthread(func, args):
th = threading.Thread(target=func, args=args)
th.daemon = True
th.start()
def serverbackground(cd, logarea): # To my knowledge, running the server in the main thread would stall the gui, fuck that lol
logmax = helpers.getlogmax()
def mongo():
sysctl = Popen(['systemctl', 'start', 'mongodb'])
sysctl.wait()
def execute(cd):
popen = Popen(['npm', 'run', 'dev'], stdin=PIPE, stdout=PIPE, universal_newlines=True, cwd=cd)
for stdout_line in iter(popen.stdout.readline, ""):
yield stdout_line
popen.stdout.close()
return_code = popen.wait()
if return_code:
raise subprocess.CalledProcessError(return_code)
if platform == "linux":
print("Running on linux requires mongodb to be started!")
mongo()
for path in execute(cd):
if len(logarr) < logmax:
logarr.append(path)
print(f"truePath : {self.truePath}")
print(textvar.get())
if currentOption.get() == '':
window.destroy()
else:
logarr.pop(0)
logarr.append(path)
if logarea:
logarea.configure(state="normal")
logarea.delete(1.0, "end")
for element in logarr:
logarea.insert(tk.INSERT, element)
logarea.configure(state="disabled")
textvar.set(self.truePath)
window.destroy()
def check4sn(configfile):
file = helpers.getsnpath(configfile) + "package.json"
if Path(file).is_file():
with open(file) as f:
d = json.load(f)
if (d["name"] == "wf-emulator"):
return True
else:
return False
def on_closing(root):
if messagebox.askokcancel("Quit", "Do you want to quit?"):
root.destroy()
def change(self, path, name, textVar, iconList):
textVar.set(f"Current Option: {name}")
print(path)
self.truePath=path
print(self.truePath)
self.currentImage=helpers.getIcon(self, path, iconList[path])
icon=customtkinter.CTkImage(dark_image=self.currentImage, size=(200, 200))
self.iconLabel.destroy()
self.iconLabel = customtkinter.CTkLabel(sideFrame, text="", image=icon, width=275, height=200)
self.iconLabel.grid(row=0, column=0)
class main:
def __init__(self, configfile):
root = ThemedTk(theme='black', themebg=True)
root.title('SpaceNinGui Version 1.0')
root.minsize(400, 300)
serverlogs = tk.StringVar()
wfemucheck = str(helpers.check4sn(configfile))
menubar = tk.Menu(root)
vcmd = root.register(helpers.is_number)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Options", command=lambda: menus.settingsmenu(file = configfile, mainframe=mainframe, vcmd=vcmd))
filemenu.add_separator()
filemenu.add_command(label="Exit", command=lambda: helpers.on_closing(root))
menubar.add_cascade(label="SpaceNinGUI", menu=filemenu)
menubar.add_separator()
menubar.add_command(label="\u22EE", activebackground=menubar.cget("background"))
def outsideThread(self, listFrame, itemList, limit, truePath):
i = 0
for element in itemList:
if limit in element["name"].lower(): ass= True
else: ass= False
print(f"{element["name"]} : {str(ass)}")
if limit in element["name"].lower():
menubar.add_command(label="Server", command=lambda: menus.servermenu(mainframe, configfile))
menubar.add_command(label="Settings", command=lambda: menus.settingsmenu(file=(helpers.getsnpath(configfile) + "config.json"), mainframe=mainframe, vcmd=vcmd))
mainframe = ttk.Frame(root)
menubar.add_command(label="\u22EE", activebackground=menubar.cget("background"))
menubar.add_command(label="Client", command=lambda: menus.clientmenu(file="sngconfig.json", mainframe=mainframe))
menubar.add_command(label="Settings", command=lambda: menus.settingsmenu(file=(helpers.getclientpath(configfile) + "/OpenWF/client_config.json"), mainframe=mainframe, vcmd=vcmd))
menubar.add_command(label="Scripts", command=lambda: menus.plutomenu(file="sngconfig.json", mainframe=mainframe))
if "slot" in element:
button = customtkinter.CTkButton(self.listFrameInner, text=(f"{element["name"]} - SLOT {str(element["slot"])}"), border_color="black", anchor="w", fg_color="transparent", width = 299, command=lambda element=element: change(self, element["uniqueName"], element["name"], currentOption, iconList))
else:
i+=1
button = customtkinter.CTkButton(self.listFrameInner, text=(f"{element["name"]} - NO SLOT"), border_color="black", anchor="w", fg_color="transparent", width = 299, command=lambda element=element: change(self, element["uniqueName"], element["name"], currentOption, iconList))
button.pack(anchor="nw", expand=True)
print(i)
self.threadRunning=False
def reset(self, args):
if self.threadRunning:
return #If the search thread is running, just wait, don't be fucking lazy, it takes 2 seconds for THE ENTIRE LIST, it is not that hard
helpers.removeChildren(self.listFrameInner)
helpers.bgThread(outsideThread, args)
helpers.bgThread(outsideThread, [self, listFrame, itemList, '', self.truePath])
sideFrame= customtkinter.CTkFrame(centerFrame, height=200, width=275, fg_color="transparent")
icon=customtkinter.CTkImage(dark_image=self.currentImage, size=(200, 200))
self.iconLabel = customtkinter.CTkLabel(sideFrame, text="", image=icon, width=275, height=200)
self.iconLabel.grid(row=0, column=0)
sideFrame.grid(row=0, column=0, sticky="nsew")
searchFrame=customtkinter.CTkFrame(newWindow, width=600)
searchFrame.grid(row=2, column=0)
search=customtkinter.CTkEntry(searchFrame, textvariable=currentLimit, fg_color="transparent", width=400)
search.grid(row=0, column=0)
searchButton=customtkinter.CTkButton(searchFrame, width=200, text="Search", command=lambda: reset(self, [self, listFrame, itemList, currentLimit.get(), self.truePath]))
searchButton.grid(row=0, column=1)
optionLabel= customtkinter.CTkLabel(newWindow, textvariable=currentOption)
submitButton=customtkinter.CTkButton(newWindow, width=100, text="Submit", height=30, command= lambda: submit(self,self.truePath,textvar,newWindow))
submitButton.grid(row=4, column=0)
centerFrame.grid(row=1, column=0)
listFrame.grid(row=0, column=1)
optionLabel.grid(row=3, column=0)
def verticalButtons(self, buttonList, frame):
for button in buttonList.keys():
sideButton = customtkinter.CTkButton(frame, height=28, hover_color=self.theme["highlight_color"],
border_color=self.theme["highlight_color"],
border_width=(self.x * .001),
fg_color="transparent",
bg_color="transparent",
text=button,
command=buttonList[button])
sideButton.pack(pady=(self.y * .01), padx=2, side="top", anchor="nw")
def labelDown(self, labelList, frame, column):
newFrame=customtkinter.CTkFrame(frame, fg_color="transparent")
newFrame.grid(row=0, column=3, sticky="nswe")
i=1
l = []
for labelText in labelList:
label = customtkinter.CTkLabel(newFrame, textvariable=labelText, height=28, text_color="white")
l.append(label)
for g in l:
g.pack(anchor='nw')
i+=1
def horizontalButtons(self, buttonList, frame):
for button in buttonList.keys():
sideButton = customtkinter.CTkButton(frame, height=28, hover_color=self.theme["highlight_color"],
border_color=self.theme["highlight_color"],
border_width=(self.x * .001),
fg_color="transparent",
bg_color="transparent",
text=button,
command=buttonList[button])
sideButton.pack(pady=(self.x * .01), padx=2, side="left", anchor="w")
checklabel = ttk.Label(mainframe, text=f"Was Spaceninja Found: {wfemucheck}", anchor=tk.W, font=("Arial", 16, "bold"))
checklabel.grid(row = 0, column = 0, sticky = tk.W, pady = 2)
mainframe.grid(row = 0, column = 0, pady = 2)
root.protocol("WM_DELETE_WINDOW", lambda: helpers.on_closing(root))
root.config(menu=menubar)
root.mainloop()
class menus():
class install():
def serverMenu(self):
helpers.removeChildren(self.mainFrame)
topFrame = customtkinter.CTkFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),
)
topFrame.pack(pady=(self.y * .10))
topFrame.grid_propagate(0)
def __init__(self):
self.step = 1
sideFrame = customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .25), height=self.y*.8, fg_color=self.theme['bg_deep'])
sideFrame.grid(row=0, column=0, sticky="ns")
self.config = {}
self.elements = {}
borderFrame=customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .01), height=(self.y*.8), fg_color=self.theme['bg_color'], corner_radius=0)
borderFrame.grid(row=0, column=1, sticky="ns")
sideFrame.grid_propagate(1)
root = ThemedTk(theme='black', themebg=True)
self.root = root
self.installstep=tk.StringVar()
self.installprog=tk.IntVar()
self.installprog.set(0)
self.installstep.set("Init")
#font options lmao
standard = ('Noto Sans', 10)
standardbold = ('Noto Sans', 10, "bold")
self.standard = standard
self.standardbold = standardbold
buttonList = {
"Start Server" : lambda: helpers.bgThread(comunic.startServer, [self, self.serverPath, self.logArea]),
"Open Server Location": lambda: helpers.openLocation(self, comunic.getSnPath('sngconfig.json'))
}
menuTools.verticalButtons(self, buttonList=buttonList, frame=sideFrame)
root.title('SpaceNinGui Installer')
root.minsize(400, 300)
leftframe = ttk.Frame(root, borderwidth=10)
rightframe = ttk.Frame(root, borderwidth=1)
steps=["1: Initial Message", "2: Install Spaceninja Server", "3: Install Warframe Bootstrapper", "4: Final Steps"]
ttk.Label(leftframe, text="Steps:").grid(padx=20)
self.steplabel=[]
for step in steps:
label=ttk.Label(leftframe, text=step, anchor=tk.W)
self.steplabel.append(label)
for label in self.steplabel:
label.grid(padx=20, pady=5, sticky=tk.W)
self.logArea = customtkinter.CTkTextbox(topFrame, width=(self.x * .7 * .74))
self.logArea.grid(row=0, column=2, sticky="ns")
def updateMenu(self):
helpers.removeChildren(self.mainFrame)
topFrame = customtkinter.CTkFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),
)
topFrame.pack(pady=(self.y * .10))
topFrame.grid_propagate(0)
self.steplabel[0].config(font=standardbold)
rightinnerframe = ttk.Frame(rightframe)
ttk.Label(rightinnerframe, text="Welcome to SpaceNinGui! \nFirst, We have to get some inital settings setup. \nWe will start with the server configuration.").grid()
leftframe.grid(row=0, column=0, sticky=tk.W)
sideFrame = customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .25), height=self.y*.8, fg_color="transparent", corner_radius=10)
sideFrame.grid(row=0, column=0, sticky="ns")
rightinnerframe.grid()
rightframe.grid(row=0, column=1, sticky=tk.E)
nextbutton = ttk.Button(rightframe, text="Next", command=lambda: self.next(rightinnerframe))
nextbutton.grid(row=1, sticky=tk.SE)
root.protocol("WM_DELETE_WINDOW", lambda: helpers.on_closing(root))
root.mainloop()
borderFrame=customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .01), height=(self.y*.8), fg_color=self.theme['bg_color'], corner_radius=0)
borderFrame.grid(row=0, column=1, sticky="ns")
sideFrame.grid_propagate(1)
def configsave(self):
with open('sngconfig.json', 'w') as f:
tot = {}
tot["spaceninjapath"] = self.elements['serverpath'].get()
tot["wfpath"] = self.elements['clientpath'].get()
tot['maxlogsize']=10
json.dump(tot, f, indent=2)
self.versions = [
customtkinter.StringVar(),
customtkinter.StringVar()
]
buttonList = {
"Open Client Location" : lambda: helpers.openLocation(self, self.clientPath),
"Open Server Location": lambda: helpers.openLocation(self, comunic.getSnPath(self.configFile)),
"Update Client Bootstrapper" : lambda: comunic.downloadLatestDll(self, self.clientPath),
"Update Server" : lambda: placeholder()
}
menuTools.verticalButtons(self, buttonList=buttonList, frame=sideFrame)
self.versions[0].set("Checking Server Version")
self.versions[1].set("Checking Client Version")
def install(self, clientpath, serverpath):
#first install server
self.installstep.set("Downloading Server Through Git")
sysctl = Popen(['git', 'clone', 'https://openwf.io/SpaceNinjaServer.git', serverpath])
self.installprog.set(1)
sysctl.wait()
self.installstep.set("Installing Server Requirements (via npm)")
self.installprog.set(25)
sysctl = Popen(["npm", '--prefix', f'{serverpath}', 'install'])
sysctl.wait()
self.installstep.set("Copying Config File")
shutil.copy(serverpath + "/config.json.example", serverpath + "/config.json")
self.installstep.set("Starting Bootstrapper Download")
self.installprog.set(50)
print("Server install worked. ")
helpers.downloadlatestdll(clientpath)
self.installprog.set(99)
self.installstep.set("Install Complete!\nPress next then restart to get started!")
helpers.bgThread(comunic.getLatestVersions, [self, 'tempFile.json', self.versions])
def next(self, inner):
if self.step == 1:
self.step+=1
for child in inner.winfo_children(): child.destroy()
self.elements["serverpath"] = tk.StringVar()
path = ttk.Entry(inner, width=50, textvariable=self.elements["serverpath"])
flavortext = ttk.Label(inner, text="Please input a path that you would like to install the Server in!")
flavortext.grid(padx=10)
path.grid(padx=10)
self.steplabel[0].config(font=self.standard)
self.steplabel[1].config(font=self.standardbold)
elif self.step == 2:
self.step+=1
self.elements["clientpath"] = tk.StringVar()
for child in inner.winfo_children(): child.destroy()
path = ttk.Entry(inner, width=50, textvariable=self.elements["clientpath"])
flavortext = ttk.Label(inner, text="Please input the path that has Warframe installed\nI highly suggest making a copy to prevent potental bans.", anchor=tk.CENTER)
flavortext.grid(padx=10, pady=5)
path.grid(padx=10)
self.elements["wfpath"] = path
self.steplabel[1].config(font=self.standard)
self.steplabel[2].config(font=self.standardbold)
elif self.step == 3:
self.step+= 1
print("final step!!!")
for child in inner.winfo_children(): child.destroy()
flavortext = ttk.Label(inner, text="Thank you! The OpenWF setup should be downloading in the background!", anchor=tk.CENTER)
flavortext.grid(padx=10, pady=5)
statustext = ttk.Label(inner, textvariable=self.installstep, anchor=tk.CENTER)
statustext.grid(padx=10, pady=5)
statusbar = ttk.Progressbar(inner, variable=self.installprog)
statusbar.grid()
helpers.bgthread(self.install, [self.elements["clientpath"].get(), self.elements["serverpath"].get()])
elif self.step == 4:
if self.installstep.get() == "Install Complete!\nPress next then restart to get started!":
self.configsave()
self.root.destroy()
menuTools.labelDown(self, labelList=self.versions, frame=topFrame, column=3)
def clientMenu(self):
helpers.removeChildren(self.mainFrame)
topFrame = customtkinter.CTkFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),
)
topFrame.pack(pady=(self.y * .10))
topFrame.grid_propagate(0)
menuBar = customtkinter.CTkFrame(topFrame, fg_color=self.theme["bg_deep"], width=(self.x * (.70)), height=self.y * .1)
menuBar.grid(row=0, column=0, sticky="we")
buttonList = {
"Start Client (steam)" : lambda: helpers.bgThread(comunic.startClient, [self, json.load(open(self.configFile))["steamID"]]),
"Open Logs Location" : lambda: comunic.openClientLogs(self, platform)
}
menuTools.horizontalButtons(self, buttonList, menuBar)
def settingsMenu(self, file):
data = savetools.loadFile(self, file)
helpers.removeChildren(self.mainFrame)
topFrame = customtkinter.CTkScrollableFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),
)
topFrame.pack(pady=(self.y * .10))
newData = {}
def recusiveIssue(self, data, newData, topFrame, recLayer, i):
print("Length : " + str(i) + " Type : " + str(type(data)))
if type(data) is dict:
for key in data.keys():
layerArr = ""
for n in range(recLayer):
layerArr = layerArr + " "
if recLayer > 0:
layerArr=layerArr+""
l = customtkinter.CTkLabel(topFrame, text=layerArr + key, anchor='w')
l.grid(row=i, column=0, sticky='w')
print(key + f" : {str(i)}")
match data[key]:
case str():
newData[key] = customtkinter.StringVar()
newData[key].set(data[key])
e = customtkinter.CTkEntry(topFrame, textvariable=newData[key], width=self.x*.5)
e.grid(row=i, column=1, padx=10)
i+=1
case bool():
newData[key] = customtkinter.BooleanVar()
newData[key].set(data[key])
e = customtkinter.CTkSwitch(topFrame, variable=newData[key], onvalue=True, offvalue=False, text='')
e.grid(row=i, column=1, padx=10)
i+=1
case int():
newData[key] = customtkinter.StringVar()
newData[key].set(str(data[key]))
e = customtkinter.CTkEntry(topFrame, textvariable=newData[key], width=self.x*.5, validate='key', validatecommand=(self.verifyNumb, '%P'))
e.grid(row=i, column=1, padx=10)
i+=1
case dict():
i+=1
newData[key] = {}
i = recusiveIssue(self, data[key], newData[key], topFrame, (recLayer + 1), i)
case list():
i+=1
newData[key] = []
i = recusiveIssue(self, data[key], newData[key], topFrame, (recLayer + 1), i)
elif type(data) is list:
for key in range(len(data)):
layerArr = ""
for n in range(recLayer):
layerArr = layerArr + " "
if recLayer > 0:
layerArr=layerArr+""
l = customtkinter.CTkLabel(topFrame, text=layerArr + str(key), anchor='w')
l.grid(row=i, column=0, sticky='w')
print(str(key) + " key")
match data[key]:
case str():
newData.append(customtkinter.StringVar())
newData[key].set(data[key])
e = customtkinter.CTkEntry(topFrame, textvariable=newData[key], width=self.x*.5)
e.grid(row=i, column=1, padx=10)
i+=1
case bool():
newData.append(customtkinter.BooleanVar())
newData[key].set(data[key])
e = customtkinter.CTkSwitch(topFrame, variable=newData[key], onvalue=True, offvalue=False, text='')
e.grid(row=i, column=1, padx=10)
i+=1
case int():
newData.append(customtkinter.IntVar())
newData[key].set(data[key])
e = customtkinter.CTkEntry(topFrame, textvariable=newData[key], width=self.x*.5)
e.grid(row=i, column=1, padx=10)
i+=1
case dict():
i+=1
newData.append({})
i = recusiveIssue(self, data[key], newData[key], topFrame, (recLayer + 1), i)
case list():
i+=1
newData.append([])
i = recusiveIssue(self, data[key], newData[key], topFrame, (recLayer + 1), i)
return i
i=0
i=recusiveIssue(self, data, newData, topFrame, 0, i)
saveButton = customtkinter.CTkButton(topFrame, height=28, hover_color=self.theme["highlight_color"],
border_color=self.theme["highlight_color"],
border_width=(self.x * .001),
fg_color="transparent",
bg_color="transparent",
text="Save Settings",
command=lambda: savetools.saveFile(self, newData, file))
saveButton.grid(row=i, column=0, sticky='w')
def plutoMenu(self):
helpers.removeChildren(self.mainFrame)
plutoList=[f for f in listdir(self.clientPath+'/OpenWF/scripts/') if isfile(join(self.clientPath + "/OpenWF/scripts/", f))]
runningList={}
print(plutoList)
topFrame = customtkinter.CTkFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),
)
topFrame.pack(pady=(self.y * .10))
topFrame.grid_propagate(0)
topFrame.columnconfigure(1, weight=1)
i=0
for pluto in plutoList:
runningList[pluto] = customtkinter.BooleanVar()
label = customtkinter.CTkLabel(topFrame, text=pluto)
label.grid(row=i, column=0, sticky="nsw", padx=10)
toggle = customtkinter
e = customtkinter.CTkSwitch(topFrame, variable=runningList[pluto], command=lambda pluto=pluto: comunic.runPluto(self, pluto, runningList), text='')
e.grid(row=i, column=1, padx=10)
i+=1
print(pluto)
def inlineScripting(self):
helpers.removeChildren(self.mainFrame)
topFrame = customtkinter.CTkFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),
)
topFrame.pack(pady=(self.y * .10))
topFrame.grid_propagate(0)
sideFrame = customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .25), height=self.y*.8, fg_color=self.theme['bg_deep'])
sideFrame.grid(row=0, column=0, sticky="ns")
borderFrame=customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .01), height=(self.y*.8), fg_color=self.theme['bg_color'], corner_radius=0)
borderFrame.grid(row=0, column=1, sticky="ns")
sideFrame.grid_propagate(1)
buttonList = {
"Push Inline" : lambda: comunic.pushInline(self, self.logArea)
}
menuTools.verticalButtons(self, buttonList=buttonList, frame=sideFrame)
self.logArea = customtkinter.CTkTextbox(topFrame, width=(self.x * .7 * .74))
self.logArea.grid(row=0, column=2, sticky="ns")
def arsenalMenu(self):
helpers.removeChildren(self.mainFrame)
#Load weapons from cache
try:
self.weapons=helpers.formatExportWeapons(self, './cache/items/weapons.json')
self.powersuits=helpers.formatExportPowersuits(self, './cache/items/powersuits.json')
self.weaponsIcons=helpers.formatExportPlus(self, './cache/items/plus/weapons.json')
self.powersuitsIcons=helpers.formatExportPlus(self, './cache/items/plus/powersuits.json')
except:
print("FUCK")
comunic.getWarframeExports(self, "./cache/items/")
comunic.getWarframeExportsPlus(self, "./cache/items/")
self.weapons=helpers.formatExportWeapons(self, './cache/items/weapons.json')
self.powersuits=helpers.formatExportPowersuits(self, './cache/items/powersuits.json')
self.weaponsIcons=helpers.formatExportPlus(self, './cache/items/plus/weapons.json')
self.powersuitsIcons=helpers.formatExportPlus(self, './cache/items/plus/powersuits.json')
topFrame = customtkinter.CTkFrame(self.mainFrame, fg_color=self.theme["bg_deep"], corner_radius=10, height=(self.y * .80), width=(self.x * (.70)),)
topFrame.pack(pady=(self.y * .10))
topFrame.grid_propagate(0)
leftFrame = customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .25), height=self.y*.8, fg_color=self.theme['bg_deep'])
leftFrame.grid(row=0, column=0, sticky="ns")
borderFrame=customtkinter.CTkFrame(topFrame, width=(self.x * .7 * .01), height=(self.y*.8), fg_color=self.theme['bg_color'], corner_radius=0)
borderFrame.grid(row=0, column=1, sticky="ns")
leftFrame.grid_propagate(1)
rightFrame = customtkinter.CTkFrame(topFrame, fg_color=self.theme['bg_deep'])
rightFrame.grid(row=0, column=2, sticky="nsew")
selectedWeapons = {}
i=0
for entry in ["Warframe", "Primary", "Secondary", "Melee"]:
selectedWeapons[entry] = customtkinter.StringVar()
l=customtkinter.CTkLabel(rightFrame, text=entry)
l.grid(row=i, column=0, padx=6)
e=customtkinter.CTkEntry(rightFrame, textvariable=selectedWeapons[entry], width=self.x*.3, fg_color=self.theme["fg_color"])
e.grid(row=i, column=1, sticky="n", padx=10, pady=3)
if not (entry == "Warframe"):
button=customtkinter.CTkButton(rightFrame, text="📁", width=5, command=lambda selectedWeapons=selectedWeapons[entry]: menuTools.selectFromList(self, self.weapons, self.weaponsIcons, selectedWeapons))
elif entry == "Warframe":
button=customtkinter.CTkButton(rightFrame, text="📁", width=5, command=lambda selectedWeapons=selectedWeapons[entry]: menuTools.selectFromList(self, self.powersuits, self.powersuitsIcons, selectedWeapons))
#if not entry:
# how?????
button.grid(row=i, column=2)
i+=1
buttonList = {
"Push All" : lambda: comunic.pushWeapon(self, [selectedWeapons["Warframe"].get(),selectedWeapons["Primary"].get(),selectedWeapons["Secondary"].get(),selectedWeapons["Melee"].get()], [3, 1, 0, 5]),
"Push Warframe" : lambda: comunic.pushWeapon(self, selectedWeapons["Warframe"].get(), 3),
"Push Primary" : lambda: comunic.pushWeapon(self, selectedWeapons["Primary"].get(), 1),
"Push Secondary" : lambda: comunic.pushWeapon(self, selectedWeapons["Secondary"].get(), 0),
"Push Melee" : lambda: comunic.pushWeapon(self, selectedWeapons["Melee"].get(), 5)
}
menuTools.verticalButtons(self, buttonList, leftFrame)
class main():
def exit(self):
self.threadStop = True
for thread in self.popenThreads:
helpers.killPopen(thread)
self.root.destroy()
def __init__(self, configFile):
self.configFile = configFile
self.clientPath = json.load(open(configFile))['wfpath']
self.serverPath = json.load(open(configFile))['spaceninjapath']
self.debug = False
self.root = customtkinter.CTk()
self.popenThreads = []
self.x=750
self.y=500
self.theme = themes.getThemes(self)[json.load(open(configFile))['theme']]
self.threadStop = False
print()
for lib in [helpers, install, savetools]:
lib.check()
self.rightFrame = customtkinter.CTkScrollableFrame(self.root,
orientation="vertical",
width=(self.x * .20),
height=(self.y * 1),
fg_color=self.theme["fg_color"],
bg_color=self.theme["bg_color"],
corner_radius=0
)
buttonList = {
"Server" : lambda: menus.serverMenu(self),
"Server Settings": lambda: menus.settingsMenu(self, self.serverPath+'config.json'),
"Client" : lambda: menus.clientMenu(self),
"Client Settings": lambda: menus.settingsMenu(self, self.clientPath+'OpenWF/client_config.json'),
"Scripts" : lambda: menus.plutoMenu(self),
"Script Store": lambda: placeholder(),
"Inline Scripting" : lambda: menus.inlineScripting(self),
"Metadata" : lambda: placeholder(),
"Arsenal Management": lambda: menus.arsenalMenu(self),
"Weapon Upgrades" : lambda: placeholder(),
"Updates": lambda: menus.updateMenu(self),
"GUI Settings" : lambda: menus.settingsMenu(self, self.configFile)
}
menuTools.verticalButtons(self, buttonList, self.rightFrame)
self.rightFrame.grid(row=0, column=0)
self.mainFrame = customtkinter.CTkScrollableFrame(self.root,
width=(self.x * (1-.20)),
height=(self.y * 1),
fg_color=self.theme["bg_color"],
bg_color=self.theme["bg_color"],
corner_radius=0)
self.verifyNumb = self.root.register(helpers.isNumber)
self.mainFrame.grid(row=0, column=1)
self.root.title("SpaceNinGui CustomTK 1.0.0")
self.root.protocol("WM_DELETE_WINDOW", lambda: main.exit(self))
self.root.geometry(f"{str(self.x)}x{str(self.y)}")
self.root.resizable(width=False, height=False)
self.root.mainloop()
if __name__ == "__main__":
if isfile('sngconfig.json'):
main('sngconfig.json')
else:
install()
pass

BIN
cache/items/icons/placeholder.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -1,2 +0,0 @@
Requests==2.32.3
ttkthemes==3.2.2

206
subfiles/comunic.py Normal file
View File

@ -0,0 +1,206 @@
#communication stuff here
import requests
import json
from hashlib import sha256
from pathlib import Path
from shutil import copyfileobj
from . import helpers, savetools
from websockets.sync.client import connect
from subprocess import Popen, PIPE
from sys import platform
from os import listdir
from os.path import isfile, join, exists
import os
from pathlib import Path
import subprocess
def startClient(self, id):
cmd = f"steam://rungameid/{id}"
Popen(['steam', cmd])
def downloadLatestDll(self, filepath):
x = requests.get('https://openwf.io/supplementals/client%20drop-in/meta')
meta = json.loads(x.text)
url = f"https://openwf.io/supplementals/client%20drop-in/{meta['version']}/dwmapi.dll"#
content = requests.get(url, stream=True).content
hashofdll = sha256()
hashofdll.update(content)#
if hashofdll.hexdigest() == meta['sha256']:
print(filepath)
with open(filepath + "dwmapi.dll", "wb") as out_file:
out_file.write(content)
helpers.messageBox(self=self,title="Bootstrapper Downloaded", message="Bootstrapper Downloaded!", type="info")
else:
helpers.messageBox(self=self,title="Unknown Error.", message="SpaceninGUI could not verify the hash of the Bootstrapper. Sorry :(", type="error")#
def getLatestVersions(self, cacheFile, value):
ver = {
"server" : (
"no lol" #not finished update check for server, check back later :3
),
"client" : ""
}
#client code here
x = requests.get('https://openwf.io/supplementals/client%20drop-in/meta')
meta = json.loads(x.text)
ver["client"] = meta['version']
try:
oldVer = savetools.loadFile(self, cacheFile)["client"]
except:
with open('tempFile.json', 'w') as f:
json.dump({
"client":'notassigned',
'server':'notassigned'
},f,indent=2)
oldVer = savetools.loadFile(self, cacheFile)["client"]
if oldVer == ver["client"]:
client="Up To Date!"
else:
client="New Version " + ver["client"]
server = "server Check Not Implemented"
value[0].set("Latest Server Version: " + server)
value[1].set("Latest Client Version: " + client)
def startServer(self, cd, logArea): # To my knowledge, running the server in the main thread would stall the gui, fuck that lol
logmax = helpers.getLogMax(self, self.configFile)
logarr=[]
def mongo():
sysctl = Popen(['systemctl', 'start', 'mongodb'])
sysctl.wait()#
def execute(cd):
popen = Popen(['npm', 'run', 'dev'], stdin=PIPE, stdout=PIPE, universal_newlines=True, cwd=cd, preexec_fn=os.setsid)
self.popenThreads.append(popen)
for stdout_line in iter(popen.stdout.readline, ""):
yield stdout_line
popen.stdout.close()
return_code = popen.wait()
if return_code:
raise subprocess.CalledProcessError(return_code)#
def start(cd, logArea):
for path in execute(cd):
if len(logarr) < logmax:
logarr.append(path)
else:
logarr.pop(0)
logarr.append(path)
if logArea:
logArea.configure(state="normal")
logArea.delete(1.0, "end")
for element in logarr:
logArea.insert("end", element)
logArea.configure(state="disabled")
if platform == "linux":
if not self.popenThreads:
helpers.messageBox(self, title="MongoDB", message="The mongodb server is required to start SNS\nYou will need to give sudo permission for this.", type="info")
mongo()
start(cd, logArea)
else:
helpers.messageBox(self, title="Already Running!", message="The Server is already running!", type="info")
def getClientResponse():
try:
with connect("ws://localhost:6155") as websocket:
message = json.loads(websocket.recv())
except:
message=False
return message
def checkForClient(clientpath):
onlyfiles = [f for f in listdir(clientpath) if isfile(join(clientpath, f))]
if "dwmapi.dll" in onlyfiles:
return True
else:
return False
def runPluto(self, name, runningList):
openwfpath = self.clientPath + "/OpenWF/scripts/"
onlyfiles = [f for f in listdir(openwfpath) if isfile(join(openwfpath, f))]
print("called " + name)
if getClientResponse():
running = []
print(getClientResponse()["running_scripts"])
if name in running:
requests.get(url=("http://localhost:6155/stop_script?OpenWF/scripts/" + name))
else:
requests.get(url=("http://localhost:6155/start_script?OpenWF/scripts/" + name))
for script in getClientesponse()["running_scripts"]:
running.append(script.removeprefix("OpenWF/scripts/"))#
for file in onlyfiles:
if file in running:
if runningList[file]: runningList[file].set(True)
else:
if runningList[file]: runningList[file].set(False)
else:
if runningList[name]: runningList[name].set(False)
def getSnPath(file):
if Path(file).is_file():
with open(file) as f:
d = json.load(f)
return d["spaceninjapath"]
else:
return False
def openClientLogs(self, platform):
if platform=="linux":
print("ok")
helpers.messageBox(self, "")
def pushWeapon(self, string, slot):
if type(string) is list:
i=0
for part in string:
print(i)
pluto = f"gRegion:GetLocalPlayerAvatar():InventoryControl():RemoveItem({slot[i]}, true) gRegion:GetLocalPlayerAvatar():GiveItem(Type(\"{part}\"), true)"
requests.get(f"http://localhost:61558/start_script_inline?{pluto}")
if slot[i] == 3:
level = f"gRegion:GetLocalPlayerAvatar():InventoryControl():GetActivePowerSuit():SetXP(1600000)"
else:
level = f"gRegion:GetLocalPlayerAvatar():InventoryControl():GetWeaponInHand({slot[i]}):SetXP(1600000)"
requests.get(f"http://localhost:61558/start_script_inline?{level}")
i+=1
else:
pluto = f"gRegion:GetLocalPlayerAvatar():InventoryControl():RemoveItem({slot}, true) gRegion:GetLocalPlayerAvatar():GiveItem(Type(\"{string}\"), true) gRegion:GetLocalPlayerAvatar():InventoryControl():GetWeaponInHand({slot}):SetXP(1600000)"
requests.get(f"http://localhost:61558/start_script_inline?{pluto}")
def pushInline(self, Area):
#format
formatted = Area.get(0.0, "end").replace("\n", ' ')
requests.get(f"http://localhost:61558/start_script_inline?{formatted}")
def getWarframeExports(self, path):
exportList = {
"weapons":"https://raw.githubusercontent.com/calamity-inc/warframe-public-export/refs/heads/senpai/ExportWeapons_en.json",
"powersuits":"https://raw.githubusercontent.com/calamity-inc/warframe-public-export/refs/heads/senpai/ExportWarframes_en.json"
}
for export in exportList.keys():
helpers.folderExist(path)
with open(path + f"{export}.json", "wb") as out_file:
content = requests.get(exportList[export], stream=True).content
out_file.write(content)
def getWarframeExportsPlus(self, path):
exportList = {
"weapons":"https://raw.githubusercontent.com/calamity-inc/warframe-public-export-plus/refs/heads/senpai/ExportWeapons.json",
"powersuits":"https://raw.githubusercontent.com/calamity-inc/warframe-public-export-plus/refs/heads/senpai/ExportWarframes.json"
}
for export in exportList.keys():
helpers.folderExist((path+"/plus/").replace("//", "/"))
with open((path + f"/plus/{export}.json").replace('//', '/'), "wb") as out_file:
content = requests.get(exportList[export], stream=True).content
out_file.write(content)
def getIconDownload(self, path, savePath):
if not exists("./cache/items/icons" + savePath.rsplit('/', 1)[0]):
Path("./cache/items/icons" + savePath.rsplit('/', 1)[0]).mkdir(parents=True, exist_ok=True)
with open("./cache/items/icons" + savePath, "wb+") as out_file:
print(f"https://browse.wf{savePath}")
out_file.write(requests.get(f"https://browse.wf{savePath}").content)
print(f"Saved {path} Icon")

160
subfiles/helpers.py Normal file
View File

@ -0,0 +1,160 @@
from CTkMessagebox import CTkMessagebox
import threading
from .savetools import loadFile
from pathlib import Path
from .comunic import getIconDownload
import os
import signal
import json
from PIL import Image
try:
from os import startfile
except:
from os import system
from sys import platform
def killPopen(popen): #jesus
os.kill(os.getpgid(popen.pid), signal.SIGTERM)
def folderExist(path):
Path(path).mkdir(parents=True, exist_ok=True)
def check():
print("Save Good")
def removeChildren(frame):
for element in frame.winfo_children():
element.destroy()
def bgThread(func, args):
th = threading.Thread(target=func, args=args)
th.start()
def openLocation(self, location):
if platform == "linux":
system('xdg-open "%s"' % location)
elif platform == "windows":
startfile(foldername)
def messageBox(self, title, message, type): #type will be implemented at a later point when required. for now, just fill it in irregardless.
CTkMessagebox(title=title, message=message)
def getLogMax(self, save):
return loadFile(self, save)['maxlogsize'] #not entirely sure why I made this a seperate function but eh
def isNumber(data):
if data == '':
return True
try:
rv = int(data)
except ValueError:
return False
return True
def formatExportWeapons(self, file1):
log = open("log.txt", "a")
testfile = open("test1.json", 'w')
if open(file1):
print("opened")
with open(file1, 'r') as file:
data=json.load(file)["ExportWeapons"]
redund = []
for diction in range(len(data)):
for key in list(data[diction].keys()):
if key not in ["name", "slot", "uniqueName"]:
del data[diction][key]
print("deleted " + str(data[diction]["name"] + ' ' + key))
if 'slot' not in data[diction].keys():
redund.append(diction)
i=0
for diction in redund:
i+=1
print("Removed Unneeded Modular " + str(data[diction-i]["name"]), file=log)
del data[diction-i]
def sortFunc(e):
return e["name"]
data.sort(key=sortFunc)
json.dump(data, testfile, indent=2)
return data
def formatExportPowersuits(self, file1):
log = open("log.txt", "a")
testfile = open("test2.json", 'w')
if open(file1):
print("opened")
with open(file1, 'r') as file:
data=json.load(file)["ExportWarframes"]
redund = []
for diction in range(len(data)):
for key in list(data[diction].keys()):
if key not in ["name", "productCategory", "uniqueName"]:
del data[diction][key]
print("deleted " + str(data[diction]["name"] + ' ' + key))
def sortFunc(e):
return e["name"]
data.sort(key=sortFunc)
json.dump(data, testfile, indent=2)
return data
def formatExportPlus(self, file1):
with open(file1, 'r') as file:
data=json.load(file)
write = False
for item in data.keys():
print(data[item])
if type(data[item]) is dict:
icon = data[item]["icon"]
print(data[item])
data[item] = icon
write=True
if write == True:
with open(file1, 'w') as file:
json.dump(data, file, indent=2)
return data
def getIcon(self, path, savePath):
try:
image = Image.open("./cache/items/icons" + savePath)
return image
except:
getIconDownload(self, path, savePath)
return Image.open("./cache/items/icons" + savePath)
#Old Helper options, left here for future reference. Shitty code, but it works, and it may be useful in the future
# def getlogmax():
# file = 'sngconfig.json'
# if Path(file).is_file():
# with open(file) as f:
# d = json.load(f)
#
# else:
# return False
# def check4sn(configfile):
# file = helpers.getsnpath(configfile) + "package.json"
# if Path(file).is_file():
# with open(file) as f:
# d = json.load(f)
# if (d["name"] == "wf-emulator"):
# return True
# else:
# return False#

23
subfiles/install.py Normal file
View File

@ -0,0 +1,23 @@
def check():
print("install Good")
def installFiles(self, clientpath, serverpath):
#first install server
self.installstep.set("Downloading Server Through Git")
sysctl = Popen(['git', 'clone', 'https://openwf.io/SpaceNinjaServer.git', serverpath])
self.installprog.set(1)
sysctl.wait()
self.installstep.set("Installing Server Requirements (via npm)")
self.installprog.set(25)
sysctl = Popen(["npm", '--prefix', f'{serverpath}', 'install'])
sysctl.wait()
self.installstep.set("Copying Config File")
shutil.copy(serverpath + "/config.json.example", serverpath + "/config.json")
self.installstep.set("Starting Bootstrapper Download")
self.installprog.set(50)
print("Server install worked. ")
helpers.downloadlatestdll(clientpath)
self.installprog.set(99)
self.installstep.set("Install Complete!\nPress next then restart to get started!")

55
subfiles/savetools.py Normal file
View File

@ -0,0 +1,55 @@
import json
def check():
print("Save Check Good")
# Yea I know this is pretty pointless in a seperate file but it's nice to have these things
def loadFile(self, file1):
with open(file1, "r") as file:
data = json.load(file)
return data
def saveFile(self, newData, file):
with open(file, "r") as file1:
data = json.load(file1)
def anotherRecusion(data, newData):
if type(data) is dict:
for key in newData:
match data[key]:
case str():
data[key]=newData[key].get()
case bool():
data[key]=newData[key].get()
case int():
data[key]=int(newData[key].get())
case dict():
data[key] = anotherRecusion(data[key], newData[key])
case list():
data[key]= anotherRecusion(data[key], newData[key])
elif type(data) is list:
for key in range(len(newData)):
match data[key]:
case str():
data[key]=newData[key].get()
case bool():
data[key]=newData[key].get()
case int():
data[key]=int(newData[key].get())
case dict():
data[key] = anotherRecusion(data[key], newData[key])
case list():
data[key]= anotherRecusion(data[key], newData[key])
return data
data = anotherRecusion(data, newData)
print(data)
with open(file, "w") as file1:
json.dump(data, file1, indent=2)

44
subfiles/themes.py Normal file
View File

@ -0,0 +1,44 @@
def getThemes(self):
themes = {
"black_orange" : {
"fg_color" : "#000000",
"bg_color" : "#14213D",
"bg_deep" : "#121e37",
"border_color" : "#14213D",
"highlight_color" : '#FCA311',
"text_color" : ""
},
"kiln" : {
"fg_color" : "#5A2901",
"bg_color" : "#AE6F3B",
"bg_deep" : "#885599",
"border_color" : "#AE6F3B",
"highlight_color" : '#246868',
"text_color" : ""
},
"mint_nebula" : {
"fg_color" : "#15001F",
"bg_color" : "#2F0047",
"bg_deep" : "#440066",
"border_color" : "#6B3E00",
"highlight_color" : '#00683E',
"text_color" : ""
},
"antimatter" : {
"fg_color" : "#13002C",
"bg_color" : "#2F036A",
"bg_deep" : "#22014E",
"border_color" : "#2F026A",
"highlight_color" : '#9C8E00',
"text_color" : ""
},
"fenix" : {
"fg_color" : "#451D08",
"bg_color" : "#73300D",
"bg_deep" : "#73300D",
"border_color" : "##A14312",
"highlight_color" : '#083045',
"text_color" : ""
}
}
return themes