-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathStashExportServiceProvider.lua
727 lines (603 loc) · 34.7 KB
/
StashExportServiceProvider.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
--[[----------------------------------------------------------------------------
StashExportServiceProvider.lua
Export service provider description for Lightroom Stash uploader
------------------------------------------------------------------------------]]
-- Lightroom SDK
local LrBinding = import 'LrBinding'
local LrDialogs = import 'LrDialogs'
local LrFileUtils = import 'LrFileUtils'
local LrPathUtils = import 'LrPathUtils'
local LrView = import 'LrView'
local LrStringUtils = import 'LrStringUtils'
local prefs = import 'LrPrefs'.prefsForPlugin()
local LrDate = import 'LrDate'
local logger = import 'LrLogger'( 'Stash' )
-- Common shortcuts
local bind = LrView.bind
local share = LrView.share
-- Stash plug-in
require 'StashAPI'
require 'StashUser'
require 'Utils'
--------------------------------------------------------------------------------
-- NOTE to developers reading this sample code: This file is used to generate
-- the documentation for the "export service provider" section of the API
-- reference material. This means it's more verbose than it would otherwise
-- be, but also means that you can match up the documentation with an actual
-- working example. It is not necessary for you to preserve any of the
-- documentation comments in your own code.
--===========================================================================--
--[[ @sdk
--- The <i>service definition script</i> for an export service provider defines the hooks
-- that your plug-in uses to extend the behavior of Lightroom's Export features.
-- The plug-in's <code>Info.lua</code> file identifies this script in the
-- <code>LrExportServiceProvider</code> entry.
-- <p>The service definition script should return a table that contains:
-- <ul><li>A pair of functions that initialize and terminate your export service. </li>
-- <li>Settings that you define for your export service.</li>
-- <li>One or more items that define the desired customizations for the Export dialog.
-- These can restrict the built-in services offered by the dialog,
-- or customize the dialog by defining new sections. </li>
-- <li> A function that defines the export operation to be performed
-- on rendered photos (required).</li> </ul>
-- <p>The <code>StashExportServiceProvider.lua</code> file of the Stash sample plug-in provides
-- examples of and documentation for the hooks that a plug-in must provide in order to
-- define an export service. Lightroom expects your plug-in to define the needed callbacks
-- and properties with the required names and syntax. </p>
-- <p>Unless otherwise noted, all of the hooks in this section are available to
-- both Export and Publish service provider plug-ins. If your plug-in supports
-- Lightroom's Publish feature, you should also read the API reference section
-- <a href="SDK%20-%20Publish%20service%20provider.html">publish service provider</a>.</p>
-- @module_type Plug-in provided
module 'SDK - Export service provider' -- not actually executed, but suffices to trick LuaDocs
--]]
--============================================================================--
local exportServiceProvider = {}
--------------------------------------------------------------------------------
--- (optional) Plug-in defined value declares whether this plug-in supports the Lightroom
-- publish feature. If not present, this plug-in is available in Export only.
-- When true, this plug-in can be used for both Export and Publish. When
-- set to the string "only", the plug-in is visible only in Publish.
-- @name exportServiceProvider.supportsIncrementalPublish
-- @class property
exportServiceProvider.supportsIncrementalPublish = 'true'
--------------------------------------------------------------------------------
--- (optional) Plug-in defined value declares which fields in your property table should
-- be saved as part of an export preset or a publish service connection. If present,
-- should contain an array of items with key and default values. For example:
-- <pre>
-- exportPresetFields = {<br/>
-- { key = 'username', default = "" },<br/>
-- { key = 'fullname', default = "" },<br/>
-- { key = 'nsid', default = "" },<br/>
-- { key = 'privacy', default = 'public' },<br/>
-- { key = 'privacy_family', default = false },<br/>
-- { key = 'privacy_friends', default = false },<br/>
-- }<br/>
-- </pre>
-- <p>The <code>key</code> item should match the values used by your user interface
-- controls.</p>
-- <p>The <code>default</code> item is the value to the first time
-- your plug-in is selected in the Export or Publish dialog. On second and subsequent
-- activations, the values chosen by the user in the previous session are used.</p>
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @name exportServiceProvider.exportPresetFields
-- @class property
exportServiceProvider.exportPresetFields = {
{ key = 'titleFirstChoice', default = 'title'},
{ key = 'titleSecondChoice', default = 'filename'},
{ key = 'overwriteMetadata', default = false}
}
--------------------------------------------------------------------------------
--- (optional) Plug-in defined value suppresses the display of the named sections in
-- the Export or Publish dialogs. You can use either <code>hideSections</code> or
-- <code>showSections</code>, but not both. If present, this should be an array
-- containing one or more of the following strings:
-- <ul>
-- <li>exportLocation</li>
-- <li>fileNaming</li>
-- <li>fileSettings</li>
-- <li>imageSettings</li>
-- <li>outputSharpening</li>
-- <li>metadata</li>
-- <li>watermarking</li>
-- </ul>
-- <p>You cannot suppress display of the "Connection Name" section in the Publish Manager dialog.</p>
-- <p>If you suppress the "exportLocation" section, the files are rendered into
-- a temporary folder which is deleted immediately after the Export operation
-- completes.</p>
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @name exportServiceProvider.hideSections
-- @class property
exportServiceProvider.hideSections = { 'exportLocation' }
--------------------------------------------------------------------------------
--- (optional) Plug-in defined value restricts the available file format choices in the
-- Export or Publish dialogs to those named. You can use either <code>allowFileFormats</code> or
-- <code>disallowFileFormats</code>, but not both. If present, this should be an array
-- containing one or more of the following strings:
-- <ul>
-- <li>JPEG</li>
-- <li>PSD</li>
-- <li>TIFF</li>
-- <li>DNG</li>
-- <li>ORIGINAL</li>
-- </ul>
-- <p>This property affects the output of still photo files only;
-- it does not affect the output of video files.
-- See <a href="#exportServiceProvider.canExportVideo"><code>canExportVideo</code></a>.)</p>
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @name exportServiceProvider.allowFileFormats
-- @class property
exportServiceProvider.allowFileFormats = { 'JPEG' }
--------------------------------------------------------------------------------
--- (optional) Plug-in defined value restricts the available color space choices in the
-- Export or Publish dialogs to those named. You can use either <code>allowColorSpaces</code> or
-- <code>disallowColorSpaces</code>, but not both. If present, this should be an array
-- containing one or more of the following strings:
-- <ul>
-- <li>sRGB</li>
-- <li>AdobeRGB</li>
-- <li>ProPhotoRGB</li>
-- </ul>
-- <p>Affects the output of still photo files only, not video files.
-- See <a href="#exportServiceProvider.canExportVideo"><code>canExportVideo</code></a>.</p>
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @name exportServiceProvider.allowColorSpaces
-- @class property
exportServiceProvider.allowColorSpaces = { 'sRGB' }
--------------------------------------------------------------------------------
--- (optional, Boolean) Plug-in defined value is true to hide print resolution controls
-- in the Image Sizing section of the Export or Publish dialog.
-- (Recommended when uploading to most web services.)
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @name exportServiceProvider.hidePrintResolution
-- @class property
exportServiceProvider.hidePrintResolution = true
--------------------------------------------------------------------------------
--- (optional, Boolean) When plug-in defined value istrue, both video and
-- still photos can be exported through this plug-in. If not present or set to false,
-- video files cannot be exported through this plug-in. If set to the string "only",
-- video files can be exported, but not still photos.
-- <p>No conversions are available for video files. They are simply
-- copied in the same format that was originally imported into Lightroom.</p>
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @name exportServiceProvider.canExportVideo
-- @class property
exportServiceProvider.canExportVideo = false
--------------------------------------------------------------------------------
-- (string) Plug-in defined value is the filename of the icon to be displayed
-- for this publish service provider, in the Publish Services panel, the Publish
-- Manager dialog, and in the header shown when a published collection is selected.
-- The icon must be in PNG format and no more than 26 pixels wide or 19 pixels tall.
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @name exportServiceProvider.small_icon
-- @class property
exportServiceProvider.small_icon = 'logo.png'
--------------------------------------------------------------------------------
--- (optional, string) Plug-in defined value customizes the behavior of the
-- Description entry in the Publish Manager dialog. If the user does not provide
-- an explicit name choice, Lightroom can provide one based on another entry
-- in the publishSettings property table. This entry contains the name of the
-- property that should be used in this case.
-- @name exportServiceProvider.publish_fallbackNameBinding
-- @class property
exportServiceProvider.publish_fallbackNameBinding = 'fullname'
--------------------------------------------------------------------------------
--- When set to the string "disable", the "Go to Published Collection" context-menu item
-- is disabled (dimmed) for this publish service.
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @name exportServiceProvider.titleForGoToPublishedCollection
-- @class property
-- Sta.sh doesn't seem to allow going to a folder directly.
exportServiceProvider.titleForGoToPublishedCollection = "disable"
--------------------------------------------------------------------------------
--- (optional, string) Plug-in defined value overrides the label for the
-- "Go to Published Photo" context-menu item, allowing you to use something more appropriate to
-- your service. Set to the special value "disable" to disable (dim) the menu item for this service.
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @name exportServiceProvider.titleForGoToPublishedPhoto
-- @class property
exportServiceProvider.titleForGoToPublishedPhoto = LOC "$$$/Stash/TitleForGoToPublishedCollection=Show in Sta.sh"
--------------------------------------------------------------------------------
--- This plug-in defined callback function is called when the user attempts to change the name
-- of a collection, to validate that the new name is acceptable for this service.
-- <p>This is a blocking call. You should use it only to validate easily-verified
-- characteristics of the name, such as illegal characters in the name. For
-- characteristics that require validation against a server (such as duplicate
-- names), you should accept the name here and reject the name when the server-side operation
-- is attempted.</p>
-- @name exportServiceProvider.validatePublishedCollectionName
-- @class function
-- @param proposedName (string) The name as currently typed in the new/rename/edit
-- collection dialog.
-- @return (Boolean) True if the name is acceptable, false if not
-- @return (string) If the name is not acceptable, a string that describes the reason, suitable for display.
-- Unknown what the Sta.sh API allows as a folder name. Assuming it's only ASCII
function exportServiceProvider.validatePublishedCollectionName( proposedName )
return LrStringUtils.isOnlyAscii( proposedName )
end
-------------------------------------------------------------------------------
function exportServiceProvider.metadataThatTriggersRepublish( publishSettings )
return {
default = false,
title = true,
caption = true,
keywords = true,
}
end
-------------------------------------------------------------------------------
--- (Boolean) This plug-in defined value, when true, disables (dims) the Rename Published
-- Collection command in the context menu of the Publish Services panel
-- for all published collections created by this service.
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @name exportServiceProvider.disableRenamePublishedCollection
-- @class property
-- Sta.sh allows renames, but the API is currently broken.
exportServiceProvider.disableRenamePublishedCollection = false
-------------------------------------------------------------------------------
--- This plug-in callback function is called when the user has renamed a
-- published collection via the Publish Services panel user interface. This is
-- your plug-in's opportunity to make the corresponding change on the service.
-- <p>If your plug-in is unable to update the remote service for any reason,
-- you should throw a Lua error from this function; this causes Lightroom to revert the change.</p>
-- <p>This is not a blocking call. It is called from within a task created
-- using the <a href="LrTasks.html"><code>LrTasks</code></a> namespace. In most
-- cases, you should not need to start your own task within this function.</p>
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @name publishServiceProvider.renamePublishedCollection
-- @class function
-- @param publishSettings (table) The settings for this publish service, as specified
-- by the user in the Publish Manager dialog. Any changes that you make in
-- this table do not persist beyond the scope of this function call.
-- @param info (table) A table with these fields:
-- <ul>
-- <li><b>isDefaultCollection</b>: (Boolean) True if this is the default collection.</li>
-- <li><b>name</b>: (string) The new name being assigned to this collection.</li>
-- <li><b>parents</b>: (table) An array of information about parents of this collection, in which each element contains:
-- <ul>
-- <li><b>localCollectionId</b>: (number) The local collection ID.</li>
-- <li><b>name</b>: (string) Name of the collection set.</li>
-- <li><b>remoteCollectionId</b>: (number or string) The remote collection ID assigned by the server.</li>
-- </ul> </li>
-- <li><b>publishService</b>: (<a href="LrPublishService.html"><code>LrPublishService</code></a>)
-- The publish service object.</li>
-- <li><b>publishedCollection</b>: (<a href="LrPublishedCollection.html"><code>LrPublishedCollection</code></a>
-- or <a href="LrPublishedCollectionSet.html"><code>LrPublishedCollectionSet</code></a>)
-- The published collection object being renamed.</li>
-- <li><b>remoteId</b>: (string or number) The ID for this published collection
-- that was stored via <a href="LrExportSession.html#exportSession:recordRemoteCollectionId"><code>exportSession:recordRemoteCollectionId</code></a></li>
-- <li><b>remoteUrl</b>: (optional, string) The URL, if any, that was recorded for the published collection via
-- <a href="LrExportSession.html#exportSession:recordRemoteCollectionUrl"><code>exportSession:recordRemoteCollectionUrl</code></a>.</li>
-- </ul>
function exportServiceProvider.renamePublishedCollection( publishSettings, info )
if info.remoteId then
StashAPI.renameFolder( info.remoteId, info.name )
end
end
-------------------------------------------------------------------------------
--- (optional) This plug-in defined callback function is called whenever a
-- published photo is selected in the Library module. Your implementation should
-- return true if there is a viable connection to the publish service and
-- comments can be added at this time. If this function is not implemented,
-- the new comment section of the Comments panel in the Library is left enabled
-- at all times for photos published by this service. If you implement this function,
-- it allows you to disable the Comments panel temporarily if, for example,
-- the connection to your server is down.
-- <p>This is not a blocking call. It is called from within a task created
-- using the <a href="LrTasks.html"><code>LrTasks</code></a> namespace. In most
-- cases, you should not need to start your own task within this function.</p>
-- <p>First supported in version 3.0 of the Lightroom SDK.</p>
-- @param publishSettings (table) The settings for this publish service, as specified
-- by the user in the Publish Manager dialog. Any changes that you make in
-- this table do not persist beyond the scope of this function call.
-- @return (Boolean) True if comments can be added at this time.
-- Sta.sh doesn't support comments at this time
function exportServiceProvider.canAddCommentsToService( publishSettings )
return false
end
--------------------------------------------------------------------------------
local function updateCantExportBecause( propertyTable )
if not propertyTable.validAccount then
propertyTable.LR_cantExportBecause = "You haven't logged in to Sta.sh yet."
return
end
propertyTable.LR_cantExportBecause = nil
end
local displayNameForTitleChoice = {
filename = LOC "$$$/Stash/ExportDialog/Title/Filename=Filename",
title = LOC "$$$/Stash/ExportDialog/Title/Title=IPTC Title",
empty = LOC "$$$/Stash/ExportDialog/Title/Empty=Leave Blank",
}
local function getStashTitle( photo, exportSettings, pathOrMessage )
local title
-- Get title according to the options in Stash Title section.
if exportSettings.titleFirstChoice == 'filename' then
title = LrPathUtils.leafName(pathOrMessage)
elseif exportSettings.titleFirstChoice == 'title' then
title = photo:getFormattedMetadata 'title'
if (not title or #title == 0) and exportSettings.titleSecondChoice == 'filename' then
title = LrPathUtils.leafName(pathOrMessage)
end
else
title = "Untitled"
end
return title
end
--------------------------------------------------------------------------------
function exportServiceProvider.getCollectionBehaviorInfo( publishSettings )
return {
defaultCollectionName = LOC "$$$/Stash/DefaultCollectionName/Publish to Sta.sh=Publish to Sta.sh",
defaultCollectionCanBeDeleted = false,
canAddCollection = true,
maxCollectionSetDepth = 0,
-- Collection sets are not supported in Sta.sh.
}
end
-----------------------------------------------------------------------------------
-- (optional) This plug-in defined callback function is called when the
-- user chooses this export service provider in the Export or Publish dialog,
-- or when the destination is already selected when the dialog is invoked,
-- (remembered from the previous export operation).
-- <p>This is a blocking call. If you need to start a long-running task (such as
-- network access), create a task using the <a href="LrTasks.html"><code>LrTasks</code></a>
-- namespace.</p>
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @param propertyTable (table) An observable table that contains the most
-- recent settings for your export or publish plug-in, including both
-- settings that you have defined and Lightroom-defined export settings
-- @name exportServiceProvider.startDialog
-- @class function
function exportServiceProvider.startDialog( propertyTable )
-- Can't export until we've validated the login.
propertyTable:addObserver( 'validAccount', function() updateCantExportBecause( propertyTable ) end )
updateCantExportBecause( propertyTable )
-- Make sure we're logged in.
require 'StashUser'
StashUser.verifyLogin( propertyTable )
end
--------------------------------------------------------------------------------
--- (optional) This plug-in defined callback function is called when the user
-- chooses this export service provider in the Export or Publish dialog.
-- It can create new sections that appear above all of the built-in sections
-- in the dialog (except for the Publish Service section in the Publish dialog,
-- which always appears at the very top).
-- <p>Your plug-in's <a href="#exportServiceProvider.startDialog"><code>startDialog</code></a>
-- function, if any, is called before this function is called.</p>
-- <p>This is a blocking call. If you need to start a long-running task (such as
-- network access), create a task using the <a href="LrTasks.html"><code>LrTasks</code></a>
-- namespace.</p>
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @param f (<a href="LrView.html#LrView.osFactory"><code>LrView.osFactory</code> object)
-- A view factory object.
-- @param propertyTable (table) An observable table that contains the most
-- recent settings for your export or publish plug-in, including both
-- settings that you have defined and Lightroom-defined export settings
-- @return (table) An array of dialog sections (see example code for details)
-- @name exportServiceProvider.sectionsForTopOfDialog
-- @class function
function exportServiceProvider.sectionsForTopOfDialog( f, propertyTable )
return {
{
title = "Sta.sh account",
synopsis = bind 'accountStatus',
f:row {
spacing = f:control_spacing(),
f:static_text {
title = bind 'accountStatus',
alignment = 'right',
fill_horizontal = 1,
},
f:push_button {
width = 90,
title = bind 'loginButtonTitle',
enabled = bind 'loginButtonEnabled',
action = function()
require 'StashUser'
StashUser.login( propertyTable )
end,
},
},
},
{
title = LOC "$$$/Stash/ExportDialog/Title=Sta.sh Options",
synopsis = function( props )
if props.titleFirstChoice == 'title' then
return LOC( "$$$/Stash/ExportDialog/Synopsis/TitleWithFallback=IPTC Title or ^1", displayNameForTitleChoice[ props.titleSecondChoice ] )
else
return props.titleFirstChoice and displayNameForTitleChoice[ props.titleFirstChoice ] or ''
end
end,
f:column {
spacing = f:control_spacing(),
f:row {
spacing = f:label_spacing(),
f:static_text {
title = LOC "$$$/Stash/ExportDialog/ChooseTitleBy=Set Stash Title Using:",
alignment = 'right',
width = share 'StashTitleSectionLabel',
},
f:popup_menu {
value = bind 'titleFirstChoice',
width = share 'StashTitleLeftPopup',
items = {
{ value = 'filename', title = displayNameForTitleChoice.filename },
{ value = 'title', title = displayNameForTitleChoice.title },
{ value = 'empty', title = displayNameForTitleChoice.empty },
},
},
f:spacer { width = 20 },
f:static_text {
title = LOC "$$$/Stash/ExportDialog/ChooseTitleBySecondChoice=If Empty, Use:",
enabled = LrBinding.keyEquals( 'titleFirstChoice', 'title', propertyTable ),
},
f:popup_menu {
value = bind 'titleSecondChoice',
enabled = LrBinding.keyEquals( 'titleFirstChoice', 'title', propertyTable ),
items = {
{ value = 'filename', title = displayNameForTitleChoice.filename },
{ value = 'empty', title = displayNameForTitleChoice.empty },
},
},
},
f:row {
spacing = f:label_spacing(),
f:static_text {
title = LOC "$$$/Stash/ExportDialog/OverwriteMetadata=When updating a published photo:",
alignment = 'right',
width = share 'StashOverwriteMetadata',
},
f:popup_menu {
value = bind 'overwriteMetadata',
width = share 'StashOverwriteMetadataPopup',
items = {
{ value = true, title = "Overwrite existing title, keywords and description" },
{ value = false, title = "Leave existing title, keywords and description" },
},
},
}
},
},
}
end
--------------------------------------------------------------------------------
--- (optional) This plug-in defined callback function is called for each exported photo
-- after it is rendered by Lightroom and after all post-process actions have been
-- applied to it. This function is responsible for transferring the image file
-- to its destination, as defined by your plug-in. The function that
-- you define is launched within a cooperative task that Lightroom provides. You
-- do not need to start your own task to run this function; and in general, you
-- should not need to start another task from within your processing function.
-- <p>First supported in version 1.3 of the Lightroom SDK.</p>
-- @param functionContext (<a href="LrFunctionContext.html"><code>LrFunctionContext</code></a>)
-- function context that you can use to attach clean-up behaviors to this
-- process; this function context terminates as soon as your function exits.
-- @param exportContext (<a href="LrExportContext.html"><code>LrExportContext</code></a>)
-- Information about your export settings and the photos to be published.
function exportServiceProvider.processRenderedPhotos( functionContext, exportContext )
-- Ensure that the auth tokens are still good
if not (prefs.expire == nil) and (tonumber(prefs.expire) < LrDate.currentTime()) then
StashAPI.refreshAuth()
end
if not StashUser.storedCredentialsAreValid() == true then
LrErrors.throwUserError( "Something's up with your login credentials, they're not valid!" )
end
-- Make a local reference to the export parameters.
local exportSession = exportContext.exportSession
local exportSettings = assert(exportContext.propertyTable)
-- Get the # of photos.
local numPhotos = exportSession:countRenditions()
-- By default, use the stackName "Lightroom Exports" with there's more than 1 image uploaded.
-- This is the case for exporting.
-- For publishing, the name becomes "Uploaded by Lightroom"
local stackName = "Lightroom Exports"
local stackId = nil
-- Setup a variable to distinguish if we're trying to publish, or just exporting
local publishing = false
if exportContext.publishService then
publishing = true
local publishedCollectionInfo = exportContext.publishedCollectionInfo
local isDefaultCollection = publishedCollectionInfo.isDefaultCollection
-- However, if we're uploading from the default collection, then just dump stuff into a folder labelled
-- "Uploaded by Lightroom"
-- The presumed use-case of this collection is piece-meal uploading, so in virtually all cases, this is fine.
-- However, if the user creates a collection, we'll create a corresponding folder on Sta.sh.
if isDefaultCollection then
stackName = "Uploaded by Lightroom"
else
stackName = publishedCollectionInfo.name
end
if publishedCollectionInfo.remoteId ~= nil and StashAPI.verifyStackExists(publishedCollectionInfo.remoteId) then
stackId = publishedCollectionInfo.remoteId
end
end
-- Set progress title depending on whether we're exporting or publishing,
-- and if we're exporting/publishing more than one photo.
local action = "Exporting"
if publishing then
action = "Publishing"
end
local action_title = string.format("%s one photo to Sta.sh", action)
if numPhotos > 1 then
action_title = string.format("%s %s photos to Sta.sh", action, numPhotos)
end
local progressScope = exportContext:configureProgress {title = action_title}
-- Iterate through photos.
for i, rendition in exportContext:renditions {stopIfCanceled = true} do
-- Update progress scope.
progressScope:setPortionComplete((i - 1)/numPhotos)
-- Get next photo.
local photo = rendition.photo
-- Keep StashID local to each iteration of the loop, otherwise Lua will make it persist across loops
-- Bad Thing because Lightroom seems to upload changed images before moving onto new ones, so the new ones will
-- constantly overwrite the last image that was modified.
-- Fixes https://github.com/kyl191/lr-stash/issues/1
local itemId = nil
if publishing and rendition.publishedPhotoId then
itemId = rendition.publishedPhotoId
logger:debug("Found existing stash id: " .. itemId)
end
if not rendition.wasSkipped then
local success, pathOrMessage = rendition:waitForRender()
-- Update progress scope again once we've got rendered photo.
progressScope:setPortionComplete( ( i - 0.5 ) / numPhotos )
-- Check for cancellation again after photo has been rendered.
if progressScope:isCanceled() then break end
if success then
-- Build up common metadata for this photo.
local title = getStashTitle(photo, exportSettings, pathOrMessage)
local description = photo:getFormattedMetadata('caption')
local keywordTags = photo:getFormattedMetadata('keywordTagsForExport')
local tags
if keywordTags then
tags = {}
local keywordIter = string.gfind( keywordTags, "[^,]+" )
for keyword in keywordIter do
-- Strip non-alphanumeric characters from keyword
if string.find( keyword, "[^%w*]") ~= nil then
keyword = string.gsub( keyword, "[^%w*]", "" )
end
table.insert(tags, keyword)
end
end
-- Upload or replace the photo
StashInfo = StashAPI.uploadPhoto({
filePath = pathOrMessage,
title = title,
description = description,
tags = table.concat(tags, ' '),
itemId = itemId or nil,
stackId = stackId or nil,
stackName = stackName or nil,
overwriteMetadata = exportSettings.overwriteMetadata or nil,
})
Utils.logTable(StashInfo, "Upload Result")
if publishing then
-- the itemid is a unsigned long int, which Lua doesn't support
-- so convert it to text
if type(StashInfo.itemid) == 'number' then
StashInfo.itemid = LrStringUtils.numberToString(StashInfo.itemid)
end
logger:info("Recording item id " .. StashInfo.itemid)
rendition:recordPublishedPhotoId(StashInfo.itemid)
rendition:recordPublishedPhotoUrl("https://sta.sh/1" .. StashInfo.itemid)
end
-- Sta.sh is now assigning new stackids to each upload
-- Set the stackid on the first upload if it's a new folder or the recorded folder
-- doesn't exist
if publishedCollectionInfo.remoteId == nil or
not StashAPI.verifyStackExists(publishedCollectionInfo.remoteId) then
stackId = LrStringUtils.numberToString(StashInfo.stackid)
logger:info(string.format("Recording stackId: %s", stackId))
exportSession:recordRemoteCollectionId(stackId)
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)
prefs.uploadCount = prefs.uploadCount + 1
end
end
end
progressScope:done()
end
--------------------------------------------------------------------------------
return exportServiceProvider