· 2 years ago · Oct 31, 2022, 05:30 AM
1local REPO_API = "https://api.github.com"
2local REPO_PATH = "/repos/IronicPickle/cc-store/contents"
3local GITHUB_ACCESS_TOKEN = "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"
4
5local REPO_FULL = REPO_API..REPO_PATH
6
7local PROGRAM = ""
8local ARGS = ""
9local DIR = ""
10local CHANNEL = ""
11
12local function decode64(data)
13 local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
14 data = string.gsub(data, '[^'..b..'=]', '')
15 return (data:gsub('.', function(x)
16 if (x == '=') then return '' end
17 local r,f='',(b:find(x)-1)
18 for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
19 return r
20 end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
21 if (#x ~= 8) then return '' end
22 local c=0
23 for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
24 return string.char(c)
25 end))
26end
27
28local function getFileFromRepo(file)
29 local res = http.get(REPO_FULL..file, {
30 ["Authorization"] = "token "..GITHUB_ACCESS_TOKEN,
31 })
32 if res == nil then return nil end
33 local body = textutils.unserialiseJSON(res.readAll())
34 local content = body.content
35 res.close()
36 if content == nil then
37 return nil
38 end
39 return decode64(content)
40end
41
42local function createRootDir()
43 print(" > Creating root directory "..DIR)
44
45 fs.makeDir(DIR)
46end
47
48local function getSyncServer()
49 print(" > Downloading sync client")
50
51 local content = getFileFromRepo("/syncServer.lua")
52 if content == nil then
53 error("Critical error, could not download sync client!")
54 end
55
56 local f = fs.open(DIR.."/syncServer.lua", "w")
57 f.write(content)
58 f.close()
59
60end
61
62local function generateStartupScript()
63 print(" > Generating startup script")
64
65 local programPath = DIR.."/programs/"..PROGRAM
66
67 local content = DIR..'/syncServer.lua "'..programPath..' '..ARGS..'"'
68
69 local f = fs.open("/startup.lua", "w")
70 f.write("")
71 f.writeLine("local CLI_ARGS = { ... }")
72 f.writeLine("local DO_SETUP = CLI_ARGS[1] == '--setup'")
73 f.writeLine("")
74 f.writeLine("local CHANNEL = \""..CHANNEL.."\"")
75 f.writeLine("local REPO_FULL = \""..REPO_FULL.."\"")
76 f.writeLine("local GITHUB_ACCESS_TOKEN = \""..GITHUB_ACCESS_TOKEN.."\"")
77 f.writeLine("local DIR = \""..DIR.."\"")
78 f.writeLine("local PROGRAM = \""..PROGRAM.."\"")
79 f.writeLine("local PROGRAM_ARGS = \""..ARGS.."\"")
80 f.writeLine("")
81 f.writeLine("shell.run(DIR..'/syncServer.lua '..CHANNEL..' '..REPO_FULL..' '..GITHUB_ACCESS_TOKEN..' '..DIR..' '..PROGRAM..' \"'..PROGRAM_ARGS..'\" '..tostring(DO_SETUP))")
82 f.close()
83end
84
85local function install()
86 term.clear()
87 print("\n> Running install")
88 createRootDir()
89 getSyncServer()
90 generateStartupScript()
91 print("\n> Install complete")
92
93 print("\nRun /startup.lua to start")
94end
95
96local function checkRepoReachable()
97 print(" > Checking repo is reachable")
98
99 if not http.checkURL(REPO_API) then
100 error("Repo URL not whitelisted")
101 end
102
103 if getFileFromRepo("/README.md") == nil then
104 error("Repo doesn't exist")
105 end
106
107 print(" < Repo successfully reached")
108end
109
110local function checkRepoContainsSyncServer()
111 print(" > Checking repo for syncServer.lua")
112
113 if getFileFromRepo("/syncServer.lua") == nil then
114 error("Sync Server doesn't exist on repo")
115 end
116
117 print(" < syncServer.lua found in repo")
118end
119
120local function splitArgs(content)
121 local argsString = content:match("$ARGS(.-)$ARGS")
122 if argsString == nil then return {} end
123 local matches = string.gmatch(argsString, "([^|]+)")
124 local args = {}
125 for str in matches do
126 local default = str:match("%((.-)%)")
127 table.insert(args, { name = str, default = default })
128 end
129 return args
130end
131
132local function urlEncode(url)
133 if url == nil then
134 return
135 end
136 url = url:gsub("\n", "\r\n")
137 url = url:gsub("([^%w ])", function(char) return string.format("%%%02X", string.byte(char)) end)
138 --url = url:gsub(" ", "+")
139 return url
140end
141
142local function readInput(prefix)
143 if prefix == nil then prefix = " ->" end
144 print(prefix)
145 _, y = term.getCursorPos()
146 term.setCursorPos(#prefix + 2, y - 1)
147 local input = read()
148 print("")
149 return urlEncode(input)
150end
151
152local function readArgs(args)
153 local readArgsString = ""
154 for _,arg in pairs(args) do
155 print(" | "..arg.name)
156 local input = readInput(" | ->")
157 if #input == 0 then input = arg.default end
158 readArgsString = readArgsString.." "..(input or "")
159 end
160 return readArgsString
161end
162
163local function checkRepoContainsProgram()
164 print(" > Checking repo for "..PROGRAM)
165
166 local content = getFileFromRepo("/programs/"..PROGRAM)
167
168 if content == nil then
169 error("Program doesn't exist on repo")
170 end
171
172 print(" < Found "..PROGRAM.." in repo")
173
174 return content
175end
176
177
178local function setup()
179 term.clear()
180 print("> Script Configuration")
181 print(" - Repo API: "..REPO_API)
182 print(" - Repo Path: "..REPO_PATH)
183 checkRepoReachable()
184 checkRepoContainsSyncServer()
185
186 print("\n> Further Configuration Required")
187 print(" - Program Name [name] (do not include .lua)")
188 PROGRAM = readInput()..".lua"
189 local argsTable = splitArgs(checkRepoContainsProgram())
190 if #argsTable > 0 then
191 print(" - Program Arguments\n")
192 ARGS = readArgs(argsTable)
193 else
194 print(" - No program arguments found, skipping...\n")
195 end
196 print(" - Root Directory (/lua)")
197 DIR = readInput()
198 if #DIR == 0 then DIR = "/lua" end
199 print(" - Sync Server Channel (40100)")
200 CHANNEL = readInput()
201 if #CHANNEL == 0 then CHANNEL = "40100" end
202
203 term.clear()
204
205 print("\n> Configuration")
206 print(" - Program: "..PROGRAM..ARGS)
207 print(" - Root Directory: "..DIR)
208 print(" - Sync Server Channel: "..CHANNEL)
209
210 print("\nPress any key to run install")
211 read()
212
213 install()
214end
215
216setup()