· 5 years ago · Jul 10, 2020, 08:00 PM
1local fs = require("filesystem")
2local term = require("term")
3
4local api = {
5 version = 1.1,
6 debugging = false
7}
8
9local callName = ""
10
11function api.setDebugging(value)
12 api.debugging = value
13end
14
15local function setCallName(value)
16 if callName == "" then
17 callName = value
18 end
19end
20
21local function getCallName()
22 return callName
23end
24
25local function resetCallName()
26 callName = ""
27end
28
29function api.handleError(prefix)
30 return function(err)
31 if prefix ~= nil then
32 prefix = prefix .. " "
33 end
34
35 print(prefix .. "Error: " .. err)
36
37 if api.debugging then
38 print(debug.traceback())
39 end
40 end
41end
42
43
44--[ API Utils ]--
45
46api.apis = {}
47
48local apiSources = {
49 pastebin = "pastebin",
50 github = "github"
51}
52
53local apiSourcePaths = {
54 [apiSources.pastebin] = "https://pastebin.com/raw/%s",
55 [apiSources.github] = "https://raw.githubusercontent.com/%s"
56}
57
58local apiOptions = {
59 -- 1st Party
60 bar = {
61 type = apiSources.pastebin,
62 path = "hmCLEdpH"
63 },
64 button = {
65 type = apiSources.pastebin,
66 path = "ivyWQqLg"
67 },
68 division = {
69 type = apiSources.pastebin,
70 path = "BHwuU95U"
71 },
72 tab = {
73 type = apiSources.pastebin,
74 path = "cE7vQiJN"
75 },
76
77 -- 3rd Party
78 json = {
79 type = apiSources.github,
80 path = "rxi/json.lua/master/json.lua"
81 }
82}
83
84local function apiFilePath(name, isLibrary)
85 isLibrary = isLibrary or false
86
87 if isLibrary then
88 return string.format("/lib/%s.lua", name)
89 end
90
91 return name
92end
93
94local function fetchRemoteSource(sourcePath, type, filePath)
95 if apiSourcePaths[type] == nil then
96 return false, string.format("%s is not a valid API source", type)
97 end
98
99 local remotePath = string.format(apiSourcePaths[type], sourcePath)
100
101 -- Use force override flag. If this function has been called it can be assumed the file is safe to overwrite
102 local command = string.format("wget -f \"%s\" %s >> /dev/null", remotePath, filePath)
103
104 return xpcall(
105 os.execute,
106 api.handleError("Get Remote API"),
107 command
108 )
109end
110
111function api.apis.exists(name, isLibrary)
112 local filePath = apiFilePath(name, isLibrary)
113
114 return fs.exists(filePath)
115end
116
117function api.apis.get(sourcePath, name, isLibrary, type, forceGet)
118 isLibrary = isLibrary or false
119 type = type or apiSources.pastebin
120 forceGet = forceGet or false
121
122 if api.apis.exists(name, isLibrary) and not forceGet then
123 return true
124 end
125
126 local filePath = apiFilePath(name, isLibrary)
127
128 local status, _ = fetchRemoteSource(sourcePath, type, filePath)
129
130 return status
131end
132
133function api.apis.load(sourcePath, name, type, forceGet)
134 package.loaded[name] = nil
135 local status = api.apis.get(sourcePath, name, true, type, forceGet)
136
137 if not status then
138 error(string.format("Failed to load %s API", name))
139 end
140
141 return require(name)
142end
143
144function api.apis.loadByName(name, forceGet)
145 if apiOptions[name] == nil then
146 error(string.format("No API with name %s found", name))
147 end
148
149 local apiOption = apiOptions[name]
150
151 return api.apis.load(apiOption.path, name, apiOption.type, forceGet)
152end
153
154
155--[ Table Utils ]--
156
157api.table = {}
158
159function api.table.contains(needle, haystack, returnOffset)
160 returnOffset = returnOffset or false
161
162 for offset, value in pairs(haystack) do
163 if value == needle then
164 if retturnOffset then
165 return offset
166 end
167
168 return true
169 end
170 end
171
172 if returnOffset then
173 return nil
174 end
175
176 return false
177end
178
179function api.table.keys(tableParam)
180 local keys = {}
181
182 for key, _ in pairs(tableParam) do
183 table.insert(keys, key)
184 end
185
186 return keys
187end
188
189function api.table.values(tableParam)
190 local values = {}
191
192 for _, value in pairs(tableParam) do
193 table.insert(values, value)
194 end
195
196 return values
197end
198
199function api.table.concat(tableParam, indent)
200 indent = indent or 0
201
202 local output = ""
203
204 for key, value in pairs(tableParam) do
205 local stringValue = value
206
207 if type(value) == "table" then
208 stringValue = "\n" .. api.table.concat(value, indent + 1)
209 end
210
211 output = output .. string.rep("\t", indent) .. string.format("%s: %s\n", key, stringValue)
212 end
213
214 return output
215end
216
217
218--[ Color Manager Class ]--
219
220local ColorManager = {
221 gpu = nil,
222
223 backgroundColor = nil,
224 backgroundIsPalette = false,
225 foregroundColor = nil,
226 foregroundIsPalette = false
227}
228
229function ColorManager:new(gpu)
230 if gpu == nil then
231 error("ColorManager - Missing required parameter: gpu")
232 end
233
234 local colorManager = {}
235 setmetatable(colorManager, self)
236 self.__index = self
237
238 self.gpu = gpu
239
240 return colorManager
241end
242
243function ColorManager:save()
244 self.backgroundColor, self.backgroundIsPalette = self.gpu.getBackground()
245 self.foregroundColor, self.foregroundIsPalette = self.gpu.getForeground()
246end
247
248function ColorManager:restore()
249 if self.backgroundColor ~= nil then
250 self.gpu.setBackground(self.backgroundColor, self.backgroundIsPalette)
251
252 self.backgroundColor = nil
253 self.backgroundIsPalette = false
254 end
255
256 if self.foregroundColor ~= nil then
257 self.gpu.setForeground(self.foregroundColor, self.foregroundIsPalette)
258
259 self.backgroundColor = nil
260 self.backgroundIsPalette = false
261 end
262end
263
264api.ColorManager = ColorManager
265
266
267--[ Command Handlers ]--
268
269local originalPath = "/lib/event.lua"
270local unpatchedPath = "/lib/event_unpatched.lua"
271
272local validCommands = {
273 "patch",
274 "unpatch",
275 "getApi"
276}
277
278local function commandPatch(args)
279 if fs.exists(unpatchedPath) then
280 print(string.format("Unpatched file already exists at %s", unpatchedPath))
281 print("Unpatch command should be used before applying the patch")
282
283 return
284 end
285
286 -- Move the old event.lua
287 fs.rename(originalPath, unpatchedPath)
288
289 -- Download patched event.lua
290 print(string.format("Downloading patched %s", originalPath))
291
292 api.apis.get("V7k0adVW", "event", true)
293
294 print(string.format("Successfully patched %s", originalPath))
295end
296
297local function commandUnpatch(args)
298 if not fs.exists(unpatchedPath) then
299 print(string.format("Unable to locate unpatched files at %s", unpatchedPath))
300
301 return
302 end
303
304 fs.remove(originalPath)
305 fs.rename(unpatchedPath, originalPath)
306
307 print(string.format("Successfully unpatched %s", originalPath))
308end
309
310local function commandGetApi(args)
311 local apiName = args[2]
312
313 if apiOptions[apiName] == nil then
314 if apiName ~= nil then
315 print(string.format("No API found with name %s", apiName))
316 else
317 print("No API name provided")
318 end
319
320 print(string.format("Try: %s", table.concat(api.table.keys(apiOptions), ", ")))
321
322 return
323 end
324
325 print(string.format("Downloading %s API to /lib/%s.lua", apiName, apiName))
326
327 local apiOption = apiOptions[apiName]
328
329 if api.apis.get(apiOption.path, apiName, apiOption.type, true) then
330 print(string.format("Successfully downloaded %s API", apiName))
331 else
332 print(string.format("Failed to download %s API. Please try again", apiName))
333 end
334end
335
336local function handleCommand(args)
337 local command = args[1]
338
339 if command == "patch" then
340 commandPatch(args)
341 elseif command == "unpatch" then
342 commandUnpatch(args)
343 elseif command == "getApi" then
344 commandGetApi(args)
345 else
346 print(string.format("Unknown command: %s", command))
347 print(string.format("Try: %s", table.concat(validCommands, ", ")))
348 end
349end
350
351--[ Functional Code ]--
352
353local args = { ... }
354
355if #args ~= 0 and args[1] ~= "bioUtil" then
356 handleCommand(args)
357end
358
359return api