Skip to content

Commit 52fb1c9

Browse files
committed
refactor custom render decision flow and move property table dump to utils
1 parent d7c5edf commit 52fb1c9

13 files changed

Lines changed: 1673 additions & 1302 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ cat layout.odt
2424
deploy.sh
2525
diagnostic.txt
2626
copilot-instructions.md
27+
DEBUG-TODO.md
2728

2829
# Temporary folder for localisation tools
2930
piwigoPublish.lrplugin/__i18n_tmp__/

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Changelog
22
## [20269999.99]
33
### Fixed
4-
Associating an existing image with a new album would not upload image if it had been changed in LrC since first upload to Piwigo
4+
Fix #45 Unable to remove photos from Piwigo
5+
Associating an existing image with a new album should force re-upload of image if it had been changed in LrC since first upload to Piwigo
56
### Added
67
Fix #12 Feature request: Keyword removal by filtering when publising images to Piwigo
8+
Image assoication behaviour made optional to allow per-album custom export settings
79

810
## [20260221.33] - 2026-02-21
911
### Fixed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ This plugin was developed to allow me to continue publishing to Piwigo from LrC,
3030

3131
[Jeffrey Friedl for JSON.lua](http://regex.info/blog/lua/json)
3232

33-
[Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software for md5.lua](https://github.com/kikito/md5.lua)
34-
3533
[Bastian Machek with his Immich Plugin](https://github.com/bmachek/lrc-immich-plugin)
3634

3735
[Min Idzelis with his Immich Plugin](https://github.com/midzelis/mi.Immich.Publisher)

piwigoPublish.lrplugin/Init.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ _G.LrExportSettings = import "LrExportSettings"
4747

4848
-- Global requires
4949
_G.JSON = require "JSON"
50-
_G.md5 = require "md5"
5150
_G.utils = require "utils"
5251
_G.PiwigoAPI = require "PiwigoAPI"
5352
_G.PWImportService = require "PWImportService"

piwigoPublish.lrplugin/PWSendMetadata.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,10 @@ local function SendMetadata()
102102
end
103103
callStatus = {}
104104
local metaData = {}
105-
105+
local collectionSettings = {}
106+
-- todo - get collections for collection this photo is in so collection level overrides can be applied when building metadata structure
106107
-- build metadata structure
107-
metaData = utils.getPhotoMetadata(publishSettings, lrPhoto)
108+
metaData = utils.getPhotoMetadata(publishSettings, lrPhoto, collectionSettings)
108109
metaData.Remoteid = remoteId
109110

110111
-- get keyword filters from publishSettings and build include / exclude patterns

piwigoPublish.lrplugin/PiwigoAPI.lua

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,7 @@ function PiwigoAPI.getInfos(propertyTable)
14351435
log:info("PiwigoAPI.getInfos - headers\n" .. utils.serialiseVar(headers))
14361436
log:info("PiwigoAPI.getInfos - getResponse\n" .. utils.serialiseVar(getResponse))
14371437
LrDialogs.message("PiwigoAPI.getInfos - Cannot get host information from Piwigo - " ..
1438-
(getResponse.errorMessage or "Unknown error"))
1438+
(getResponse.errorMessage or "Unknown error"))
14391439
return false
14401440
end
14411441

@@ -2142,36 +2142,43 @@ function PiwigoAPI.dissociateImageFromCategory(propertyTable, imageId, categoryI
21422142
end
21432143

21442144
log:info("PiwigoAPI.dissociateImageFromCategory - remaining categories: " .. #newCategoryIds)
2145-
2145+
callStatus.deletedImage = false
21462146
-- If image would be orphaned (no remaining categories), delete it entirely
21472147
if #newCategoryIds == 0 then
21482148
log:info("PiwigoAPI.dissociateImageFromCategory - image would be orphaned, deleting entirely")
2149-
return PiwigoAPI.deletePhoto(propertyTable, categoryId, imageId, callStatus)
2150-
end
2151-
2152-
-- Update image with new categories list (replaces all associations)
2153-
local categoriesStr = table.concat(newCategoryIds, ";")
2149+
local delcallStatus = PiwigoAPI.deletePhoto(propertyTable, categoryId, imageId, callStatus)
2150+
if delcallStatus.status then
2151+
callStatus.status = true
2152+
callStatus.statusMsg = "Image removed from category and deleted (was orphaned)"
2153+
else
2154+
callStatus.statusMsg = delcallStatus.statusMsg or "Failed to delete orphaned image"
2155+
end
21542156

2155-
local params = {
2156-
{ name = "method", value = "pwg.images.setInfo" },
2157-
{ name = "image_id", value = tostring(imageId) },
2158-
{ name = "categories", value = categoriesStr },
2159-
{ name = "multiple_value_mode", value = "replace" },
2160-
{ name = "pwg_token", value = propertyTable.token }
2161-
}
2157+
callStatus.deletedImage = true
2158+
else
2159+
-- Update image with new categories list (replaces all associations)
2160+
local categoriesStr = table.concat(newCategoryIds, ";")
2161+
2162+
local params = {
2163+
{ name = "method", value = "pwg.images.setInfo" },
2164+
{ name = "image_id", value = tostring(imageId) },
2165+
{ name = "categories", value = categoriesStr },
2166+
{ name = "multiple_value_mode", value = "replace" },
2167+
{ name = "pwg_token", value = propertyTable.token }
2168+
}
21622169

2163-
log:info("PiwigoAPI.dissociateImageFromCategory - new categories string: " .. categoriesStr)
2170+
log:info("PiwigoAPI.dissociateImageFromCategory - new categories string: " .. categoriesStr)
21642171

2165-
local postResponse = PiwigoAPI.httpPostMultiPart(propertyTable, params)
2172+
local postResponse = PiwigoAPI.httpPostMultiPart(propertyTable, params)
21662173

2167-
if postResponse.status then
2168-
callStatus.status = true
2169-
log:info("PiwigoAPI.dissociateImageFromCategory - success")
2170-
else
2171-
callStatus.statusMsg = postResponse.statusMsg or "Dissociation failed"
2172-
log:info("PiwigoAPI.dissociateImageFromCategory - failed: " .. callStatus.statusMsg)
2174+
if postResponse.status then
2175+
callStatus.status = true
2176+
log:info("PiwigoAPI.dissociateImageFromCategory - success")
2177+
else
2178+
callStatus.statusMsg = postResponse.statusMsg or "Dissociation failed"
2179+
log:info("PiwigoAPI.dissociateImageFromCategory - failed: " .. callStatus.statusMsg)
2180+
end
21732181
end
2174-
21752182
return callStatus
21762183
end
21772184

@@ -2326,10 +2333,10 @@ function PiwigoAPI.updateGallery(propertyTable, exportFilename, metaData)
23262333
end
23272334
if not (uploadSuccess) then
23282335
if httpHeaders.error then
2329-
statusDes = httpHeaders.error.name
2336+
statusDes = httpHeaders.error.name or ""
23302337
status = httpHeaders.error.errorCode
23312338
else
2332-
statusDes = httpHeaders.statusDes
2339+
statusDes = httpHeaders.statusDes or ""
23332340
status = httpHeaders.status
23342341
end
23352342
LrDialogs.message("Cannot upload - " .. metaData.fileName .. " to Piwigo - " .. status, statusDes)
@@ -2523,15 +2530,17 @@ function PiwigoAPI.deletePhoto(propertyTable, pwCatID, pwImageID, callStatus)
25232530
callStatus.status = true
25242531
callStatus.statusMsg = ""
25252532
else
2526-
log:info("PiwigoAPI.deletePhoto - propertyTable \n " .. utils.serialiseVar(utils.anonymisePropertyTable(propertyTable)))
2533+
log:info("PiwigoAPI.deletePhoto - propertyTable \n " ..
2534+
utils.serialiseVar(utils.anonymisePropertyTable(propertyTable)))
25272535
log:info("PiwigoAPI.deletePhoto - params \n" .. utils.serialiseVar(params))
25282536
log:info("PiwigoAPI.deletePhoto - httpResponse \n" .. utils.serialiseVar(httpResponse))
25292537
log:info("PiwigoAPI.deletePhoto - httpHeaders \n" .. utils.serialiseVar(httpHeaders))
25302538
callStatus.status = false
25312539
callStatus.statusMsg = body.message or ""
25322540
end
25332541
else
2534-
log:info("PiwigoAPI.deletePhoto - propertyTable \n " .. utils.serialiseVar(utils.anonymisePropertyTable(propertyTable)))
2542+
log:info("PiwigoAPI.deletePhoto - propertyTable \n " ..
2543+
utils.serialiseVar(utils.anonymisePropertyTable(propertyTable)))
25352544
log:info("PiwigoAPI.deletePhoto - params \n" .. utils.serialiseVar(params))
25362545
log:info("PiwigoAPI.deletePhoto - httpResponse \n" .. utils.serialiseVar(httpResponse))
25372546
log:info("PiwigoAPI.deletePhoto - httpHeaders \n" .. utils.serialiseVar(httpHeaders))
@@ -2635,7 +2644,8 @@ function PiwigoAPI.addComment(publishSettings, metaData)
26352644
-- get antispam token from image details (unique for each image)
26362645
local rtnStatus = PiwigoAPI.checkPhoto(publishSettings, metaData.remoteId)
26372646
if not rtnStatus.status then
2638-
log:info("PiwigoAPI.addComment - unanble to retrieve token\n" .. utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
2647+
log:info("PiwigoAPI.addComment - unanble to retrieve token\n" ..
2648+
utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
26392649
return false
26402650
end
26412651
local imageDets = rtnStatus.imageDets
@@ -2658,11 +2668,13 @@ function PiwigoAPI.addComment(publishSettings, metaData)
26582668
return false
26592669
end
26602670
if utils.nilOrEmpty(author) then
2661-
log:info("PiwigoAPI.addComment - missing author\n" .. utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
2671+
log:info("PiwigoAPI.addComment - missing author\n" ..
2672+
utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
26622673
return false
26632674
end
26642675
if utils.nilOrEmpty(key) then
2665-
log:info("PiwigoAPI.addComment - missing key\n" .. utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
2676+
log:info("PiwigoAPI.addComment - missing key\n" ..
2677+
utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
26662678
return false
26672679
end
26682680
-- Piwigo antispam forces a delay between the key being created and used
@@ -2759,7 +2771,7 @@ function PiwigoAPI.setAlbumCover(publishService)
27592771
log:info("publishservice" .. publishService:getName())
27602772
local catalog = LrApplication.activeCatalog()
27612773
local publishSettings = publishService:getPublishSettings()
2762-
log:info("publishSettings\n" .. utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
2774+
log:info("publishSettings\n" .. utils.serialiseVar(utils.anonymisePropertyTable(publishSettings)))
27632775

27642776
if not publishSettings then
27652777
LrDialogs.message("PiwigoAPI.setAlbumCover - Can't find PublishSettings for this publish collection", "",

piwigoPublish.lrplugin/PublishDialogSections.lua

Lines changed: 10 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -787,102 +787,22 @@ local function prefsDialog(f, propertyTable)
787787
},
788788

789789

790-
f:group_box {
791-
title = "Metadata Settings",
792-
font = "<system/bold>",
793-
fill_horizontal = 1,
794-
795-
f:spacer { height = 2 },
796-
797-
f:row {
798-
f:static_text {
799-
title = "Title: ",
800-
font = "<system>",
801-
alignment = 'right',
802-
width_in_chars = 8,
803-
},
804-
f:edit_field {
805-
value = bind 'mdTitle',
806-
font = "<system>",
807-
alignment = 'left',
808-
width_in_chars = 60,
809-
height_in_lines = 3,
810-
},
811-
},
812-
f:row {
813-
f:static_text {
814-
title = "Description: ",
815-
font = "<system>",
816-
alignment = 'right',
817-
width_in_chars = 8,
818-
},
819-
f:edit_field {
820-
value = bind 'mdDescription',
821-
font = "<system>",
822-
alignment = 'left',
823-
width_in_chars = 60,
824-
height_in_lines = 3,
825-
},
826-
},
827-
},
790+
f:spacer { height = 2 },
791+
-- custom metadata fields (Title and description)
792+
UIHelpers.createMetaDataGroupBox(f, bind),
828793

829794
f:spacer { height = 2 },
795+
-- keyword hierarchy and synonyms, and keyword filtering
830796
UIHelpers.createKeywordSettingsGroupBox(f, bind),
831797

832798
f:spacer { height = 2 },
833-
f:group_box {
834-
title = "Other Settings",
835-
font = "<system/bold>",
836-
fill_horizontal = 1,
837-
f:spacer { height = 1 },
838-
f:row {
839-
fill_horizontal = 1,
840-
f:static_text {
841-
title = "",
842-
alignment = 'right',
843-
width_in_chars = 7,
844-
},
845-
f:checkbox {
846-
title = "Synchronise Album Descriptions",
847-
font = "<system>",
848-
tooltip = "If checked, Album descriptions will be maintainable in Lightroom and sent to Piwigo",
849-
value = bind 'syncAlbumDescriptions',
850-
},
851-
},
799+
-- album custom settings and album association (one image, multiple albums)
800+
UIHelpers.createAlbumSettingsGroupBox(f, bind, propertyTable),
852801

853-
f:spacer { height = 1 },
854-
f:row {
855-
fill_horizontal = 1,
856-
f:static_text {
857-
title = "",
858-
alignment = 'right',
859-
width_in_chars = 7,
860-
},
861-
f:checkbox {
862-
title = "Synchronise comments as part of a Publish Process",
863-
font = "<system>",
864-
tooltip = "When checked, comments will be synchronised for all photos in a collection during a publish operation",
865-
value = bind 'syncCommentsPublish',
866-
},
867-
},
868-
f:row {
869-
fill_horizontal = 1,
870-
f:static_text {
871-
title = "",
872-
alignment = 'right',
873-
width_in_chars = 7,
874-
},
875-
f:checkbox {
876-
title = "Only include Published Photos",
877-
enabled = bind('syncCommentsPublish', propertyTable),
878-
font = "<system>",
879-
tooltip = "When checked, only photos being published will have comments synchronised",
880-
value = bind 'syncCommentsPubOnly',
881-
},
882-
},
883-
884-
885-
},
802+
f:spacer { height = 2 },
803+
-- other settings (album descriptions and comments handling)
804+
UIHelpers.createOtherSettingsGroupBox(f, bind),
805+
886806
}
887807
end
888808
--

piwigoPublish.lrplugin/PublishServiceProvider.lua

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
require "PublishDialogSections"
2626
require "PublishTask"
27+
require "PublishTaskImageProcessing"
28+
2729

2830
return {
2931

@@ -51,16 +53,22 @@ return {
5153

5254
-- these fields are stored in the publish service settings by Lightroom
5355
exportPresetFields = {
54-
{ key = 'host', default = '' },
55-
{ key = "userName", default = '' },
56-
{ key = "userPW", default = '' },
57-
{ key = "KwFullHierarchy", default = true },
58-
{ key = "KwSynonyms", default = true },
59-
{ key = "mdTitle", default = "{{title}}" },
60-
{ key = "mdDescription", default = "{{caption}}" },
61-
{ key = "syncAlbumDescriptions", default = false },
62-
{ key = "syncCommentsPublish", default = true },
63-
{ key = "syncCommentsPubOnly", default = false },
56+
{ key = 'host', default = '' },
57+
{ key = "userName", default = '' },
58+
{ key = "userPW", default = '' },
59+
{ key = "KwFullHierarchy", default = true },
60+
{ key = "KwSynonyms", default = true },
61+
{ key = "mdTitle", default = "{{title}}" },
62+
{ key = "mdDescription", default = "{{caption}}" },
63+
{ key = "syncAlbumDescriptions", default = false },
64+
{ key = "syncCommentsPublish", default = true },
65+
{ key = "syncCommentsPubOnly", default = false },
66+
{ key = "PWP_albumAssociation", default = true },
67+
{ key = "PWP_customAlbumSettings", default = false },
68+
{ key = "KwFilterExclude", default = '' },
69+
{ key = "KwFilterInclude", default = '' },
70+
71+
6472
},
6573

6674
metadataThatTriggersRepublish = function(publishSettings, photoId, fieldName)
@@ -91,18 +99,19 @@ return {
9199
-- titleForPublishedSmartCollection_standalone = ""
92100

93101
-- Images Processing function
94-
processRenderedPhotos = PublishTask.processRenderedPhotos,
95-
canAddCommentsToService = PublishTask.canAddCommentsToService,
96-
addCommentToPublishedPhoto = PublishTask.addCommentToPublishedPhoto,
97-
getCommentsFromPublishedCollection = PublishTask.getCommentsFromPublishedCollection,
98-
deletePhotosFromPublishedCollection = PublishTask.deletePhotosFromPublishedCollection,
99-
shouldDeletePhotosFromServiceOnDeleteFromCatalog = PublishTask.shouldDeletePhotosFromServiceOnDeleteFromCatalog,
102+
processRenderedPhotos = PublishTaskImageProcessing.processRenderedPhotos,
103+
addCommentToPublishedPhoto = PublishTaskImageProcessing.addCommentToPublishedPhoto,
104+
getCommentsFromPublishedCollection = PublishTaskImageProcessing.getCommentsFromPublishedCollection,
105+
deletePhotosFromPublishedCollection = PublishTaskImageProcessing.deletePhotosFromPublishedCollection,
106+
100107

101108
-- PublishService processing functions
102109
didCreateNewPublishService = PublishTask.didCreateNewPublishService,
103110
didUpdatePublishService = PublishTask.didUpdatePublishService,
104111
shouldDeletePublishService = PublishTask.shouldDeletePublishService,
105112
willDeletePublishService = PublishTask.willDeletePublishService,
113+
canAddCommentsToService = PublishTask.canAddCommentsToService,
114+
shouldDeletePhotosFromServiceOnDeleteFromCatalog = PublishTask.shouldDeletePhotosFromServiceOnDeleteFromCatalog,
106115

107116
-- Published Collections / CollectionSets Processing functions
108117
getCollectionBehaviorInfo = PublishTask.getCollectionBehaviorInfo,

0 commit comments

Comments
 (0)