diff --git a/sys/apis/http/pastebin.lua b/sys/apis/http/pastebin.lua new file mode 100644 index 0000000..54f5b24 --- /dev/null +++ b/sys/apis/http/pastebin.lua @@ -0,0 +1,150 @@ + +--- Attempts to guess the pastebin ID from the given code or URL +local function extractId(paste) + local patterns = { + "^([%a%d]+)$", + "^https?://pastebin.com/([%a%d]+)$", + "^pastebin.com/([%a%d]+)$", + "^https?://pastebin.com/raw/([%a%d]+)$", + "^pastebin.com/raw/([%a%d]+)$", + } + + for i = 1, #patterns do + local code = paste:match( patterns[i] ) + if code then return code end + end + + return nil +end + +function download(url) + if type( url ) ~= "string" then + error( "bad argument #1 (expected string, got " .. type( url ) .. ")", 2 ) + end + + if not http then + return false, "Pastebin requires http API" + end + + local paste = extractId( url ) + if not paste then + return false, "Invalid pastebin code. The code is the ID at the end of the pastebin.com URL." + end + + -- Add a cache buster so that spam protection is re-checked + local cacheBuster = ("%x"):format(math.random(0, 2^30)) + local response, err = http.get( + "https://pastebin.com/raw/"..textutils.urlEncode( paste ).."?cb="..cacheBuster + ) + + if not response then + return response, err + end + + -- If spam protection is activated, we get redirected to /paste with Content-Type: text/html + local headers = response.getResponseHeaders() + if not headers["Content-Type"] or not headers["Content-Type"]:find( "^text/plain" ) then + return false, "Pastebin blocked the download due to spam protection. Please complete the captcha in a web browser: https://pastebin.com/" .. textutils.urlEncode( paste ) + end + + local sResponse = response.readAll() + response.close() + return sResponse +end + +local function put(sPath) + if type( sPath ) ~= "string" then + error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 ) + end + + if not http then + return false, "Pastebin requires http API" + end + + -- Upload a file to pastebin.com + -- Determine file to upload + if not fs.exists( sPath ) or fs.isDir( sPath ) then + return false, "No such file" + end + + -- Read in the file + local sName = fs.getName( sPath ) + local file = fs.open( sPath, "r" ) + local sText = file.readAll() + file.close() + + -- POST the contents to pastebin + local key = "0ec2eb25b6166c0c27a394ae118ad829" + local response = http.post( + "https://pastebin.com/api/api_post.php", + "api_option=paste&".. + "api_dev_key="..key.."&".. + "api_paste_format=lua&".. + "api_paste_name="..textutils.urlEncode(sName).."&".. + "api_paste_code="..textutils.urlEncode(sText) + ) + + if response then + local sResponse = response.readAll() + response.close() + + return string.match( sResponse, "[^/]+$" ) + end + return false, "Failed." +end + +local function get(sCode, sPath) + if type( sCode ) ~= "string" then + error( "bad argument #1 (expected string, got " .. type( sCode ) .. ")", 2 ) + end + + if type( sPath ) ~= "string" then + error( "bad argument #2 (expected string, got " .. type( sPath ) .. ")", 2 ) + end + + if not http then + return false, "Pastebin requires http API" + end + + if fs.exists( sPath ) then + return false, "File already exists" + end + + -- GET the contents from pastebin + local res, msg = download(sCode) + if not res then + return res, msg + end + + local file = fs.open( sPath, "w" ) + file.write( res ) + file.close() + + return sPath +end + +local function run(sCode, ...) + if not http then + return false, "Pastebin requires http API" + end + + if type( sCode ) ~= "string" then + error( "bad argument #1 (expected string, got " .. type( sCode ) .. ")", 2 ) + end + + local res, msg = download(sCode) + if not res then + return res, msg + end + local func, err = load(res, sCode, "t", _ENV) + if not func then + return func, err + end + return pcall(func, ...) +end + +return { + get = get, + put = put, + run = run, +} \ No newline at end of file diff --git a/sys/apis/pastebin.lua b/sys/apis/pastebin.lua deleted file mode 100644 index d78c10c..0000000 --- a/sys/apis/pastebin.lua +++ /dev/null @@ -1,146 +0,0 @@ - ---- Attempts to guess the pastebin ID from the given code or URL -local function extractId(paste) - local patterns = { - "^([%a%d]+)$", - "^https?://pastebin.com/([%a%d]+)$", - "^pastebin.com/([%a%d]+)$", - "^https?://pastebin.com/raw/([%a%d]+)$", - "^pastebin.com/raw/([%a%d]+)$", - } - - for i = 1, #patterns do - local code = paste:match( patterns[i] ) - if code then return code end - end - - return nil -end - -function download(url) - if not http then - return false, "Pastebin requires http API" - end - - if type( url ) ~= "string" then - error( "bad argument #1 (expected string, got " .. type( url ) .. ")", 2 ) - end - - local paste = extractId( url ) - if not paste then - return false, "Invalid pastebin code." - end - - -- Add a cache buster so that spam protection is re-checked - local cacheBuster = ("%x"):format(math.random(0, 2^30)) - local response, err = http.get( - "https://pastebin.com/raw/"..textutils.urlEncode( paste ).."?cb="..cacheBuster - ) - - if response then - -- If spam protection is activated, we get redirected to /paste with Content-Type: text/html - local headers = response.getResponseHeaders() - if not headers["Content-Type"] or not headers["Content-Type"]:find( "^text/plain" ) then - return false, "Pastebin blocked the download due to spam protection. Please complete the captcha in a web browser: https://pastebin.com/" .. textutils.urlEncode( paste ) - end - - local sResponse = response.readAll() - response.close() - return true, sResponse - end - - return false, err -end - -function put(sPath) - if not http then - return false, "Pastebin requires http API" - end - - if type( sPath ) ~= "string" then - error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 ) - end - - -- Upload a file to pastebin.com - -- Determine file to upload - if not fs.exists( sPath ) or fs.isDir( sPath ) then - return false, "No such file" - end - - -- Read in the file - local sName = fs.getName( sPath ) - local file = fs.open( sPath, "r" ) - local sText = file.readAll() - file.close() - - -- POST the contents to pastebin - local key = "0ec2eb25b6166c0c27a394ae118ad829" - local response = http.post( - "https://pastebin.com/api/api_post.php", - "api_option=paste&".. - "api_dev_key="..key.."&".. - "api_paste_format=lua&".. - "api_paste_name="..textutils.urlEncode(sName).."&".. - "api_paste_code="..textutils.urlEncode(sText) - ) - - if response then - local sResponse = response.readAll() - response.close() - - local sCode = string.match( sResponse, "[^/]+$" ) - - return true, sCode - end - return false, "Failed." -end - -function get(sCode, sPath) - if not http then - return false, "Pastebin requires http API" - end - - if type( sCode ) ~= "string" then - error( "bad argument #1 (expected string, got " .. type( sCode ) .. ")", 2 ) - end - - if type( sPath ) ~= "string" then - error( "bad argument #2 (expected string, got " .. type( sPath ) .. ")", 2 ) - end - - if fs.exists( sPath ) then - return false, "File already exists" - end - - -- GET the contents from pastebin - local res, msg = download(sCode) - if not res then - return res, msg - end - - local file = fs.open( sPath, "w" ) - file.write( msg ) - file.close() - - return true -end - -function run(sCode, ...) - if not http then - return false, "Pastebin requires http API" - end - - if type( sCode ) ~= "string" then - error( "bad argument #1 (expected string, got " .. type( sCode ) .. ")", 2 ) - end - - local res, msg = download(sCode) - if not res then - return res, msg - end - local func, err = load(msg, sCode, "t", _ENV) - if not func then - return func, err - end - return pcall(func, ...) -end diff --git a/sys/apps/Files.lua b/sys/apps/Files.lua index 855aaa1..0e40ec5 100644 --- a/sys/apps/Files.lua +++ b/sys/apps/Files.lua @@ -1,5 +1,6 @@ local Config = require('config') local Event = require('event') +local pastebin = require('http.pastebin') local UI = require('ui') local Util = require('util') @@ -7,7 +8,6 @@ local colors = _G.colors local fs = _G.fs local multishell = _ENV.multishell local os = _G.os -local pastebin = _G.pastebin local shell = _ENV.shell local FILE = 1 @@ -41,10 +41,10 @@ local Browser = UI.Page { buttons = { { text = '^-', event = 'updir' }, { text = 'File', dropdown = { - { text = 'Run', event = 'run', flags = FILE }, - { text = 'Edit e', event = 'edit', flags = FILE }, - { text = 'Cloud edit c', event = 'cedit', flags = FILE }, - { text = 'Pastebin put p', event = 'cedit', flags = FILE }, + { text = 'Run', event = 'run', flags = FILE }, + { text = 'Edit e', event = 'edit', flags = FILE }, + { text = 'Cloud edit c', event = 'cedit', flags = FILE }, + { text = 'Pastebin put p', event = 'pastebin', flags = FILE }, { text = 'Shell s', event = 'shell' }, { spacer = true }, { text = 'Quit q', event = 'quit' }, @@ -367,7 +367,7 @@ function Browser:eventHandler(event) local s, m = pastebin.put(file.fullName) if s then os.queueEvent('clipboard_copy', s) - self.notification:success(string.format('Uploaded as %s', m), 0) + self.notification:success(string.format('Uploaded as %s', s), 0) else self.notification:error(m) end diff --git a/sys/apps/pastebin.lua b/sys/apps/pastebin.lua index 66057ca..6c4df9e 100644 --- a/sys/apps/pastebin.lua +++ b/sys/apps/pastebin.lua @@ -18,6 +18,8 @@ if not http then return end +local pastebin = require('http.pastebin') + local sCommand = tArgs[1] if sCommand == "put" then -- Upload a file to pastebin.com @@ -29,14 +31,16 @@ if sCommand == "put" then return end - local success, msg = pastebin.put(sFile) + print( "Connecting to pastebin.com... " ) - if success then + local resp, msg = pastebin.put(sFile) + + if resp then print( "Uploaded as "..msg ) - print( "Run \"pastebin get "..msg.."\" to download anywhere" ) + print( "Run \"pastebin get "..resp.."\" to download anywhere" ) else - print( msg ) + printError( msg ) end elseif sCommand == "get" then @@ -46,30 +50,36 @@ elseif sCommand == "get" then return end + print( "Connecting to pastebin.com... " ) + -- Determine file to download local sCode = tArgs[2] local sFile = tArgs[3] local sPath = shell.resolve( sFile ) if fs.exists( sPath ) then - print( "File already exists" ) + printError( "File already exists" ) return end - local success, msg = pastebin.get(sCode, sPath) + local resp, msg = pastebin.get(sCode, sPath) - if success then - print( "Downloaded as "..sFile ) + if resp then + print( "Downloaded as "..resp ) else - print(msg) + printError( msg ) end + elseif sCommand == "run" then local sCode = tArgs[2] - local success, msg = pastebin.run(sCode, table.unpack(tArgs, 3)) - if not success then - print(msg) + print( "Connecting to pastebin.com... " ) + + local resp, msg = pastebin.run(sCode, table.unpack(tArgs, 3)) + if not resp then + printError( msg ) end else + printUsage() return end diff --git a/sys/apps/telnet.lua b/sys/apps/telnet.lua index 3f5dd84..40a1134 100644 --- a/sys/apps/telnet.lua +++ b/sys/apps/telnet.lua @@ -6,6 +6,7 @@ local Util = require('util') local multishell = _ENV.multishell local os = _G.os local read = _G.read +local shell = _ENV.shell local term = _G.term local args = { ... } diff --git a/sys/autorun/apps.lua b/sys/autorun/apps.lua index 97bec3e..c66656b 100644 --- a/sys/autorun/apps.lua +++ b/sys/autorun/apps.lua @@ -2,6 +2,3 @@ fs.mount('sys/apps/pain.lua', 'urlfs', 'http://pastebin.com/raw/wJQ7jav0') fs.mount('sys/apps/update.lua', 'urlfs', 'http://pastebin.com/raw/UzGHLbNC') fs.mount('sys/apps/Enchat.lua', 'urlfs', 'https://raw.githubusercontent.com/LDDestroier/enchat/master/enchat3.lua') fs.mount('sys/apps/cloud.lua', 'urlfs', 'https://cloud-catcher.squiddev.cc/cloud.lua') - --- baking this in before a PR to cc:tweaked -os.loadAPI('sys/apis/pastebin.lua') \ No newline at end of file