SHOW:
|
|
- or go back to the newest paste.
1 | --[[ | |
2 | Super Text Downloader by EldidiStroyrr/LDDestroier | |
3 | ||
4 | The purpose of this program is to have a single | |
5 | unified download script for ComputerCraft, as opposed | |
6 | to making multiple programs, each able to download from one site. | |
7 | ||
8 | The main aspect to make this script more modular is having | |
9 | a table (websiteSyntaxes) to store the website that it downloads | |
10 | from, as well as what abbreviation it's called with and the | |
11 | syntax of the raw download URL. | |
12 | Later updates added special prefixes that act in different ways | |
13 | that could not work with the standard syntax. | |
14 | ||
15 | pastebin get 3PBKGR4k std | |
16 | std ld std std | |
17 | ||
18 | This is a beta. You fool! | |
19 | Working on: | |
20 | +multi-file download handling | |
21 | +fixing bugs (namely, use of Discover and OnlineAPPS) | |
22 | - | ["STD"] = "https://raw.githubusercontent.com/LDDestroier/STD-GUI/master/list.lua", --stock |
22 | + | |
23 | - | ["Discover"] = "https://pastebin.com/raw/9bXfCz6M", --owned by dannysmc95 |
23 | + | |
24 | - | --["OnlineAPPS"] = "https://pastebin.com/raw/g2EnDYLp", --owned by Twijn, but discontinued |
24 | + | |
25 | - | ["STD-Media"] = "https://pastebin.com/raw/3JZHXTGL" --non-program media files |
25 | + | |
26 | std.channelURLs = { --special URLs for getting a list of files. | |
27 | ["STD"] = "http://pastebin.com/raw/zVws7eLq", --stock | |
28 | ["Discover"] = "http://pastebin.com/raw/9bXfCz6M", --owned by dannysmc95 | |
29 | ["OnlineAPPS"] = "http://pastebin.com/raw/g2EnDYLp", --owned by Twijn | |
30 | } | |
31 | local goodchan = false | |
32 | for k,v in pairs(std.channelURLs) do | |
33 | if std.channel == k then | |
34 | goodchan = true | |
35 | break | |
36 | end | |
37 | end | |
38 | - | std.std_version = 1.453 --Number, not string! |
38 | + | |
39 | std.channel = "STD" | |
40 | end | |
41 | std.prevChannel = std.channel | |
42 | std.std_version = 1.451 --Number, not string! | |
43 | std.stdList = "/."..std.channel:lower().."_list" --String, path of store listings | |
44 | std.websiteList = "/.std_websites" --String, path of website listings | |
45 | local doStore = true --If you do 'std ld', should you open up the store? Or just fuck off? | |
46 | std.serious = true | |
47 | ||
48 | local logo = {[[ | |
49 | __________________________ | |
50 | / ___________ ______ ____ \ | |
51 | / / | | | | \ \ | |
52 | \ \______ | | | | | | | |
53 | \______ \ | | | | | | | |
54 | \ \ | | | | | | | |
55 | ______/ / | | | |___/ / | |
56 | /_______/ |_| |______/ | |
57 | Super Text Downloader | |
58 | ||
59 | ]],[[ | |
60 | LLL LLLLL LLL | |
61 | L L L L L | |
62 | L L L L | |
63 | LLL L L L | |
64 | L L L L | |
65 | L L L L L | |
66 | LLL L LLL | |
67 | Super Text Downloader]] | |
68 | - | -- start Base64 |
68 | + | |
69 | - | local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" |
69 | + | |
70 | - | local encode = function(data) |
70 | + | |
71 | - | return ((data:gsub('.', function(x) |
71 | + | |
72 | - | local r,b='',x:byte() |
72 | + | |
73 | - | for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end |
73 | + | |
74 | - | return r; |
74 | + | |
75 | - | end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) |
75 | + | |
76 | - | if (#x < 6) then return '' end |
76 | + | |
77 | - | local c=0 |
77 | + | |
78 | - | for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end |
78 | + | |
79 | - | return b:sub(c+1,c+1) |
79 | + | |
80 | - | end)..({ '', '==', '=' })[#data%3+1]) |
80 | + | |
81 | end | |
82 | - | local decode = function(data) |
82 | + | |
83 | - | data = string.gsub(data, '[^'..b..'=]', '') |
83 | + | |
84 | - | return (data:gsub('.', function(x) |
84 | + | |
85 | - | if (x == '=') then return '' end |
85 | + | |
86 | - | local r,f='',(b:find(x)-1) |
86 | + | |
87 | - | for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end |
87 | + | |
88 | - | return r; |
88 | + | |
89 | - | end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) |
89 | + | |
90 | - | if (#x ~= 8) then return '' end |
90 | + | |
91 | - | local c=0 |
91 | + | |
92 | - | for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end |
92 | + | |
93 | - | return string.char(c) |
93 | + | |
94 | - | end)) |
94 | + | |
95 | table.insert(output, {key,value}) | |
96 | - | -- finished Base64 |
96 | + | |
97 | return output | |
98 | end | |
99 | ||
100 | local function displayHelp(mode) | |
101 | if mode == 1 then | |
102 | print("std <abbr> <fileid> [output]") | |
103 | print("Do 'std list' to see all codes") | |
104 | print("Do 'std ld' for a GUI") | |
105 | write("Channel '") | |
106 | if term.isColor() then term.setTextColor(colors.yellow) end | |
107 | write(std.channel) | |
108 | term.setTextColor(colors.white) | |
109 | print("' is selected.") | |
110 | elseif mode == 2 then | |
111 | if std.serious then | |
112 | print("List of website codes:") | |
113 | else | |
114 | print("all ur codes:") | |
115 | end | |
116 | std.websiteSyntaxes["dd"] = {} --Filler | |
117 | std.websiteSyntaxes["PB"] = {} --Filler | |
118 | for k,v in pairs(std.websiteSyntaxes) do | |
119 | if term.getTextColor then prevColor = term.getTextColor() else prevColor = colors.white end | |
120 | write(" '") | |
121 | if term.isColor() then term.setTextColor(colors.orange) end | |
122 | write(k) | |
123 | term.setTextColor(prevColor) | |
124 | write("' ") | |
125 | if k == "dd" then | |
126 | print("direct download") | |
127 | elseif k == "PB" then | |
128 | print("pastebin.com (safe)") | |
129 | elseif string.find(v.url,"/") then | |
130 | start = string.find(v.url,"://")+3 | |
131 | finish = string.find(v.url,"/",9)-1 | |
132 | print(string.sub(v.url,start,finish)) | |
133 | end | |
134 | end | |
135 | elseif mode == 3 then | |
136 | print(logo[pocket and 2 or 1]) | |
137 | end | |
138 | end | |
139 | ||
140 | local function choice(input) --A useful function for input. Similar to the MS-DOS 6.0 command. | |
141 | local event, key | |
142 | repeat | |
143 | event, key = os.pullEvent("key") | |
144 | - | std.websiteSyntaxes["dd64"] = {} |
144 | + | |
145 | - | std.websiteSyntaxes["PB"] = {} |
145 | + | |
146 | until string.find(string.lower(input), string.lower(key)) | |
147 | return string.lower(key) | |
148 | end | |
149 | ||
150 | --This list of websites is used as a backup, should you not be able to connect to pastebin. | |
151 | std.websiteSyntaxes = { | |
152 | pb = { | |
153 | url = "http://pastebin.com/raw.php?i=FILECODE", | |
154 | fullName = "Pastebin", | |
155 | - | elseif k == "dd64" then |
155 | + | |
156 | - | print("direct download + Base64") |
156 | + | |
157 | hb = { | |
158 | url = "http://hastebin.com/raw/FILECODE", | |
159 | fullName = "Hastebin", | |
160 | codeLength = 10, | |
161 | }, | |
162 | pe = { | |
163 | url = "http://pastie.org/pastes/FILECODE/download", | |
164 | fullName = "Pastie", | |
165 | codeLength = 0, | |
166 | }, | |
167 | fn = { | |
168 | url = "https://fnpaste.com/FILECODE/raw", | |
169 | fullName = "fnPaste", | |
170 | codeLength = 4, | |
171 | }, | |
172 | gh = { | |
173 | url = "https://raw.githubusercontent.com/FILECODE", | |
174 | fullName = "Github", | |
175 | codeLength = 0, | |
176 | }, | |
177 | gg = { | |
178 | url = "https://gist.githubusercontent.com/FILECODE/raw/", | |
179 | fullName = "Github Gist", | |
180 | codeLength = 0, | |
181 | }, | |
182 | sn = { | |
183 | - | url = "https://pastebin.com/raw.php?i=FILECODE", |
183 | + | |
184 | fullName = "Snippt", | |
185 | codeLength = 6, | |
186 | }, | |
187 | cp = { | |
188 | - | url = "https://hastebin.com/raw/FILECODE", |
188 | + | |
189 | fullName = "Codepad", | |
190 | codeLength = 8, | |
191 | }, | |
192 | id = { | |
193 | url = "http://ideone.com/plain/FILECODE", | |
194 | fullName = "Ideone", | |
195 | codeLength = 6, | |
196 | }, | |
197 | db = { | |
198 | url = "https://www.dropbox.com/s/FILECODE?raw=true", | |
199 | fullName = "Dropbox", | |
200 | codeLength = 0, | |
201 | }, | |
202 | dd = { | |
203 | url = "FILECODE", | |
204 | fullName = "Direct Download", | |
205 | codeLength = 0, | |
206 | }, | |
207 | } | |
208 | ||
209 | local tArg = {...} | |
210 | if shell then | |
211 | std_file = shell.getRunningProgram() | |
212 | else | |
213 | std_file = "" | |
214 | end | |
215 | ||
216 | local getTableSize = function(tbl) | |
217 | local amnt = 0 | |
218 | for k,v in pairs(tbl) do | |
219 | amnt = amnt + 1 | |
220 | end | |
221 | return amnt | |
222 | end | |
223 | - | url = "https://ideone.com/plain/FILECODE", |
223 | + | |
224 | std.getSTDList = function(prevChannel) | |
225 | local weburl = "http://pastebin.com/raw/FSCzZRUk" --URL of URL list. | |
226 | local storeurl = std.channelURLs[std.channel] --URL of store list. | |
227 | local webcontents = http.get(weburl) | |
228 | local storecontents = http.get(storeurl) | |
229 | if not (webcontents and storecontents) then | |
230 | if shell then | |
231 | print("Couldn't update list!") | |
232 | end | |
233 | return false, "Couldn't update list!" | |
234 | else | |
235 | local uut = runFile(std.stdList) | |
236 | if not uut then std.storeURLs = nil end | |
237 | local beforeSize = getTableSize(std.storeURLs or {}) | |
238 | local webprog = webcontents.readAll() | |
239 | local storeprog = storecontents.readAll() | |
240 | local webfile = fs.open(std.websiteList,"w") | |
241 | local storefile = fs.open(std.stdList,"w") | |
242 | webfile.writeLine(webprog) | |
243 | webfile.close() | |
244 | storefile.writeLine(storeprog) | |
245 | storefile.close() | |
246 | runFile(std.websiteList) | |
247 | local outcome = runFile(std.stdList) | |
248 | if outcome == false then | |
249 | std.channel = prevChannel | |
250 | return std.getSTDList("STD") | |
251 | end | |
252 | local afterSize = getTableSize(std.storeURLs or {}) | |
253 | return true, "Downloaded to "..std.stdList, afterSize-beforeSize | |
254 | end | |
255 | end | |
256 | ||
257 | if tArg[1] == "update" or not fs.exists(std.stdList) then | |
258 | local updateChan = tArg[2] | |
259 | if (updateChan) and (not std.channelURLs[updateChan]) and tArg[1] == "update" then | |
260 | printError("No such channel.") | |
261 | for k,v in pairs(std.channelURLs) do | |
262 | term.setTextColor(colors.white) | |
263 | write(" ") | |
264 | if k == std.channel then | |
265 | write("@") | |
266 | if term.isColor() then term.setTextColor(colors.yellow) end | |
267 | else | |
268 | write("O") | |
269 | end | |
270 | print(" "..k) | |
271 | - | |
271 | + | |
272 | term.setTextColor(colors.white) | |
273 | return | |
274 | end | |
275 | if std.serious then | |
276 | write("Updating list...") | |
277 | - | |
277 | + | |
278 | write("just a sec, gettin your repo...") | |
279 | end | |
280 | if updateChan and std.channelURLs[updateChan] then | |
281 | std.prevChannel = std.channel | |
282 | std.channel = updateChan | |
283 | - | return true, "Downloaded to "..std.stdList |
283 | + | |
284 | local success,_,diff = std.getSTDList(std.prevChannel) | |
285 | if not success then | |
286 | if std.serious then | |
287 | return printError("FAIL!") | |
288 | else | |
289 | return printError("IT'S NO USE!") | |
290 | end | |
291 | else | |
292 | if std.serious then | |
293 | write("good!") | |
294 | if diff > 0 then | |
295 | print(" (got "..diff.." new store entries)") | |
296 | else | |
297 | write("\n") | |
298 | end | |
299 | else | |
300 | write("yay!!") | |
301 | if diff > 0 then | |
302 | print(" (nao got "..diff.." moar shop things!)") | |
303 | else | |
304 | write("\n") | |
305 | end | |
306 | end | |
307 | if tArg[1] == "update" then return true end | |
308 | end | |
309 | end | |
310 | ||
311 | if not shell then return end | |
312 | ||
313 | local websiteCode = tArg[1] | |
314 | - | local success = std.getSTDList(std.prevChannel) |
314 | + | |
315 | local retrieveName = tArg[3] | |
316 | ||
317 | if (websiteCode == "list") and (not fileCode) then | |
318 | displayHelp(2) | |
319 | return false | |
320 | elseif (websiteCode == "you foolish fool") and (not fileCode) then | |
321 | displayHelp(3) | |
322 | return false | |
323 | - | print("good!") |
323 | + | |
324 | displayHelp(1) | |
325 | - | print("excellent!") |
325 | + | |
326 | end | |
327 | ||
328 | local getFile = function(filename,url) | |
329 | if fs.isReadOnly(filename) then | |
330 | return false, "access denied" | |
331 | end | |
332 | local prog | |
333 | if type(url) == "table" then | |
334 | prog = contextualGet(url[1]) | |
335 | else | |
336 | prog = http.get(url) | |
337 | end | |
338 | if not prog then | |
339 | return false, "could not connect" | |
340 | end | |
341 | prog = prog.readAll() | |
342 | local fyle = fs.open(filename,"w") | |
343 | fyle.write(prog) | |
344 | fyle.close() | |
345 | return true, fs.getSize(filename) | |
346 | end | |
347 | ||
348 | runFile(std.stdList) | |
349 | runFile(std.websiteList) | |
350 | ||
351 | local fileURL | |
352 | if websiteCode == "ld" then | |
353 | if not fileCode then | |
354 | if doStore then | |
355 | runURL("http://pastebin.com/raw/P9dDhQ2m") | |
356 | return | |
357 | else | |
358 | return print("GUI Store has been disabled.") | |
359 | end | |
360 | else | |
361 | if not std.storeURLs then | |
362 | if std.serious then | |
363 | write("Updating list...") | |
364 | else | |
365 | write("just a sec, gettin your repo...") | |
366 | end | |
367 | std.getSTDList() | |
368 | end | |
369 | if not std.storeURLs[fileCode] then | |
370 | - | local pastebinUpload = function(sName,sText) |
370 | + | |
371 | - | write( "Connecting to pastebin.com... " ) |
371 | + | |
372 | - | local key = "0ec2eb25b6166c0c27a394ae118ad829" |
372 | + | |
373 | - | local response = http.post( |
373 | + | |
374 | - | "http://pastebin.com/api/api_post.php", |
374 | + | |
375 | - | "api_option=paste&".. |
375 | + | |
376 | - | "api_dev_key="..key.."&".. |
376 | + | |
377 | - | "api_paste_format=lua&".. |
377 | + | |
378 | - | "api_paste_name="..textutils.urlEncode(sName).."&".. |
378 | + | |
379 | - | "api_paste_code="..textutils.urlEncode(sText) |
379 | + | |
380 | - | ) |
380 | + | fileURL = "http://pastebin.com/"..fileCode |
381 | - | if response then |
381 | + | |
382 | - | print( "Success." ) |
382 | + | |
383 | - | local sResponse = response.readAll() |
383 | + | |
384 | - | response.close() |
384 | + | return printError("FAIL!\n") |
385 | - | return string.match( sResponse, "[^/]+$" ) |
385 | + | |
386 | - | end |
386 | + | |
387 | print("GOOD!") | |
388 | term.setTextColor(colors.white) | |
389 | local rawget = prog.readAll() | |
390 | local s = string.find(rawget,"<textarea id=\"paste_code\"")+103 | |
391 | local e = string.find(rawget,"</textarea>")-1 | |
392 | local contents = string.gsub(string.sub(rawget,s,e),""","\"") | |
393 | contents = contents:gsub("<","<") | |
394 | contents = contents:gsub(">",">") | |
395 | if retrieveName and shell then | |
396 | local dlname = fs.combine(shell.dir(),retrieveName) | |
397 | if fs.exists(dlname) then | |
398 | if std.serious then | |
399 | print("'" .. dlname .. "' exists! Overwrite?") | |
400 | write("[Y,N]?") | |
401 | else | |
402 | print("yoo alreddy got a '"..dlname.."'!! redu eet?") | |
403 | write("[why,enn]??") | |
404 | end | |
405 | local key = choice("yn") | |
406 | print(string.upper(key)) | |
407 | if key == "n" then | |
408 | if std.serious then | |
409 | print("Cancelled.") | |
410 | else | |
411 | print("whatevz") | |
412 | end | |
413 | sleep(0) | |
414 | return false | |
415 | end | |
416 | end | |
417 | local file = fs.open(dlname, "w") | |
418 | file.writeLine(contents) | |
419 | - | fileURL = "https://pastebin.com/"..fileCode:sub(1,8) |
419 | + | |
420 | if std.serious then | |
421 | print("Done! DL'd " .. fs.getSize(dlname) .. " bytes.") | |
422 | else | |
423 | - | return printError("FAIL!") |
423 | + | |
424 | end | |
425 | else | |
426 | local func = loadstring(contents) | |
427 | setfenv(func, getfenv()) | |
428 | func() | |
429 | end | |
430 | sleep(0) | |
431 | return | |
432 | end | |
433 | else | |
434 | if not std.websiteSyntaxes[websiteCode] then | |
435 | if std.serious then | |
436 | return printError("Invalid website code '" .. websiteCode .. "'") | |
437 | else | |
438 | return printError("dat '"..websiteCode.."' is NAWT GUUD!!") | |
439 | end | |
440 | else | |
441 | if (std.websiteSyntaxes[websiteCode].codeLength == 0) or (not std.websiteSyntaxes[websiteCode].codeLength) then | |
442 | fileURL = string.gsub(std.websiteSyntaxes[websiteCode].url, "FILECODE", fileCode) | |
443 | else | |
444 | fileURL = string.gsub(std.websiteSyntaxes[websiteCode].url, "FILECODE", string.sub(fileCode,1,std.websiteSyntaxes[websiteCode].codeLength)) | |
445 | end | |
446 | end | |
447 | sleep(0) | |
448 | end | |
449 | ||
450 | if std.serious then | |
451 | write("Connecting to '" .. fileURL .. "'...") | |
452 | else | |
453 | if math.random(1,2) == 1 then | |
454 | write("gettin ze '"..fileURL.."'...") | |
455 | else | |
456 | write("commeptin to '"..fileURL.."' naow...") | |
457 | end | |
458 | end | |
459 | local contents = http.get(fileURL) | |
460 | if not contents then | |
461 | if term.isColor() then | |
462 | term.setTextColor(colors.red) | |
463 | end | |
464 | if std.serious then | |
465 | print("NOPE!") | |
466 | else | |
467 | print("NI!") | |
468 | end | |
469 | sleep(0) | |
470 | return false | |
471 | else | |
472 | - | elseif websiteCode == "dd64" then |
472 | + | |
473 | - | write("Conntecting to '"..fileCode.."'...") |
473 | + | |
474 | - | local cont = http.get(fileCode) |
474 | + | |
475 | - | local dlname = fs.combine(shell.dir(),retrieveName) |
475 | + | |
476 | - | if cont then |
476 | + | |
477 | if term.isColor() then | |
478 | term.setTextColor(colors.green) | |
479 | end | |
480 | - | cont = decode(cont.readAll()) |
480 | + | |
481 | - | local file = fs.open(dlname,"w") |
481 | + | |
482 | - | file.write(cont) |
482 | + | |
483 | print("gud!") | |
484 | end | |
485 | term.setTextColor(prevColor) | |
486 | if retrieveName and shell then | |
487 | local dlname = fs.combine(shell.dir(),retrieveName) | |
488 | if fs.exists(dlname) then | |
489 | - | return true |
489 | + | |
490 | print("'" .. dlname .. "' exists! Overwrite?") | |
491 | - | return printError("FAIL!") |
491 | + | |
492 | else | |
493 | - | elseif websiteCode == "pbupload" then |
493 | + | |
494 | - | fileCode = fs.combine("",fileCode) |
494 | + | |
495 | - | if not fs.exists(fileCode) then |
495 | + | |
496 | - | return printError("NO SUCH FILE!") |
496 | + | |
497 | print(string.upper(key)) | |
498 | - | local file = fs.open(fileCode,"r") |
498 | + | |
499 | - | local cont = file.readAll() |
499 | + | |
500 | print("Cancelled.") | |
501 | - | local sCode = pastebinUpload(fileCode,cont) |
501 | + | |
502 | - | if sCode then |
502 | + | |
503 | - | write("Uploaded with code:") |
503 | + | |
504 | - | if term.isColor() then term.setTextColor(colors.yellow) end |
504 | + | |
505 | - | print(sCode) |
505 | + | |
506 | end | |
507 | - | print("Don't forget it!") |
507 | + | |
508 | local file = fs.open(dlname, "w") | |
509 | file.writeLine(contents.readAll()) | |
510 | file.close() | |
511 | - | return true |
511 | + | |
512 | print("Done! DL'd " .. fs.getSize(dlname) .. " bytes.") | |
513 | - | elseif websiteCode == "pbupload64" then |
513 | + | |
514 | - | fileCode = fs.combine("",fileCode) |
514 | + | |
515 | - | if not fs.exists(fileCode) then |
515 | + | |
516 | - | return printError("NO SUCH FILE!") |
516 | + | |
517 | local contents = loadstring(contents.readAll()) | |
518 | - | local file = fs.open(fileCode,"r") |
518 | + | |
519 | - | local cont = encode(file.readAll()) |
519 | + | |
520 | end | |
521 | - | local sCode = pastebinUpload(fileCode,cont) |
521 | + | |
522 | - | if sCode then |
522 | + | |
523 | - | write("Uploaded with Base64 with code:") |
523 | + |