Initial Commit

This commit is contained in:
Rick McEwen
2025-08-20 10:37:50 -06:00
commit 2fc4b8f086
5 changed files with 419 additions and 0 deletions

View File

@ -0,0 +1,36 @@
--[[----------------------------------------------------------------------------
Info.lua
Summary information for ftp_upload sample plug-in
--------------------------------------------------------------------------------
ADOBE SYSTEMS INCORPORATED
Copyright 2007 Adobe Systems Incorporated
All Rights Reserved.
NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
with the terms of the Adobe license agreement accompanying it. If you have received
this file from a source other than Adobe, then your use, modification, or distribution
of it requires the prior written permission of Adobe.
------------------------------------------------------------------------------]]
return {
LrSdkVersion = 3.0,
LrSdkMinimumVersion = 1.3, -- minimum SDK version required by this plug-in
LrToolkitIdentifier = 'com.photonodes.lightroom.export.web_upload',
LrPluginName = LOC "$$$/photonodes/PluginName=Photonodes Export Plugin",
LrExportServiceProvider = {
title = "PhotoNodes",
file = 'PhotonodesUploadServiceProvider.lua',
},
VERSION = { major=1, minor=2, revision=0, },
}

View File

@ -0,0 +1,168 @@
-- Lightroom SDK
local LrView = import 'LrView'
--============================================================================--
PhotonodesUploadExportDialogSections = {}
-------------------------------------------------------------------------------
local function updateExportStatus( propertyTable )
local message = nil
repeat
-- Use a repeat loop to allow easy way to "break" out.
-- (It only goes through once.)
if propertyTable.client_id == nil or propertyTable.client_id == "" then
message = LOC "$$$/Photonodes/ExportDialog/Messages/SelectPreset=Enter a PhotoNodes Client Id"
break
end
if propertyTable.event_code == nil or propertyTable.event_code == "" then
message = LOC "$$$/Photonodes/ExportDialog/Messages/SelectPreset=Enter a PhotoNodes Event Code"
break
end
if propertyTable.gallery_name == nil or propertyTable.gallery_name == "" then
message = LOC "$$$/Photonodes/ExportDialog/Messages/SelectPreset=Enter a Gallery Name"
break
end
until true
if message then
propertyTable.message = message
propertyTable.hasError = true
propertyTable.hasNoError = false
propertyTable.LR_cantExportBecause = message
else
propertyTable.message = nil
propertyTable.hasError = false
propertyTable.hasNoError = true
propertyTable.LR_cantExportBecause = nil
end
end
-------------------------------------------------------------------------------
function PhotonodesUploadExportDialogSections.startDialog( propertyTable )
propertyTable:addObserver( 'items', updateExportStatus )
propertyTable:addObserver( 'client_id', updateExportStatus )
propertyTable:addObserver( 'event_code', updateExportStatus )
propertyTable:addObserver( 'gallery_name', updateExportStatus )
updateExportStatus( propertyTable )
end
-------------------------------------------------------------------------------
function PhotonodesUploadExportDialogSections.sectionsForBottomOfDialog( _, propertyTable )
local f = LrView.osFactory()
local bind = LrView.bind
local share = LrView.share
local result = {
{
title = LOC "$$$/Photonodes/ExportDialog/EventSettings=Photonodes Settings",
synopsis = bind { key = 'fullPath', object = propertyTable },
-- f:row {
-- f:static_text {
-- title = LOC "$$$/FtpUpload/ExportDialog/Destination=Destination:",
-- alignment = 'right',
-- width = share 'labelWidth'
-- },
-- LrFtp.makeFtpPresetPopup {
-- factory = f,
-- properties = propertyTable,
-- valueBinding = 'ftpPreset',
-- itemsBinding = 'items',
-- fill_horizontal = 1,
-- },
-- },
f:row {
f:spacer {
width = share 'labelWidth'
},
f:static_text {
title = LOC "$$$/PhotonodesUpload/ExportDialog/ClientId=Client Id:",
alignment = 'right',
width = share 'labelWidth',
},
f:edit_field {
title = LOC "$$$/PhotonodesUpload/ExportDialog/ClientId=Client Id:",
value = bind 'client_id',
enabled = true,
truncation = 'middle',
immediate = true,
fill_horizontal = 1,
},
},
f:row {
f:spacer {
width = share 'labelWidth'
},
f:static_text {
title = LOC "$$$/PhotonodesUpload/ExportDialog/EventCode=Event Code:",
alignment = 'right',
width = share 'labelWidth',
},
f:edit_field {
title = LOC "$$$/PhotonodesUpload/ExportDialog/EventCode=Event Code:",
value = bind 'event_code',
enabled = true,
truncation = 'middle',
immediate = true,
fill_horizontal = 1,
},
},
f:row {
f:spacer {
width = share 'labelWidth'
},
f:static_text {
title = LOC "$$$/PhotonodesUpload/ExportDialog/GalleryName=Gallery Name:",
alignment = 'right',
width = share 'labelWidth',
},
f:edit_field {
title = LOC "$$$/PhotonodesUpload/ExportDialog/GalleryName=Gallery Name:",
value = bind 'gallery_name',
enabled = true,
truncation = 'middle',
immediate = true,
fill_horizontal = 1,
},
},
},
}
return result
end

View File

@ -0,0 +1,27 @@
-- PhotoNodes Upload plug-in
require "PhotonodesUploadExportDialogSections"
require "PhotonodesUploadTask"
--============================================================================--
return {
hideSections = { 'exportLocation' },
allowFileFormats = nil, -- nil equates to all available formats
allowColorSpaces = nil, -- nil equates to all color spaces
exportPresetFields = {
{ key = 'client_id', default = nil; },
{ key = 'event_code', default = 'LR Photos' },
{ key = "gallery_name", default = nil },
},
startDialog = PhotonodesUploadExportDialogSections.startDialog,
sectionsForBottomOfDialog = PhotonodesUploadExportDialogSections.sectionsForBottomOfDialog,
processRenderedPhotos = PhotonodesUploadTask.processRenderedPhotos,
}

View File

@ -0,0 +1,188 @@
-- Lightroom API
local LrPathUtils = import 'LrPathUtils'
local LrHttp = import 'LrHttp'
local LrFileUtils = import 'LrFileUtils'
local LrErrors = import 'LrErrors'
local LrDialogs = import 'LrDialogs'
local logger = import 'LrLogger'
--============================================================================--
local myLogger = logger( 'photonodes_logger' ) -- the log file name
myLogger:enable( "logfile" )
local function table_to_string(tbl)
local result = "{"
for k, v in pairs(tbl) do
-- Check the key type (ignore any numerical keys - assume its an array)
if type(k) == "string" then
result = result.."[\""..k.."\"]".."="
end
-- Check the value type
if type(v) == "table" then
result = result..table_to_string(v)
elseif type(v) == "boolean" then
result = result..tostring(v)
else
result = result.."\""..v.."\""
end
result = result..","
end
-- Remove leading commas from the result
if result ~= "" then
result = result:sub(1, result:len()-1)
end
return result.."}"
end
PhotonodesUploadTask = {}
function PhotonodesUploadTask.outputToLog( message )
myLogger:trace( message )
end
function PhotonodesUploadTask.debugToLog( val )
myLogger:debug( val )
end
--------------------------------------------------------------------------------
function PhotonodesUploadTask.processRenderedPhotos( functionContext, exportContext )
-- Make a local reference to the export parameters.
local exportSession = exportContext.exportSession
local exportParams = exportContext.propertyTable
-- Set progress title.
local nPhotos = exportSession:countRenditions()
local progressScope = exportContext:configureProgress {
title = nPhotos > 1
and LOC( "$$$/photonodes/Upload/Progress=Uploading ^1 photos to Photonodes", nPhotos )
or LOC "$$$/photonodes/Upload/Progress/One=Uploading one photo to Photonodes",
}
local client_id = exportParams.client_id
local event_code = exportParams.event_code
local gallery_name = exportParams.gallery_name
PhotonodesUploadTask.outputToLog(string.format("Client Id: %s Event Code: %s Gallery Name: %s", client_id, event_code, gallery_name))
if client_id==nil or client_id=="" then
LrErrors.throwUserError( LOC "$$$/photonodes/Upload/Errors/InvalidParameters=The specified Client Id incomplete and cannot be used." )
elseif event_code==nil or event_code=="" then
LrErrors.throwUserError( LOC "$$$/photonodes/Upload/Errors/InvalidParameters=The specified Event Code is incomplete and cannot be used." )
elseif gallery_name==nil or gallery_name=="" then
LrErrors.throwUserError( LOC "$$$/photonodes/Upload/Errors/InvalidParameters=The specified Gallery Name is incomplete and cannot be used." )
end
-- This url uses event_id for event_code
-- local upload_url = string.format("http://api.photonodes.com/kiosk/api/gallerybyname/photos/upload/%s/%s", client_id, event_code)
-- This url uses event code for event_code (staging)
-- local upload_url = string.format("http://staging.photonodes.com/plugin/api/gallerybyname/photos/upload/%s", client_id)
-- This url uses event code for event_code (live)
local upload_url = string.format("http://api.photonodes.com/plugin/api/gallerybyname/photos/upload/%s", client_id)
PhotonodesUploadTask.outputToLog(string.format("Upload Url: %s", upload_url))
-- Iterate through photo renditions.
local failures = {}
local successes = {}
for _, rendition in exportContext:renditions{ stopIfCanceled = true } do
-- Wait for next photo to render.
local success, pathOrMessage = rendition:waitForRender()
-- Check for cancellation again after photo has been rendered.
if progressScope:isCanceled() then break end
if success then
local filename = LrPathUtils.leafName( pathOrMessage )
local mimeChunks = {}
mimeChunks[ #mimeChunks + 1 ] = { name = 'gallery_name', value = gallery_name }
mimeChunks[ #mimeChunks + 1 ] = { name = 'event_code', value = event_code }
mimeChunks[ #mimeChunks + 1 ] = { name = 'photo_file', fileName = filename, filePath = pathOrMessage, contentType = 'application/octet-stream' }
local result, hdrs = LrHttp.postMultipart(upload_url, mimeChunks )
PhotonodesUploadTask.outputToLog(string.format("Http Post result: %s", result))
PhotonodesUploadTask.outputToLog(string.format("Http Post headers: %s", table_to_string(hdrs)))
if not result then
if hdrs and hdrs.error then
PhotonodesUploadTask.outputToLog(string.format("Http Post error: %s", formatError( hdrs.error.nativeCode )))
LrErrors.throwUserError( formatError( hdrs.error.nativeCode ) )
end
end
if hdrs and hdrs.status == 200 then
success = true
elseif hdrs and hdrs.status == 404 then
PhotonodesUploadTask.outputToLog("Http Post error: 404")
LrErrors.throwUserError( "Client Id or Event Code not found" )
elseif hdrs and hdrs.status == 403 then
PhotonodesUploadTask.outputToLog("Http Post error: 403")
LrErrors.throwUserError( "Error uploading file" )
else
success=false
end
-- Http stuff goes here
--local success = ftpInstance:putFile( pathOrMessage, filename )
if not success then
-- If we can't upload that file, log it. For example, maybe user has exceeded disk
-- quota, or the file already exists and we don't have permission to overwrite, or
-- we don't have permission to write to that directory, etc....
table.insert( failures, filename )
else
table.insert(successes, 1)
end
-- When done with photo, delete temp file. There is a cleanup step that happens later,
-- but this will help manage space in the event of a large upload.
LrFileUtils.delete( pathOrMessage )
end
end
if #failures > 0 then
local message
if #failures == 1 then
message = LOC "$$$/photonodes/Upload/Errors/OneFileFailed=1 file failed to upload correctly."
else
message = LOC ( "$$$/photonodes/Upload/Errors/SomeFileFailed=^1 files failed to upload correctly.", #failures )
end
LrDialogs.message( message, table.concat( failures, "\n" ) )
else
if #successes == 1 then
message = string.format("1 file successfully uploaded to gallery %s.", gallery_name)
else
message = string.format("%s files successfully uploaded to gallery %s.", #successes, gallery_name)
end
LrDialogs.message( message )
end
end