local bwlLive=true
local serverDirectory="lr_web"
local defaultDomain
if prefs.defaultDomain == nil then
defaultDomain="a2zkeywording.com"
else
defaultDomain=prefs.defaultDomain
end
local defaultFTPpath = ""
local defaultFTPprotocol ="ftp"
local defaultFTPstorePassword = true
local defaultFTPusername = ""
local defaultFTPpassword = ""
local defaultFTPpassive = "normal"
local defaultFTPtitle = "KeywordPerfect Dropbox"
local defaultFTPport= 21
local defaultFTPserver = defaultDomain
--local arrExtraMetaData --now storing this info in prefs now so they survive LR sessions
local defaultDropboxName="dropbox"
defaultMainPage="keywordperfect.php"
local bwlGotLatestParams=false
urlBase="http://localhost/" .. serverDirectory .. "/"
if bwlLive then
urlBase ="http://" .. defaultDomain .. "/" .. serverDirectory .. "/"
end
--local Require = require 'Require'.path ("../debugscript.lrdevplugin")
--local Debug = require 'Debug'.init ()
--require 'strict'
-- Access the Lightroom SDK namespaces.
inspect = require('inspect')
LrFunctionContext = import 'LrFunctionContext'
LrBinding = import 'LrBinding'
LrDialogs = import 'LrDialogs'
LrPathUtils = import 'LrPathUtils'
LrView = import 'LrView'
LrFileUtils= import 'LrFileUtils'
LrTasks =import 'LrTasks'
prefs =import 'LrPrefs'.prefsForPlugin()
LrCatalog = LrApplication.activeCatalog()
versionName = LrApplication.versionString()
LrFtp = import 'LrFtp'
LrProgressScope = import 'LrProgressScope'
visualDelimiter=". "
LrLogger = import 'LrLogger'
myLogger = LrLogger( 'keywordperfect' )
myLogger:enable( "logfile" )
myLogger:trace( "booted" )
appData={}
blankGenCount=1
newKeywords={}
local debugger_on=false
--- Get a preview image corresponding to specified photo, at the specified level, if possible.
--
-- @param photo (LrPhoto or table of param, required) specified photo or table of named parameters same as below including photo=lr-photo:
-- @param photoPath (string, optional) photo-path if available, otherwise will be pulled from raw-metadata.
-- @param previewFile (string, default=unique-temp-path) target path to store jpeg - if non-vil value passed and file is pre-existing, it will be overwritten.
-- @param level (number, required) appx sizes + intended use:
--
1 - 80x60 small thumb
--
2 - 160x120 medium thumb
--
3 - 320x240 large thumb
--
4 - 640x480 small image
--
5 - 1280x960 medium image
--
6 - 2560x1920 large image
--
7 - 1:1 full-res
-- @param minLevel (number, default=1) minimum acceptable level.
--
-- @usage file, errm, level = cat:getPreview{ photo=catalog:getTargetPhoto(), level=5 }
-- @usage file, errm, level = cat:getPreview( catalog:getTargetPhoto(), nil, nil, 5 )
--
-- @return file (string, or nil) path to file containing requested preview (may be the same as preview-file passed in).
-- @return errm (string, or nil) error message if unable to obtain requested preview (includes path(s)).
-- @return level (number, or nil) actual level read, which may be different than requested level if min-level passed in.
--
function Catalog:getPreview(photo, photoPath, previewFile, level, minLevel )
if photo == nil then
myLogger:trace( "GETPREVIEW: no photo" )
end
local picW=80
local picH=60
if level==1 then
picW=80
picH=60
elseif level==2 then
picW=160
picH=120
elseif level==3 then
picW=320
picH=240
elseif level==4 then
picW=640
picH=480
elseif level==5 then
picW=1280
picH=960
else
picW=2560
picH=1920
end
if not photo.catalog then -- not lr-photo
photoPath = photo.photoPath
previewFile = photo.previewFile
myLogger:trace( "GETPREVIEW: no level in param table" )
level = photo.level
minLevel = photo.minLevel
photo = photo.photo
myLogger:trace( "GETPREVIEW: no lr-photo in param table" )
end
if level == nil then
prefs.thumbnail_size=1
level=1
myLogger:trace( "GETPREVIEW: no level" )
end
if level > 7 then
myLogger:trace( "GETPREVIEW: Max level is 7" )
level = 7
end
if photoPath == nil then
photoPath = photo:getRawMetadata( 'path' )
end
local photoFilename = LrPathUtils.leafName( photoPath )
local _previewFile
if previewFile == nil then
_previewFile = LrPathUtils.child( LrPathUtils.getStandardFilePath( 'temp' ), str:fmt( "^1.lrPreview.jpg", photoFilename ) ) -- include extension, since there are separate previews for each file-type.
else
if fso:existsAsFile( previewFile ) then
myLogger:trace( "GETPREVIEW: preview path passed is to existing file to be overwritten" )
end
_previewFile = previewFile
end
local imageId
local s = tostring( photo ) -- THIS IS WHAT ALLOWS IT TO WORK DESPITE LOCKED DATABASE (id is output by to-string method).
local p1, p2 = s:find( 'id "' )
if p1 then
s = s:sub( p2 + 1 )
p1, p2 = s:find( '" )' )
if p1 then
imageId = s:sub( 1, p1-1 )
end
end
if imageId == nil then
return nil, "bad id"
end
local cp = catalog:getPath()
myLogger:trace( "GETPREVIEW: CP: " .. tostring(deNil(cp)))
local fn = LrPathUtils.leafName( cp )
myLogger:trace( "GETPREVIEW: FN: " .. tostring(deNil(fn)))
local n = LrPathUtils.removeExtension( fn )
myLogger:trace( "GETPREVIEW: N: " .. tostring(deNil(n)))
local cd = LrPathUtils.parent( cp )
myLogger:trace( "GETPREVIEW: CD: " .. tostring(deNil(cd)))
local pn = n .. " Previews.lrdata"
myLogger:trace( "GETPREVIEW: PN: " .. tostring(deNil(pn)))
local d = LrPathUtils.child( cd, pn )
myLogger:trace( "GETPREVIEW: D: " .. tostring(deNil(d)))
local pdb = LrPathUtils.child( d, 'previews.db' )
myLogger:trace( "GETPREVIEW: PDB: " .. tostring(deNil(pdb)))
assert( fso:existsAsFile( pdb ), "nope" )
--Debug.pause( pdb )
local exe = app:getPref( 'sqlite3' )
if not str:is( exe ) then
if WIN_ENV then
exe = LrPathUtils.child( _PLUGIN.path, "sqlite3.exe" )
else
exe = LrPathUtils.child( _PLUGIN.path, "sqlite3" )
end
myLogger:trace( "GETPREVIEW: Using sqlite executable included with plugin: " .. deNil(exe))
else
myLogger:trace( "GETPREVIEW: Using custom sqlite executable: " .. deNil(exe))
end
local param = '"' .. pdb .. '"'
local targ = str:fmt( "select uuid, digest from ImageCacheEntry where imageId=^1", imageId )
local r1, r2, r3 = app:executeCommand( exe, param, { targ }, nil, 'del' )
local uuid -- of preview
local digest -- of preview
if r1 then
if r3 then
local c = str:split( r3, '|' )
if #c >= 2 then
-- good
uuid = c[1]
digest = c[2]
else
myLogger:trace( "GETPREVIEW: bad split")
return nil, "bad split"
end
else
myLogger:trace( "GETPREVIEW: no content")
return nil, "no content"
end
else
myLogger:trace( "GETPREVIEW, r2: " .. tostring(deNil(objectDump(r2))))
return nil, r2
end
local previewSubdir = str:getFirstChar( uuid )
local pDir = LrPathUtils.child( d, previewSubdir )
if fso:existsAsDir( pDir ) then
-- good
else
myLogger:trace("GETPREVIEW: preview letter dir does not exist: " .. pDir)
return nil, "preview letter dir does not exist: " .. pDir
end
previewSubdir = uuid:sub( 1, 4 )
pDir = LrPathUtils.child( pDir, previewSubdir )
if fso:existsAsDir( pDir ) then
-- good
else
myLogger:trace("GETPREVIEW: preview 4-some dir does not exist: " .. pDir)
return nil, "preview 4-some dir does not exist: " .. pDir
end
local previewFilename = uuid .. '-' .. digest .. ".lrprev"
local previewPath = LrPathUtils.child( pDir, previewFilename )
if fso:existsAsFile( previewPath ) then
myLogger:trace("GETPREVIEW: Found preview file at " .. deNil(previewPath))
app:logVerbose( "Found preview file at ^1", previewPath )
else
if tonumber(LrApplication.versionString())>4.99 then --this only works in LR5.0 and greater
local ret=photo:requestJpegThumbnail(picW, picH, function(image)
Catalog:getNewPreview( image, photoPath, previewFile, level, minLevel )
end)
return ret--, str:fmt( "No preview file corresponding to ^1 at ^2", photo:getRawMetadata( 'photoPath' ), previewPath )
else
return nil
end
end
-- this could be modified to return image data instead of file if need be.
local content
local function getImageFile()
local p1, p2 = content:find( "level_" .. str:to( level ) )
if p1 then
local start = p2 + 2 -- jump over level_n\0
local p3 = content:find( "AgHg", start )
local stop
if p3 then
stop = start + p3 - 1
else
stop = content:len() - 1
end
local data = content:sub( start, stop )
if previewFile ~= nil then -- user passed file
app:logVerbose( "Writing preview into user file: ^1", _previewFile )
else
-- rename file to include level.
local base = LrPathUtils.removeExtension( _previewFile ) .. '_' .. level
_previewFile = base .. ".jpg"
app:logVerbose( "Writing preview into default-named file: ^1", _previewFile )
end
local s, m = fso:writeFile( _previewFile, data )
if s then
myLogger:trace("GETPREVIEW: Wrote preview file: " .. deNil(_previewFile))
app:logVerbose( "Wrote preview file: ^1", _previewFile )
return _previewFile
else
return nil, m
end
else
return nil -- no real error, just no preview at that level.
end
end
minLevel = minLevel or 1
local status
status, content = LrTasks.pcall( LrFileUtils.readFile, previewPath )
if status and content then
repeat
local file, errm = getImageFile() -- at level
if file then
return file, nil, level
elseif errm then
return nil, errm
elseif level > minLevel then
level = level - 1
else
myLogger:trace("GETPREVIEW: No preview for " .. deNil(photoPath) .. " at any acceptable level.")
return nil, str:fmt( "No preview for ^1 at any acceptable level", photoPath )
end
until level <= 0
myLogger:trace("GETPREVIEW: Unable to obtain preview for ^1" .. deNil( photoPath))
return nil, str:fmt( "Unable to obtain preview for ^1", photoPath )
else
myLogger:trace("GETPREVIEW: Unable to read preview source file at " .. deNil( previewPath) .. " ALSO: " .. content)
return nil, str:fmt( "Unable to read preview source file at ^1, error message: ^2", previewPath, content )
end
end
------------------------------------------------------
function deNil(strIn)
if strIn==nil then
return ""
else
return strIn
end
end
function split(delim,s )
assert (type (delim) == "string" and string.len (delim) > 0,
"bad delimiter")
local start = 1
local t = {} -- results table
-- find each instance of a string followed by the delimiter
while true do
if s==nil then
return {}
end
local pos = string.find (s, delim, start, true) -- plain find
if not pos then
break
end
table.insert (t, string.sub (s, start, pos - 1))
start = pos + string.len (delim)
end -- while
-- insert final one (after last delimiter)
table.insert (t, string.sub (s, start))
return t
end
function flatCompare(a,b)
return a < b
end
function objectDump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. objectDump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
function arrDump(arrIn, delimiter)
local out=""
for count = 1, #arrIn do
out=out.. arrIn[count]
if count< #arrIn then
out=out.. delimiter
end
end
return out
end
function arrContainsItem(arrIn, item)
if arrIn == nil then
arrIn={}
end
for count = 1, #arrIn do
if arrIn[count]==item then
return true
end
end
return false
end
function flatPseudoArrContainsItem(strName, item)
local startCount=1
while appData[strName .. startCount] ~=nil do
if appData[strName .. startCount]==item then
return true
end
startCount=startCount+1
end
return false
end
function addToArrayRemoveDups(arrIn, item, bwlSort)
local bwlFail=false
for count = 1, #arrIn do
if arrIn[count]==item then
bwlFail=true
end
end
if not bwlFail then
table.insert(arrIn, item)
end
if bwlSort then
table.sort(arrIn, flatCompare)
end
return arrIn
end
function arrayCharCount(arrIn)
local i
local sum=0
for i = 1, #arrIn do
local thisWord=arrIn[i]
sum=sum+string.len(thisWord)
end
return sum
end
function removeParenthetical(strIn)
local firstParan=string.find(strIn, "%(")
local lastParan=string.find(strIn, "%)")
if firstParan~=nil and lastParan~=nil then
if firstParan < lastParan then
strIn=string.sub(strIn, 1, firstParan-1) .. string.sub(strIn, lastParan+1)
end
end
return strIn
end
function removeEndChars(strIn, endChar, typeIn)
local beginPiece =string.sub(strIn, 1,string.len(endChar) )
local endPiece =string.sub(strIn, string.len(strIn)-string.len(endChar)+1 )
if typeIn~="end" then
if beginPiece==endChar then
strIn=string.sub(strIn, string.len(endChar)+1 )
end
end
if typeIn~="begin" then
if endPiece==endChar then
strIn=string.sub(strIn, 1, string.len(strIn)-string.len(endChar))
end
end
return strIn
end
function returnNumeric(strIn)
local len=string.len(strIn)
local out=""
local i
for i=1,len do
local char =string.sub(strIn, i,i )
if tonumber(char)~=nil then
out=out..char
end
end
return tonumber(out)
end
function arrSlice(values,i1,i2)
local res = {}
local n = #values
-- default values for range
i1 = i1 or 1
i2 = i2 or n
if i2 < 0 then
i2 = n + i2 + 1
elseif i2 > n then
i2 = n
end
if i1 < 1 or i1 > n then
return {}
end
local k = 1
for i = i1,i2 do
res[k] = values[i]
k = k + 1
end
return res
end
function encloseItemsInChars(strIn, strDelimiterIn, strDelimiterOut, startBracket, endBracket)
local arrIn=split(strDelimiterIn, strIn)
local out=""
for i=1, #arrIn do
local thisWord=arrIn[i]
out=out .. startBracket .. thisWord .. endBracket .. strDelimiterOut
end
out=removeEndChars(out, strDelimiterOut)
return out
end
function inTable(tbl, item, trimSearch)
for key, value in pairs(tbl) do
if trimSearch then
value=LrStringUtils.trimWhitespace(value)
item=LrStringUtils.trimWhitespace(item)
end
if value == item then return key end
end
return false
end
function updateDialog()
LrFunctionContext.callWithContext( "showCustomDialogWithMultipleBind", function(context)
appData = LrBinding.makePropertyTable(context)
end
)
end
-------------------------------------------------------------------------
function _win_env()
return WIN_ENV
end
function fsoDate(timestamp)
return os.date("%Y%m%d%H%M%S", timestamp)
end
function sqlDate(timestamp)
return os.date("%Y-%m-%d %H:%M:%S", timestamp)
end
--updateProgress(baseProgress, fileCount, fileCounter, baseDelta, "Message...")
function updateProgress(base, total, thiscount, sectorFactor, description)
--myLogger:trace('progress:' .. deNil(base) .. deNil(total) .. deNil(thiscount))\
local increments=10
local percentage=100
if thiscount>total then
total=thiscount+2
end
if total>0 then
local fractional=math.ceil(total/increments)
percentage=(base + (thiscount/total)*sectorFactor)*100
--if thiscount % fractional ==0 then
myLogger:trace('progress:' .. deNil(base) .. "+" .. deNil(total) .. "+" .. deNil(thiscount) .. "*" .. deNil(description))
--old way:
--local completionUrl=urlBase .. "data.php" .. "?wo=true&tid=x&description=" .. url_encode(deNil(description)) .. "&sess=" .. deNil(prefs.sess) .. "&command=updateprogress&percentage=" .. percentage
--local completionData=http_get(completionUrl, {})
--new way:
appData.progressText= description
appData.progressValue= math.floor(percentage)
--end
end
if percentage>99 then
appData.progressText=""
appData.progressValue=""
end
end
-- LrFunctionContext.callWithContext( "showCustomDialogWithMultipleBind", function(context)
--LrFunctionContext.callWithContext( LrDialogs.showModalProgressDialog( {title="Starting up", caption="just a few seconds...", cannotCancel=false, functionContext =LrFunctionContext} )
function buildPathAsNeeded(path)
path =string.gsub(path, string.char(47), string.char(92))
myLogger:trace("aa:" .. path)
local exists = LrFileUtils:exists( path)
myLogger:trace("ab:" )
if exists ~=false then
myLogger:trace("noncreation:" .. deNil(path) )
return path
else
myLogger:trace("creation:" .. deNil(leafPart) .. " of " .. deNil(parentPart))
local parentPart=LrPathUtils.parent(path)
buildPathAsNeeded(parentPart)
local leafPart=LrPathUtils.leafName(path)
myLogger:trace("bb:" )
LrFileUtils:createDirectory(leafPart)
end
return path
end
function gotoEntryWebpageForm()
gotoWebpage(deNil(defaultMainPage) .. "?sess=" .. deNil(prefs.sess) .. "&mode=enter")
end
function gotoWebpage(url)
--"http://a2zkeywording.com/lr_web/keywordperfect.php?sess=" .. prefs.sess .. "&mode=enter"
if url==nil then
url=appData.windowUrl
end
local actionBase=urlBase .. "data.php" .. "?tid=xx&wo=true&sess=" .. deNil(prefs.sess) .. "&p=" .. deNil(prefs.pathname)
if string.find( "xxx" .. url, "http:" )==nil then
url=urlBase .. url
end
local completionUrl=actionBase .. "&command=" .. "gotowebpage¶meter=" .. url_encode(url)
myLogger:trace("goto web page:" .. completionUrl)
local completionData=deNil(http_get(completionUrl, {}))
myLogger:trace("okay went to web page:" .. completionUrl)
end
function importCollections()
local actionBase=urlBase .. "data.php" .. "?tid=xx&wo=true&sess=" .. deNil(prefs.sess) .. "&p=" .. deNil(prefs.pathname)
local completionUrl=actionBase .. "&command=" .. "importcollections"
local completionData=deNil(http_get(completionUrl, {}))
end
function clearThumbFolder()
local path=deNil(_PLUGIN.path) .. "/thumbs/" .. deNil(tonumber(prefs.thumbnail_size))
for filePath in LrFileUtils.recursiveDirectoryEntries( path ) do
LrFileUtils.delete(filePath)
end
end
function tableMerge(t1, t2)
for k,v in pairs(t2) do
if type(v) == "table" then
if type(t1[k] or false) == "table" then
tableMerge(t1[k] or {}, t2[k] or {})
else
t1[k] = v
end
else
t1[k] = v
end
end
return t1
end
function uploadCatalog(mode, photoRange, idList)
--mode is collection or catalog
myLogger:trace("mode: " .. deNil(mode))
myLogger:trace("photoRange: " .. deNil(photoRange))
LrTasks.startAsyncTask(
function()
clearThumbFolder()
local bwlDebugManifestProcess=false
local baseProgress=0
local baseDelta=0
local path=prefs.dropboxPath
local keys = {'title', 'caption', 'headline'}
local params={includeIfBuried =true}
local thumbSize=prefs.thumbnail_size;
local bwlDoNotGoToWebPage=true
local totalManifest=""
local collectionManifestPath=""
local manifestFilename="manifest"
local lrManifestPath=_PLUGIN.path .. "/thumbs"
myLogger:trace("pluginpath: " .. deNil(_PLUGIN.path))
--myLogger:trace("manifest path:" .. deNil(lrManifestPath))
local lrThumbImageRoot=deNil(lrManifestPath) .. "/" .. deNil(tonumber(thumbSize))
local lrThumbImagePath=""
local errors=""
if mode==nil then
mode="catalog"
end
--local photos = getVisiblePhotos(params)--LrCatalog:getAllPhotos()
local photos={}
if (idList~=nil and idList~="") and photoRange~="specifiedcollection" then
local arrIds=split(",", idList)
for i=1, #arrIds do
local thisId=arrIds[i]
local startSize=3
if LrFileUtils.exists(lrManifestPath .. "/" .. startSize) == false then
LrFileUtils.createAllDirectories(lrThumbImageRoot .. "/" .. startSize)
end
myLogger:trace(lrManifestPath .. "/" .. startSize .. "/" .. thisId .. ".jpg")
myLogger:trace(LrFileUtils.exists(lrManifestPath .. "/" .. startSize .. "/" .. thisId .. ".jpg"))
while LrFileUtils.exists(lrManifestPath .. "/" .. startSize .. "/" .. thisId .. ".jpg")~=false and startSize<9 do
startSize=startSize+1
end
if startSize<8 then
--myLogger:trace("thisid=======" .. thisId)
local photo=LrCatalog:findPhotoByUuid(thisId)
photos[#photos+1]=photo
--myLogger:trace("photo>>=======" .. tostring(photo))
else
startSize=7
end
thumbSize=startSize
lrThumbImageRoot=lrManifestPath .. "/" .. tonumber(thumbSize)
end
if startSize==nil then
startSize=1
prefs.thumbnail_size=startSize
end
else
if photoRange=="folder" then
local specificPhoto = LrCatalog:getTargetPhoto()
--local specificPhoto=selectedPhotos[1]
local imagePath=specificPhoto:getRawMetadata("path")
local folderPath=LrPathUtils.parent(imagePath)
local folder=LrCatalog:getFolderByPath(folderPath)
photos=folder:getPhotos(false)
myLogger:trace('folder we are in:' .. folderPath)
elseif photoRange=="collection" or photoRange=="specifiedcollection" then
myLogger:trace('early collection! ')
local specificPhoto = LrCatalog:getTargetPhoto()
--local specificPhoto=selectedPhotos[1]
local collections={}
local i
local j
if photoRange~="specifiedcollection" then
collections=specificPhoto:getContainedCollections()
end
--myLogger:trace('early collection1! ' .. specificPhoto:getRawMetadata("path"))
myLogger:trace('early collection2! ' .. #collections)
local arrCollectionIds={}
if #collections==1 then
local thisCollection=collections[1]
local thisId=thisCollection.localIdentifier
arrCollectionIds={thisId}
idList=thisId
else
arrCollectionIds=split(",", idList)
end
local collections2={}
if #arrCollectionIds>0 then
for j=1, #arrCollectionIds do
local thisCollectionId=arrCollectionIds[j]
if tonumber(thisCollectionId)~=nil then --third parameter is a collection id
local bwlFoundThisCollection=false
for i=1, #collections do
--myLogger:trace("going through collections.")
local collection=collections[i]
--myLogger:trace("going through collections2.")
if tonumber(collection.localIdentifier) ==tonumber( thisCollectionId) then
--myLogger:trace("going through collections3.")
bwlFoundThisCollection =true
end
--myLogger:trace("going through collections4.")
end
if bwlFoundThisCollection then
--myLogger:trace("going through collections5.")
local thisCollection=LrCatalog:getCollectionByLocalIdentifier( idList )
--myLogger:trace("going through collections6.")
if thisCollection==nil then
errors=errors .. "Collection not found."
--myLogger:trace('collection not found!')
end
--myLogger:trace("going through collections7.")
collections2[#collections2+1]=thisCollection
--myLogger:trace("going through collections8.")
else
errors=errors .. "Collection for " .. thisCollectionId .. " not found."
myLogger:trace("Collection for " .. thisCollectionId .. " not found.")
end
end
end
end
myLogger:trace("just before the setting")
collections=collections2
local amassedPhotos={}
for i=1, #collections do
local collection=collections[i]
myLogger:trace('early collection3! ')
amassedPhotos=tableMerge(amassedPhotos, collection:getPhotos())
myLogger:trace('early collection4! ')
end
photos=amassedPhotos
myLogger:trace('collections! ')
elseif photoRange=="unkeyworded" then
local possiblePhotos=LrCatalog:getAllPhotos()
photos={}
for i=1, #possiblePhotos do
myLogger:trace('aa:3')
local thisPhoto=possiblePhotos[i]
local keywords=thisPhoto:getRawMetadata("keywords")
--myLogger:trace('trouble with no keywords?! '.. #keywords)
if #keywords==0 then
photos[#photos+1]=thisPhoto
end
--myLogger:trace('no trouble with no keywords?! ')
end
myLogger:trace('unkeyworded! ' .. #photos)
--elseif prefs.selectedPhotos ==nil then
else
myLogger:trace('aa:1')
photos = LrCatalog:getMultipleSelectedOrAllPhotos()
local justTargeted= LrCatalog:getTargetPhotos()
if #justTargeted>0 then
myLogger:trace('aa:4')
photos=justTargeted
end
--else
--myLogger:trace('aa:2')
--photos = prefs.selectedPhotos
end
end
if photos == nil or #photos<1 then
myLogger:trace('no photos')
photos={}
photos[1]= LrCatalog:getTargetPhoto()
if photos[1]==nil then
myLogger:trace('no target photos')
local allphotos=LrCatalog:getAllPhotos()
photos[1]=allphotos[1]
end
end
--dialogs.message("counterman", #photos)
--local metaData = LrCatalog:batchGetFormattedMetadata(photos,keys)
--local metaData = LrCatalog:batchGetFormattedMetadata(photos)
--local rawData = LrCatalog:batchGetRawMetadata(photos, {'uuid'})
local buff = "\n"
local outer=""
local out=0
--dialogs.message("counterman",type(appData))
if appData.imageFile==nil then
appData.imageFile={}
end
--only do this occasionally
--myLogger:trace('alpha')
baseDelta=.4
local i
if not bwlDebugManifestProcess then -- dont want to keep doing this time-consuming job:
if mode=="collection" or mode=="catalog" then
local manifestData=""
local collectionSets=LrCatalog:getChildCollectionSets()
local collections=LrCatalog:getChildCollections()
for i=1, #collectionSets do
updateProgress(baseProgress, #collectionSets, i, .4, "Uploading collection sets..")
local collectionSet=collectionSets[i]
local parent=collectionSet:getParent()
local parentId=""
if parent~=nil then
parentId=parent.localIdentifier
end
manifestData="collectionset|" .. collectionSet:getName() .. "|" .. collectionSet.localIdentifier .. "|" .. parentId
totalManifest=totalManifest .. manifestData .. string.char(13)
end
for i=1, #collections do
updateProgress(baseProgress, #collections, i, .4, "Uploading collections..")
local collection=collections[i]
local parent=collection:getParent()
local parentId=""
if parent~=nil then
parentId=parent.localIdentifier
end
manifestData="collection|" .. collection:getName() .. "|" .. collection.localIdentifier .. "|" .. parentId
totalManifest=totalManifest .. manifestData .. string.char(13)
end
collectionManifestPath= _PLUGIN.path .. "/thumbs/collection.txt"
if totalManifest~="" then
fso:writeFile(collectionManifestPath, totalManifest, true, false)
end
totalManifest=""
end
myLogger:trace( " photocount" .. #photos)
myLogger:trace( " mode" .. mode)
if mode=="catalog" then
manifestFilename="manifest"
for i=1, #photos do
bwlDoNotGoToWebPage=false
--myLogger:trace('beta')
updateProgress(baseProgress, #photos, i, .4, "Preparing thumbnails...")
--myLogger:trace('gamma')
myLogger:trace('photo#' .. i)
local manifestData=""
local photo=photos[i]
if photo~=nil then
myLogger:trace(tostring(photo))
--dialogs.message("odump", objectDump(md))
local path= photo:getRawMetadata('path')
--myLogger:trace('pithy path:' .. path)
local dateTimeDigitized= photo:getRawMetadata( 'dateTimeDigitized' )
local uuid= photo:getRawMetadata( 'uuid' )
local kwImageId= 0
--myLogger:trace("dinker" .. type(photo) .. uuid)
--appData.imageFile[#appData.imageFile+1]= {path,sqlDate(dateTimeDigitized), kwImageId, uuid, photo }
--myLogger:trace(objectDump(appData.imageFile))
--myLogger:trace("dink")
local thisbuff="\n\n"
local p = tostring(photo)
local preview=""
myLogger:trace( "path: " .. deNil(path))
if path~=nil then
--myLogger:trace("thumbroot:" .. lrThumbImageRoot)
if LrFileUtils.exists(lrThumbImageRoot) == false then
LrFileUtils.createAllDirectories(lrThumbImageRoot)
end
lrThumbImagePath=lrThumbImageRoot.. "/" .. uuid .. ".jpg"
--myLogger:trace("after create:" .. lrThumbImagePath)
if LrFileUtils.exists(lrThumbImagePath) ==false then
preview=Catalog:getPreview(photo, path, lrThumbImagePath, tonumber(thumbSize) )
end
myLogger:trace("found preview path: " .. deNil(lrThumbImagePath))
local gps= photo:getRawMetadata('gps')
local lat=""
local lon=""
if gps~=nil then
lat=gps.latitude
lon=gps.longitude
end
local fileSize=deNil(photo:getRawMetadata('fileSize'))
local altitude=deNil(photo:getRawMetadata('gpsAltitude'))
local dimensions=photo:getRawMetadata('dimensions')
local width=deNil(dimensions.width)
local height =deNil(dimensions.height )
local dimensions=photo:getRawMetadata('croppedDimensions')
local cwidth=deNil(dimensions.width)
local cheight=deNil(dimensions.height )
local aperture=deNil(photo:getRawMetadata('aperture'))
local shutterSpeed=deNil(photo:getRawMetadata('shutterSpeed'))
local flash=tostring(photo:getRawMetadata('flash'))
local caption=string.gsub (deNil(photo:getFormattedMetadata( 'caption' )), "|", ",")
local title=string.gsub ( deNil(photo:getFormattedMetadata( 'title' )), "|", ",")
local creator=string.gsub (deNil(photo:getFormattedMetadata( 'creator' )), "|", ",")
local modelReleaseStatus=string.gsub (deNil(photo:getFormattedMetadata( 'modelReleaseStatus' )), "|", ",")
--local propertyReleaseStatus=string.gsub (deNil(photo:getFormattedMetadata( 'propertyReleaseStatus' )), "|", ",")
local propertyReleaseStatus=string.gsub (deNil(photo:getFormattedMetadata( 'propertyReleaseStatus' )), "|", ",")
local location=string.gsub (deNil(photo:getFormattedMetadata( 'location' )), "|", ",")
local editCount=deNil(photo:getRawMetadata( 'editCount' ))
local headline=string.gsub(deNil(photo:getFormattedMetadata( 'headline' )), "|", ",")
local dateTimeOriginal=string.gsub (deNil(photo:getFormattedMetadata( 'dateTimeOriginal' )), "|", ",")
local orientation=photo:getDevelopSettings().orientation
manifestData=uuid .. "|" .. path .. "|" .. sqlDate(dateTimeDigitized) .. "|" .. i
.. "|" ..fileSize .. "|" .. lat .. "|" .. lon .. "|" .. altitude
.. "|" .. width .. "|" .. height .. "|" .. cwidth .. "|" .. cheight ..
"|".. flash .. "|" .. aperture .. "|" .. shutterSpeed .. "|" .. title .. "|" .. caption .. "|" .. creator .. "|" .. modelReleaseStatus .. "|" .. propertyReleaseStatus .. "|" .. editCount .. "|" .. location .. "|" .. headline .. "|" .. dateTimeOriginal
local collections=photo:getContainedCollections()
local collectionString=""
for j=1, #collections do
local collection=collections[j]
local collectionId=collection.localIdentifier
if collectionId~=nil then
collectionString = collectionString .. collectionId .. "."
end
end
local LRKeywords = existingKeywords(photo)
manifestData = manifestData .. "|" .. removeEndChars(collectionString, "." )
manifestData = manifestData .. "|" .. deNil(orientation)
manifestData = manifestData .. "|" .. LRKeywords
if deNil(prefs.arrExtraMetaData)~="" then
local metaCount
for metaCount = 1, #prefs.arrExtraMetaData do
myLogger:trace("count of metadata:" .. #prefs.arrExtraMetaData)
local userMetaField=deNil(prefs.arrExtraMetaData[metaCount])
if deNil(userMetaField)~="" then
if string.sub(userMetaField, 1, 1)=="-" then --begins with dash, it's a develop setting
userMetaField=string.sub(userMetaField, 2)
local settings=photo:getDevelopSettings()
if settings[userMetaField] ~=nil then
myLogger:trace("valid dev setting:" .. userMetaField)
manifestData = manifestData .. "|" .. string.gsub(tostring(deNil(settings[userMetaField])), "|", ",")
else
myLogger:trace("invalid dev setting:" .. userMetaField)
manifestData = manifestData .. "|"
end
elseif string.sub(userMetaField, 1, 1)=="_" then --begins with underscore, it's a getFormattedMetadata
userMetaField=string.sub(userMetaField, 2)
local settings=photo:getFormattedMetadata()
if settings[userMetaField] ~=nil then
myLogger:trace("valid formatted setting:" .. userMetaField)
manifestData = manifestData .. "|" .. string.gsub(tostring(deNil(settings[userMetaField])) , "|", ",")
else
myLogger:trace("invalid formatted setting:" .. userMetaField)
manifestData = manifestData .. "|"
end
else --else, it's raw meta data
local settings=photo:getRawMetadata()
if settings[userMetaField] ~=nil then
myLogger:trace("valid unformatted setting:" .. userMetaField)
manifestData = manifestData .. "|" .. string.gsub(tostring(deNil(settings[userMetaField])) , "|", ",")
else
myLogger:trace("invalid unformatted setting:" .. userMetaField)
manifestData = manifestData .. "|"
end
end
end
end
end
end
end
totalManifest=totalManifest .. string.char(13) .. manifestData
end
end
end
local d1="P" .. math.sqrt(16)
local d2="zan" .. math.sqrt(9) .. "!"
local d3=math.pow(10,3) *2 + math.sqrt(169)
local manifestFilePath=""
if totalManifest~=nil then
manifestFilePath= lrManifestPath .. "/" .. manifestFilename .. ".txt"
fso:writeFile(manifestFilePath, totalManifest, true, false)
end
baseProgress=baseProgress+baseDelta
--[[
local ftpPreset={
path = "tron",
protocol ="ftp",
storePassword = true,
password = "XXXXXX",
passive = "normal",
title = "Untitled FTP",
username = "victorvodka",
port= 21,
server = "asecular.com"
}
]]
local ftpPreset={
path = defaultFTPpath,
protocol = defaultFTPprotocol,
storePassword = true,
username = defaultFTPusername,
password = defaultFTPpassword,
passive = defaultFTPpassive,
title = defaultFTPtitle,
port= tonumber(defaultFTPport),
server = defaultFTPserver
}
myLogger:trace(defaultFTPpath .. "|" .. defaultFTPprotocol .. "|" .. tostring(defaultFTPstorePassword) .. "|" .. defaultFTPusername .. "|" .. defaultFTPpassword .. "|" .. defaultFTPpassive .. "|" .. defaultFTPtitle .. "|" .. defaultFTPport .. "|" .. defaultFTPserver .. "|" .. defaultDomain)
if not LrFtp.queryForPasswordIfNeeded( ftpPreset ) then
return
end
myLogger:trace("just before FTP")
local ftpInstance = LrFtp.create( ftpPreset, true )
myLogger:trace("just after FTP")
if not ftpInstance then
-- This really shouldn't ever happen.
LrErrors.throwUserError( LOC "$$$/FtpUpload/Upload/Errors/InvalidFtpParameters=The specified FTP preset is incomplete and cannot be used." )
end
------------------------
local fullPath="error"
if prefs.pathname~=nil then
fullPath= prefs.pathname .. "/" .. deNil(thumbSize)
end
myLogger:trace("fullpath:" .. fullPath)
local index = 0
while true do
local subPath = string.sub( fullPath, 0, index )
ftpInstance.path = subPath
local exists = ftpInstance:exists( '' )
if exists == false then
local success = ftpInstance:makeDirectory( '' )
if not success then
-- This is a possible situation if permissions don't allow us to create directories.
LrErrors.throwUserError( LOC "$$$/FtpUpload/Upload/Errors/CannotMakeDirectoryForUpload=Cannot upload because KeywordPerfect could not create the destination directory: " .. fullPath )
end
elseif exists == 'file' then
-- Unlikely, due to the ambiguous way paths for directories get tossed around.
LrErrors.throwUserError( LOC "$$$/FtpUpload/Upload/Errors/UploadDestinationIsAFile=Cannot upload to a destination that already exists as a file." )
elseif exists == 'directory' then
-- Excellent, it exists, do nothing here.
else
-- Not sure if this would every really happen.
LrErrors.throwUserError( LOC "$$$/FtpUpload/Upload/Errors/CannotCheckForDestination=Unable to upload because KeywordPerfect cannot ascertain if the target destination exists." )
end
if index == nil then
break
end
index = string.find( fullPath, "/", index + 1 )
end
ftpInstance.path = fullPath
-- Iterate through photo renditions.
local failures = {}
local pathOrMessage
local success=true
--local fileEntries=
local fileCount=#photos
local percentage=0
local fileCounter=0
--only used for debugging:
local localFilePath="c:/wamp/www/" .. serverDirectory .. "/" .. defaultDropboxName .. "/" .. prefs.pathname .. "/" .. deNil(thumbSize)
if mode=="collection" or mode=="catalog" then
local filename="collection.txt"
ftpInstance.path=prefs.pathname
myLogger:trace("now FTPing collection manifest:" .. collectionManifestPath .. " -- to --" .. filename .. " at " .. prefs.pathname)
local success = ftpInstance:putFile( collectionManifestPath, filename )
end
if mode=="catalog" then
--myLogger:trace("inside Catalog")
--myLogger:trace("fullpath: ")
ftpInstance.path = fullPath
if not bwlDebugManifestProcess then
baseDelta=.4
if not bwlLive then
--buildPathAsNeeded(localFilePath)
end
success=true
--myLogger:trace("bing:" .. lrThumbImageRoot)
if 1==1 then
for filePath in LrFileUtils.directoryEntries(lrThumbImageRoot) do
updateProgress(baseProgress, #photos, fileCounter, baseDelta, "Uploading thumbnails...")
--for _, rendition in exportContext:renditions{ stopIfCanceled = true } do
-- Wait for next photo to render.
--how it looks for rendition:
--local success, pathOrMessage = rendition:waitForRender()
-- Check for cancellation again after photo has been rendered.
pathOrMessage=filePath
--if progressScope:isCanceled() then
--break
--end
--myLogger:trace("bang:")
if success then
local filename = LrPathUtils.leafName( pathOrMessage )
if not bwlLive then
--local filesSystemDest= localFilePath .. "/" .. filename
--myLogger:trace("local filesystem dest:" .. filesSystemDest)
--LrFileUtils.copy( pathOrMessage, filesSystemDest )
else
--if not ftpInstance:exists(filename) then
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 )
myLogger:trace("ftp failure:" .. filename)
end
--end
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.
--dont do this for the time being:
--LrFileUtils.delete( pathOrMessage )
end
fileCounter=fileCounter+1
--oh well, can't do this:
--collectgarbage()
end
end
end
end
baseProgress=baseProgress+baseDelta
--also make sure to FTP over the manifest
local success = ftpInstance:putFile( manifestFilePath, manifestFilename .. ".txt")
--do this so the collections will be waiting for association with any images belonging to them
ftpInstance:disconnect()
LrTasks.sleep(2)
importCollections()
LrTasks.sleep(2)
appData.progressText=""
local actionBase=urlBase .. "data.php" .. "?tid=xx&wo=true&sess=" .. deNil(prefs.sess) .. "&p=" .. deNil(prefs.pathname)
local completionUrl=""
local completionData=""
--if mode=="catalog" then
completionUrl=actionBase .. "&thumbsize=" .. deNil(thumbSize) .. "&mode=" .. mode .. "&command=" .. "importfromftp"
completionData=deNil(http_get(completionUrl, {}))
--elseif mode=="collection" then
--elseif mode=="collection" then
--importCollections()
--end
myLogger:trace("now going here to process manifest:" .. completionUrl)
myLogger:trace( "completiondata:" .. completionData)
if #failures > 0 then
local message
if #failures == 1 then
message = LOC "$$$/FtpUpload/Upload/Errors/OneFileFailed=1 file failed to upload correctly."
else
message = LOC ( "$$$/FtpUpload/Upload/Errors/SomeFileFailed=^1 files failed to upload correctly.", #failures )
end
LrDialogs.message( message, table.concat( failures, "\n" ) )
end
LrTasks.sleep(6)
--completionUrl=actionBase .. "&command=" .. "refreshwebpage"
--completionData=deNil(http_get(completionUrl, {}))
--and os.time()-prefs.inLoopTime>12
--and os.time()-appData.startupTime>12
if not bwlDoNotGoToWebPage then --dont want to go to mostrecent too soon after booting
myLogger:trace("MOST RECENT(though not doing it from here)" .. tostring(bwlDoNotGoToWebPage))
--gotoWebpage("keywordperfect.php?sess=" .. prefs.sess .. "&mode=mostrecent" )
end
appData.errors=errors
end
)
end
function photoCompare(a, b)
--myLogger:trace("ayer" .. tostring(a))
if type(a)~="table" or type(b)~="table" then
return
end
if tonumber(a[2])==nil then
a=os.clock()
end
if tonumber(b[2])==nil then
b=os.clock()
end
if tonumber(a)~=nil then
return
end
if tonumber(b)~=nil then
return
end
return tonumber(a[2]) include underlings.
local cache = params.metadataCache or lrMeta:createCache{ photos=visiblePhotos, rawIds={ 'isInStackInFolder', 'stackInFolderIsCollapsed', 'stackInFolderMembers', } }
local buriedPhotos = {}
for i, photo in ipairs( visiblePhotos ) do
repeat
if not cache:getRawMetadata( photo, 'isInStackInFolder' ) then
break
end
-- photo is in stack
if not cache:getRawMetadata( photo, 'stackInFolderIsCollapsed' ) then
break
end
-- stack is collapsed, therefore it is top of stack (actually, that is only true if source is folder - viewing collection, one could view underlings of collapsed folder stacks).
local stack = cache:getRawMetadata( photo, 'stackInFolderMembers' )
--assert( stack[1] == photo, "tos?" ) - invalid assertion (see comment above).
for j, stackedPhoto in ipairs(stack) do
if photo ~= stackedPhoto then
buriedPhotos[#buriedPhotos + 1] = stackedPhoto
end
end
until true
end
tab:appendArray( visiblePhotos, buriedPhotos ) -- returns promptly if no buried photos.
return visiblePhotos
end
function pollData()
myLogger:trace("beginning of polldata:" .. sqlDate())
updateProgress(0, 100, 100, 1, "Waiting...")
appData.windowOpen=false
if appData.startupTime==nil then
appData.startupTime=os.time()
end
if prefs.inLoopTime==nil then
prefs.inLoopTime=0
end
if prefs.thumbnail_size ==nil then
prefs.thumbnail_size=1
end
local url=""
local start_time = os.time()
--url=url_encode(url)
myLogger:trace("incount1")
local sess=deNil(prefs.sess)
myLogger:trace(sess .. "xxxx");
if sess=="" then
sess=tostring(math.random()) .. "x" .. tostring(math.random())
prefs.sess=sess
end
myLogger:trace( "afterstank");
local actionBase=urlBase .. "data.php" .. "?tid=x&sess=" .. deNil(sess) .. "&command=setprefs¶meter=x"
--myLogger:trace("setprefsURL: " ..actionBase )
local data=http_get(actionBase, {})
--myLogger:trace("data: " ..deNil(data) )
--[[
if sess=="08f67525def6fad509b8fddbe5" then
prefs.sess=""
sess=""
end
if prefs.pathname=="gus@asecular.com" then
prefs.pathname=""
end
]]
local extraUrl=""
local data
local outthrough=1
local oldThirdDigitBack=0
local bwlHadACommand=false
appData.timeWhenWindowOpened=0
--prefs.selectedPhotos=LrCatalog:getMultipleSelectedOrAllPhotos()
myLogger:trace("incount2")
prefs.pathname=""
prefs.bwlNeedAUserInteractionWindow=true
if prefs.allowpageopen==nil then
prefs.allowpageopen=true
end
--load the latest params from http://a2zkeywording.com/lr_web/data.php?command=getlatestparams
--and change everything if necessary
myLogger:trace("DO I HAVE LATEST PARAMS?")
if not bwlGotLatestParams then
myLogger:trace("DID NOT HAVE LATEST PARAMS!!")
local actionBase=urlBase .. "data.php?command=getlatestparams&p=" .. deNil(prefs.pathname)
url=actionBase.. extraUrl
myLogger:trace(url)
local data=http_get(url, {})
if data~=nil then
myLogger:trace("GOT THE LATEST PARAMS!!")
local arrData=split("|", data)
defaultFTPpath = deNil(arrData[1])
defaultFTPprotocol =deNil(arrData[2])
defaultFTPstorePassword = deNil(arrData[3])=="1"
defaultFTPusername = deNil(arrData[4])
defaultFTPpassword = deNil(arrData[5])
defaultFTPpassive = deNil(arrData[6])
defaultFTPtitle = deNil(arrData[7])
defaultFTPport= deNil(arrData[8])
defaultFTPserver = deNil(arrData[9])
defaultDomain=deNil(arrData[10])
defaultDropboxName=deNil(arrData[11])
defaultMainPage=deNil(arrData[12])
urlBase ="http://" .. defaultDomain .. "/" .. serverDirectory .. "/"
end
bwlGotLatestParams=true
end
if os.time()-prefs.inLoopTime >3 or 1==1 then --keeps the loop from being launched multiple times
--myLogger:trace("looptimer:" .. os.time()-prefs.inLoopTime)
while outthrough<100000000 or 1==1 do
prefs.inLoopTime=os.time()
if os.time() -start_time >5 and not bwlHadACommand then
end
--myLogger:trace("email:" .. prefs.pathname)
local tid= string.sub(math.random(),3, 9)
local command=deNil(appData.command)
local key=deNil(appData.key)
local key2=deNil(appData.key2)
local value=deNil(appData.value)
local value2=deNil(appData.value2)
local pathname=deNil(prefs.pathname)
--myLogger:trace("pathname incoming:" .. pathname .. " with sess:" .. deNil(sess))
local datecode=fsoDate()
extraUrl=""
extraUrl=extraUrl .. "&datecode=" .. datecode
if command~="" then
extraUrl=extraUrl .. "&command=" .. command
end
if key~="" then
extraUrl=extraUrl .. "&" .. key .. "=" .. url_encode(value)
end
if key2~="" then
extraUrl=extraUrl .. "&" .. key2 .. "=" .. url_encode(value2)
end
extraUrl=extraUrl .. "&wo=" .. tostring(deNil(appData.windowOpen)) .. "&p=" .. pathname .. "&error=" .. deNil(appData.error)
appData.error=""
local tid= string.sub(math.random(),3, 9)
local actionBase=urlBase .. "data.php" .. "?tid=" ..tid .. "&sess=" .. sess .. "&version=" .. deNil(url_encode(versionName))
url=actionBase.. extraUrl
if appData.progressText~=nil and appData.progressText~="" then
url=url .. "&progresstext=" .. url_encode(deNil(appData.progressText)) .. "&progressvalue=" .. deNil(appData.progressValue)
end
local stringifiedTime= tostring(os.clock())
--myLogger:trace("stringified time:" .. stringifiedTime)
local thirdDigitBack=string.sub(stringifiedTime, string.len(stringifiedTime)-2, string.len(stringifiedTime)-2)
--myLogger:trace("stringified:" .. thirdDigitBack)
--if thirdDigitBack==6 and oldThirdDigitBack~=thirdDigitBack then
local data=http_get(url, {})
--myLogger:trace("url:" .. url)
--myLogger:trace("neg one")
if data~=nil then
--myLogger:trace("data:" .. data)
--myLogger:trace("sess: " .. sess .." ;data:" .. data)
--data has this format:
--tid|command|key|value|key2|value2CHAR13datadump
--often key...value2 will have no data
--myLogger:trace("zero")
--myLogger:trace("waa.." .. deNil(data));
local arrData=split(string.char(13), data)
if #arrData>1 then
--myLogger:trace("one")
--we only got data if this is the case
local firstRow=arrData[1]
--myLogger:trace(deNil(firstRow));
local arrFirst=split("|", firstRow)
if #arrFirst>1 then
--myLogger:trace("two")
--myLogger:trace(firstRow)
--we only got data if this is also the case
--5695669| | | | | |x |1 5
local tidIn=LrStringUtils.trimWhitespace(deNil(arrFirst[1]))
local commandIn=LrStringUtils.trimWhitespace(deNil(arrFirst[2]))
local keyIn=LrStringUtils.trimWhitespace(deNil(arrFirst[3]))
local valueIn=LrStringUtils.trimWhitespace(deNil(arrFirst[4]))
local key2In=LrStringUtils.trimWhitespace(deNil(arrFirst[5]))
local value2In=LrStringUtils.trimWhitespace(deNil(arrFirst[6]))
local xpos=LrStringUtils.trimWhitespace(deNil(arrFirst[7]))
local timeSinceWindowTalked=LrStringUtils.trimWhitespace(deNil(arrFirst[8]))
local lastKnownWindowUrl=LrStringUtils.trimWhitespace(deNil(arrFirst[9]))
local userIdIn=LrStringUtils.trimWhitespace(deNil(arrFirst[10]))
prefs.timeSinceWindowTalked=timeSinceWindowTalked
local bulkData=arrSlice(arrData,2,#arrData)
--myLogger:trace("addingkeywordtron" .. commandIn .. deNil(tidIn) .."*" .. deNil(tid) )
if commandIn~=nil then
bwlHadACommand=true
--myLogger:trace("three")
if tidIn==tid then
--myLogger:trace("four")
--myLogger:trace("commandIn=" .. commandIn .. ";value=" .. valueIn)
if commandIn=="redokeywords" then
--myLogger:trace("redo keywords" .. tostring(bulkData))
--myLogger:trace("redo keywords" .. objectDump(bulkData))
local i
myLogger:trace("before loop: " .. #bulkData)
for i=1, #bulkData do
updateProgress(0, #bulkData, i, 1, "Returning keywords to Lightroom.")
local thisLine=bulkData[i]
if thisLine~="" then
local arrLine=split("|", thisLine)
local metadata=arrLine[1]
local arrMetadata=split("^", metadata)
myLogger:trace("thisLine: " .. deNil(thisLine) )
local uuid=LrStringUtils.trimWhitespace(deNil(arrMetadata[1]))
local lat=LrStringUtils.trimWhitespace(deNil(arrMetadata[2]))
local lon=LrStringUtils.trimWhitespace(deNil(arrMetadata[3]))
local ftitle=LrStringUtils.trimWhitespace(deNil(arrMetadata[4]))
local fcaption=LrStringUtils.trimWhitespace(deNil(arrMetadata[5]))
local fcreator=LrStringUtils.trimWhitespace(deNil(arrMetadata[6]))
local fmodelReleaseStatus=LrStringUtils.trimWhitespace(deNil(arrMetadata[7]))
local fpropertyReleaseStatus=LrStringUtils.trimWhitespace(deNil(arrMetadata[8]))
local flocation=LrStringUtils.trimWhitespace(deNil(arrMetadata[9]))
local rheadline=LrStringUtils.trimWhitespace(deNil(arrMetadata[10]))
local fdateTimeOriginal=LrStringUtils.trimWhitespace(deNil(arrMetadata[11]))
local keywords=arrSlice(arrLine,2,#arrLine)
local photo=LrCatalog:findPhotoByUuid(uuid)
--app:call( Call:new{ name="Adding Keywords to " .. uuid, async=false, guard=App.guardVocal, main=function( call ) -- call as (async) task, and disallow recursive reentry - prompt user if he/she get's impatient (clicks button again before finished).
--local s, m = Catalog:update(4, call.name, function( context, phase )
app:call( Call:new{ name="Adding Keywords to " .. uuid, async=false, guard=App.guardVocal, main=function( call ) -- call as (async) task, and disallow recursive reentry - prompt user if he/she get's impatient (clicks button again before finished).
local s, m = Catalog:update(4, call.name, function( context, phase ) -- 4 second timeout
--local s, m = LrCatalog:withWriteAccessDo(call.name, function( context )
if photo~=nil then
--remove all keywords
local photoKeywords=photo:getRawMetadata("keywords")
local k
myLogger:trace("about to remove keywords")
for k=1,#photoKeywords do
local photoKeyword=photoKeywords[k]
--myLogger:trace("about to REALLY remove keywords: " .. tostring(photoKeyword))
--Debug.pause( photoKeyword )
photo:removeKeyword( photoKeyword )
end
myLogger:trace("removed keywords")
myLogger:trace("doing meta data")
photo:setRawMetadata("title", ftitle )
photo:setRawMetadata("caption", fcaption )
photo:setRawMetadata("creator", fcreator )
photo:setRawMetadata("modelReleaseStatus", fmodelReleaseStatus )
photo:setRawMetadata("propertyReleaseStatus", fpropertyReleaseStatus )
photo:setRawMetadata("location", flocation )
photo:setRawMetadata("headline", rheadline )
--HANDLE THE RETURN OF USER DATA
local h
if #arrMetadata>24 then
for h=26, #arrMetadata do
if string.find("xx" .. arrMetadata[h], "~" )~=nil then
local arrMetaInfo=split("~", arrMetadata[h])
local userMetaField=arrMetaInfo[1]
local keyval=arrMetaInfo[2]
if string.sub(userMetaField, 1, 1)=="-" then --begins with dash, it's a develop setting
userMetaField=string.sub(userMetaField, 2)
local settings=photo:getDevelopSettings()
if settings[userMetaField] ~=nil then
myLogger:trace("XXvalid dev setting:" .. userMetaField)
--no such command:
--photo:setDevelopSetting(userMetaField, keyval)
else
myLogger:trace("XXinvalid dev setting:" .. userMetaField)
end
elseif string.sub(userMetaField, 1, 1)=="_" then --begins with underscore, it's a getFormattedMetadata
userMetaField=string.sub(userMetaField, 2)
local settings=photo:getFormattedMetadata()
if settings[userMetaField] ~=nil then
myLogger:trace("XXvalid formatted setting:" .. userMetaField)
--no such command:
--photo:setFormatteddata(userMetaField, keyval)
else
myLogger:trace("XXinvalid formatted setting:" .. userMetaField)
end
else --else, it's raw meta data
local settings=photo:getRawMetadata()
if settings[userMetaField] ~=nil then
myLogger:trace("XXvalid unformatted setting:" .. userMetaField)
photo:setRawMetadata(userMetaField, keyval)
else
myLogger:trace("XXinvalid unformatted setting:" .. userMetaField)
end
end
end
end
end
--photo:setRawMetadata( "dateTimeOriginal", fdateTimeOriginal )
--myLogger:trace("did meta data")
local j
myLogger:trace("keyword count: " .. #keywords )
for j=1, #keywords do
myLogger:trace("aa")
local keywordText=LrStringUtils.trimWhitespace(deNil(keywords[j]))
if keywordText~="" then
--myLogger:trace("passed in keyword: " .. keywordText)
local thisLrKeyword = LrCatalog:createKeyword(keywordText, {}, true, nil, true)
--local knownKeywords=LrCatalog:getKeywords()
myLogger:trace("XX" .. tostring(deNil(thisLrKeyword)))
--myLogger:trace(tostring(deNil(thisLrKeyword:getName())))
--myLogger:trace("bb" )
--myLogger:trace("count known keywords:" .. #knownKeywords )
--for k=1, #knownKeywords do
--local thisKnownKeyword=deNil(knownKeywords[k])
--myLogger:trace("bc" )
--myLogger:trace("kwfound:" .. thisKnownKeyword:getName() )
--if keywordText==thisKnownKeyword:getName() then
--myLogger:trace("-" .. keywordText .. "+" .. thisKnownKeyword:getName() )
--myLogger:trace("cc " .. tostring(thisLrKeyword) )
--Debug.pause(thisLrKeyword )
if(thisLrKeyword) then
photo:addKeyword(thisLrKeyword)
end
--local photoKeywords=photo:getRawMetadata("keywords")
--myLogger:trace("2keyword count: " .. tostring(#photoKeywords))
--end
--end
end
end
end
end)
end})
--myLogger:trace("foundphoto=" .. deNil(tostring(photo)))
end
end
gotoWebpage(deNil(defaultMainPage) .. "?sess=" .. deNil(prefs.sess) .. "&mode=lastkeyworded*Keywords+exported+to+Lightroom.")
elseif commandIn=="clearsess" then
prefs.sess=""
prefs.pathname=""
sess=""
myLogger:trace("sess cleared")
elseif commandIn=="setprefs" then
--prefs[keyIn]=valueIn
myLogger:trace("prefs being set en masse".."tid=" .. tidIn)
for i=1, #bulkData do
local thisPair=bulkData[i]
if thisPair~="" then
local arrPair=split("|", thisPair)
myLogger:trace("pair:"..deNil(arrPair[1] .. "=" .. arrPair[2]))
prefs[deNil(arrPair[1])]=deNil(arrPair[2])
if deNil(arrPair[1])=="pathname" then
pathname=deNil(arrPair[2])
prefs.pathname=pathname
end
end
end
elseif commandIn=="setpref" then
prefs[keyIn]=valueIn
myLogger:trace("pref " .. keyIn .. " set to " .. valueIn .. "; tid=" .. tidIn)
elseif commandIn=="setsess" then
prefs.sess=valueIn
sess=valueIn
myLogger:trace("sess set to " .. valueIn .. "; tid=" .. tidIn)
elseif commandIn=="setdropboxpath" then
prefs.dropboxPath=valueIn
myLogger:trace("dropboxpath set to " .. valueIn .. "; tid=" .. tidIn)
elseif commandIn=="uploadcollections" then
--LrFunctionContext.callWithContext('uploadCatalog', uploadCatalog, valueIn, value2In)
uploadCatalog("collection")
myLogger:trace("collection uploaded;")
elseif commandIn=="uploadcatalog" then
--myLogger:trace("uploadcatalog")
--LrFunctionContext.callWithContext('uploadCatalog', uploadCatalog, valueIn, value2In)
uploadCatalog("catalog", valueIn, value2In)
myLogger:trace("catalog uploaded; tid=" .. tidIn)
elseif commandIn=="setmetadata" then
setMetaData(valueIn)
myLogger:trace("metadata=" .. valueIn)
elseif commandIn=="dialog" then
if valueIn == nil or valueIn=="" then
myLogger:trace("NO MESSAGE!" )
else
myLogger:trace("dialog:" .. valueIn)
LrDialogs.message( valueIn, value2In )
end
elseif commandIn=="allowpageopen" then
prefs.allowpageopen=true
elseif commandIn=="preventpageopen" then
prefs.allowpageopen=false
elseif commandIn=="gotowebpage" then
myLogger:trace("GOING TO WEB PAGE FROM COMMAND:" ..valueIn )
gotoWebpage(valueIn)
elseif commandIn=="openwindow" then
if valueIn == nil or valueIn=="" then
myLogger:trace("NO URL!" )
else
--if not appData.windowOpen then
--if string.find( "xxx" .. valueIn, "http://" )>1 then
appData.windowUrl=valueIn
myLogger:trace("opening window:" .. valueIn)
--if xpos=="x" and tonumber(timeSinceWindowTalked)>2 then
--asyncMe(webOpen, "one")
--appData.timeWhenWindowOpened=os.time()
--end
--else
--end
end
end
--always open the window if it's been closed
if lastKnownWindowUrl=="" or lastKnownWindowUrl==nil then
--prefs.sess=""
end
if xpos=="x" then
--myLogger:trace("about to show user:")
--myLogger:trace("user:" .. tostring(userIdIn))
if userIdIn=="" then
userIdIn=0
end
userIdIn=tonumber(userIdIn)
--myLogger:trace("showed user:")
-- and tonumber(userIdIn)>0
if tonumber(timeSinceWindowTalked)>5 and (os.time() -appData.timeWhenWindowOpened)>3 and userIdIn>0 then
--probably need a login for this case:
--myLogger:trace("timesince1:" .. timeSinceWindowTalked .. " local:" .. os.time() -appData.timeWhenWindowOpened )
appData.windowUrl=urlBase .. deNil(defaultMainPage) .. "?sess=" .. prefs.sess
--asyncMe(webOpen, "one")
--i hadn't been doing this here for some reason:
--perhaps doing this too much:
--appData.windowOpen=false
--appData.timeWhenWindowOpened=os.time()
--initiateOpenWindow()
elseif tonumber(timeSinceWindowTalked)>12 and (os.time() -appData.timeWhenWindowOpened)>12 and userIdIn>0 then
if prefs.allowpageopen then
myLogger:trace(prefs.sess)
myLogger:trace("timesince:" .. timeSinceWindowTalked .. " local:" .. os.time() -appData.timeWhenWindowOpened )
--asyncMe(webOpen, "one")
--asyncMe(webOpen, "one")
--perhaps doing this too much:
appData.windowOpen=false
--appData.timeWhenWindowOpened=os.time()
--initiateOpenWindow()
else
appData.timeWhenWindowOpened=os.time()
end
end
prefs.lastKnownWindowUrl=lastKnownWindowUrl
end
if prefs.bwlNeedAUserInteractionWindow then
----local completionUrl=actionBase .. "&command=" .. "gotowebpage¶meter=" .. url_encode("http://a2zkeywording.com/lr_web/keywordperfect.php?sess=" .. prefs.sess .. "&mode=enter")
--myLogger:trace("opening a url from polldata")
----local completionData=deNil(http_get(completionUrl, {}))
--gotoWebpage("keywordperfect.php?sess=" .. prefs.sess .. "&mode=intro")
----gotoEntryWebpageForm()
--prefs.bwlNeedAUserInteractionWindow=false
end
end
end
end
end
end
--end
oldThirdDigitBack=thirdDigitBack
LrTasks.sleep( 1 )
outthrough=outthrough+1
end
end
end
function setMetaData(value)
if value~="" then
prefs.arrExtraMetaData=str:split(value, ' ')
end
end
function url_encode(str)
if (str) then
str = string.gsub (str, "\n", "\r\n")
str = string.gsub (str, "([^%w ])",
function (c) return string.format ("%%%02X", string.byte(c)) end)
str = string.gsub (str, " ", "+")
end
return str
end
function http_get(base, data)
local str = base .. '?'
for key, value in pairs(data) do
str = str .. key .. '=' .. url_encode(value)
str = str .. '&'
end
local result, headers = LrHttp.get(str, {}, 2)
if headers.status ~= 200 and headers.status then
error('method call to ' .. str .. ' returned status ' .. headers.status)
end
return result
end
function wrap_call(func, location)
return LrFunctionContext.callWithContext('error_context', function(context)
context:addFailureHandler(function(result, message)
reportError(message, location)
end)
return func()
end)
end
function existingKeywords(photo)
local photoKeywords=photo:getRawMetadata("keywords")
local strOut=""
local k
myLogger:trace("about to compile keywords")
myLogger:trace("count of keywords:" .. #photoKeywords)
for k=1,#photoKeywords do
myLogger:trace("aa")
local photoKeyword=photoKeywords[k]
myLogger:trace("ab")
if string.len(strOut) > 0 then
strOut = strOut .. ", "
end
strOut = strOut .. deNil(photoKeyword:getName())
myLogger:trace("ac")
end
return strOut
end
function asyncMe(func, location)
local async
if debugger_on then
async = LrTasks.startAsyncTask
else
async = LrTasks.startAsyncTaskWithoutErrorHandler
end
async(function()
return wrap_call(func, location)
end)
end
function initiateOpenWindow()
asyncMe(webOpen, "one")
appData.windowOpen=true
appData.timeWhenWindowOpened=os.time()
end
function webOpen()
local url=""
myLogger:trace("webopen base:" .. deNil(urlBase))
myLogger:trace("webopen nonbase:" .. deNil(appData.windowUrl))
if appData.windowUrl==nil then
appData.windowUrl= prefs.lastKnownWindowUrl
end
if string.find( "xxx" .. appData.windowUrl, "http:" )==nil then
url=urlBase .. appData.windowUrl
else
url= appData.windowUrl
end
myLogger:trace("opening:" .. url)
LrHttp.openUrlInBrowser(url)
end
myLogger:trace( "USER META: " .. tostring(deNil(prefs.arrExtraMetaData)))