pastebin as an api

This commit is contained in:
kepler155c@gmail.com 2019-03-26 09:08:39 -04:00
parent ade354660f
commit 82f6d3451d
6 changed files with 249 additions and 10 deletions

146
sys/apis/pastebin.lua Normal file
View File

@ -0,0 +1,146 @@
--- 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

View File

@ -10,7 +10,7 @@ UI.Notification = class(UI.Window)
UI.Notification.defaults = {
UIElement = 'Notification',
backgroundColor = colors.gray,
closeInd = '\215',
closeInd = UI.extChars and '\215' or '*',
height = 3,
timeout = 3,
anchor = 'bottom',

View File

@ -9,6 +9,8 @@ local multishell = _ENV.multishell
local os = _G.os
local shell = _ENV.shell
local FILE = 1
UI:configure('Files', ...)
local config = Config.load('Files', {
@ -38,12 +40,13 @@ local Browser = UI.Page {
buttons = {
{ text = '^-', event = 'updir' },
{ text = 'File', dropdown = {
{ text = 'Run', event = 'run' },
{ text = 'Edit e', event = 'edit' },
{ text = 'Cloud edit c', event = 'cedit' },
{ text = 'Shell s', event = 'shell' },
{ 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 = 'Shell s', event = 'shell' },
UI.MenuBar.spacer,
{ text = 'Quit q', event = 'quit' },
{ text = 'Quit q', event = 'quit' },
} },
{ text = 'Edit', dropdown = {
{ text = 'Cut ^x', event = 'cut' },
@ -140,6 +143,7 @@ local Browser = UI.Page {
c = 'cedit',
e = 'edit',
s = 'shell',
p = 'pastebin',
r = 'refresh',
space = 'mark',
backspace = 'updir',
@ -162,10 +166,8 @@ end
function Browser.menuBar:getActive(menuItem)
local file = Browser.grid:getSelected()
if file then
if menuItem.event == 'edit' or menuItem.event == 'run' then
return not file.isDir
end
if menuItem.flags == FILE then
return file and not file.isDir
end
return true
end
@ -346,6 +348,7 @@ function Browser:eventHandler(event)
elseif event.type == 'cedit' and file then
self:run('cedit', file.name)
self:setStatus('Started cloud edit')
elseif event.type == 'shell' then
self:run('sys/apps/shell.lua')
@ -358,6 +361,16 @@ function Browser:eventHandler(event)
elseif event.type == 'associate' then
self.associations:show()
elseif event.type == 'pastebin' then
if file and not file.isDir then
local s, m = pastebin.put(file.fullName)
if s then
self.notification:success(string.format('Uploaded as %s', m), 0)
else
self.notification:error(m)
end
end
elseif event.type == 'toggle_hidden' then
config.showHidden = not config.showHidden
Config.update('Files', config)

75
sys/apps/pastebin.lua Normal file
View File

@ -0,0 +1,75 @@
local function printUsage()
print( "Usages:" )
print( "pastebin put <filename>" )
print( "pastebin get <code> <filename>" )
print( "pastebin run <code> <arguments>" )
end
local tArgs = { ... }
if #tArgs < 2 then
printUsage()
return
end
if not http then
printError( "Pastebin requires http API" )
printError( "Set http_enable to true in ComputerCraft.cfg" )
return
end
local sCommand = tArgs[1]
if sCommand == "put" then
-- Upload a file to pastebin.com
-- Determine file to upload
local sFile = tArgs[2]
local sPath = shell.resolve( sFile )
if not fs.exists( sPath ) or fs.isDir( sPath ) then
print( "No such file" )
return
end
local success, msg = pastebin.put(sFile)
if success then
print( "Uploaded as "..msg )
print( "Run \"pastebin get "..msg.."\" to download anywhere" )
else
print( msg )
end
elseif sCommand == "get" then
-- Download a file from pastebin.com
if #tArgs < 3 then
printUsage()
return
end
-- 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" )
return
end
local success, msg = pastebin.get(sCode, sPath)
if success then
print( "Downloaded as "..sFile )
else
print(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)
end
else
printUsage()
return
end

View File

@ -4,6 +4,8 @@ local UI = require('ui')
local colors = _G.colors
-- -t80x30
if _G.http.websocket then
local config = Config.load('cloud')

View File

@ -2,3 +2,6 @@ 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')