2020-10-12 23:12:46 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
2021-01-18 01:23:20 +00:00
|
|
|
"fmt"
|
2021-11-29 03:08:32 +00:00
|
|
|
"os"
|
2020-10-12 23:12:46 +00:00
|
|
|
"strconv"
|
|
|
|
|
2022-03-17 00:33:59 +00:00
|
|
|
"github.com/stashapp/stash/internal/manager"
|
2021-11-29 03:08:32 +00:00
|
|
|
"github.com/stashapp/stash/pkg/file"
|
2023-03-16 04:04:54 +00:00
|
|
|
"github.com/stashapp/stash/pkg/gallery"
|
2021-11-29 03:08:32 +00:00
|
|
|
"github.com/stashapp/stash/pkg/image"
|
2020-10-12 23:12:46 +00:00
|
|
|
"github.com/stashapp/stash/pkg/models"
|
2021-06-11 07:24:58 +00:00
|
|
|
"github.com/stashapp/stash/pkg/plugin"
|
2022-03-17 00:33:59 +00:00
|
|
|
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
2020-10-12 23:12:46 +00:00
|
|
|
"github.com/stashapp/stash/pkg/utils"
|
|
|
|
)
|
|
|
|
|
2023-09-11 02:24:15 +00:00
|
|
|
// used to refetch gallery after hooks run
|
2021-06-11 07:24:58 +00:00
|
|
|
func (r *mutationResolver) getGallery(ctx context.Context, id int) (ret *models.Gallery, err error) {
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
ret, err = r.repository.Gallery.Find(ctx, id)
|
2021-06-11 07:24:58 +00:00
|
|
|
return err
|
|
|
|
}); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *mutationResolver) GalleryCreate(ctx context.Context, input GalleryCreateInput) (*models.Gallery, error) {
|
2020-10-12 23:12:46 +00:00
|
|
|
// name must be provided
|
|
|
|
if input.Title == "" {
|
|
|
|
return nil, errors.New("title must not be empty")
|
|
|
|
}
|
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
translator := changesetTranslator{
|
|
|
|
inputMap: getUpdateInputMap(ctx),
|
|
|
|
}
|
|
|
|
|
2023-09-11 02:24:15 +00:00
|
|
|
// Populate a new gallery from the input
|
|
|
|
newGallery := models.NewGallery()
|
|
|
|
|
|
|
|
newGallery.Title = input.Title
|
|
|
|
newGallery.URL = translator.string(input.URL)
|
|
|
|
newGallery.Details = translator.string(input.Details)
|
|
|
|
newGallery.Rating = translator.ratingConversion(input.Rating, input.Rating100)
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
newGallery.Date, err = translator.datePtr(input.Date)
|
2022-08-12 02:21:46 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting date: %w", err)
|
2022-08-12 02:21:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
newGallery.StudioID, err = translator.intPtrFromString(input.StudioID)
|
2022-08-12 02:21:46 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting studio id: %w", err)
|
2022-08-12 02:21:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
|
|
|
|
newGallery.PerformerIDs, err = translator.relatedIds(input.PerformerIds)
|
2022-08-12 02:21:46 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting performer ids: %w", err)
|
2022-08-12 02:21:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
newGallery.TagIDs, err = translator.relatedIds(input.TagIds)
|
2023-07-13 02:15:02 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting tag ids: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
newGallery.SceneIDs, err = translator.relatedIds(input.SceneIds)
|
2023-06-15 02:46:09 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting scene ids: %w", err)
|
2022-07-13 06:30:54 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
// Start the transaction and save the gallery
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
qb := r.repository.Gallery
|
2022-07-13 06:30:54 +00:00
|
|
|
if err := qb.Create(ctx, &newGallery, nil); err != nil {
|
2021-02-01 20:56:54 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2020-10-12 23:12:46 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-07-13 06:30:54 +00:00
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, newGallery.ID, plugin.GalleryCreatePost, input, nil)
|
|
|
|
return r.getGallery(ctx, newGallery.ID)
|
2021-01-18 01:23:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) GalleryUpdate(ctx context.Context, input models.GalleryUpdateInput) (ret *models.Gallery, err error) {
|
|
|
|
translator := changesetTranslator{
|
|
|
|
inputMap: getUpdateInputMap(ctx),
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
// Start the transaction and save the gallery
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
ret, err = r.galleryUpdate(ctx, input, translator)
|
2021-01-18 01:23:20 +00:00
|
|
|
return err
|
|
|
|
}); err != nil {
|
2020-10-12 23:12:46 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-06-11 07:24:58 +00:00
|
|
|
// execute post hooks outside txn
|
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, ret.ID, plugin.GalleryUpdatePost, input, translator.getFields())
|
|
|
|
return r.getGallery(ctx, ret.ID)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
func (r *mutationResolver) GalleriesUpdate(ctx context.Context, input []*models.GalleryUpdateInput) (ret []*models.Gallery, err error) {
|
2020-12-04 01:42:56 +00:00
|
|
|
inputMaps := getUpdateInputMaps(ctx)
|
2020-10-12 23:12:46 +00:00
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
// Start the transaction and save the galleries
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
2021-01-18 01:23:20 +00:00
|
|
|
for i, gallery := range input {
|
|
|
|
translator := changesetTranslator{
|
|
|
|
inputMap: inputMaps[i],
|
|
|
|
}
|
2020-12-04 01:42:56 +00:00
|
|
|
|
2022-05-19 07:49:32 +00:00
|
|
|
thisGallery, err := r.galleryUpdate(ctx, *gallery, translator)
|
2021-01-18 01:23:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
ret = append(ret, thisGallery)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2020-10-12 23:12:46 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-06-11 07:24:58 +00:00
|
|
|
// execute post hooks outside txn
|
|
|
|
var newRet []*models.Gallery
|
|
|
|
for i, gallery := range ret {
|
|
|
|
translator := changesetTranslator{
|
|
|
|
inputMap: inputMaps[i],
|
|
|
|
}
|
|
|
|
|
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, gallery.ID, plugin.GalleryUpdatePost, input, translator.getFields())
|
2023-09-11 02:24:15 +00:00
|
|
|
|
2021-06-11 07:24:58 +00:00
|
|
|
gallery, err = r.getGallery(ctx, gallery.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
newRet = append(newRet, gallery)
|
|
|
|
}
|
|
|
|
|
|
|
|
return newRet, nil
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-05-19 07:49:32 +00:00
|
|
|
func (r *mutationResolver) galleryUpdate(ctx context.Context, input models.GalleryUpdateInput, translator changesetTranslator) (*models.Gallery, error) {
|
2021-01-18 01:23:20 +00:00
|
|
|
galleryID, err := strconv.Atoi(input.ID)
|
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting id: %w", err)
|
2021-01-18 01:23:20 +00:00
|
|
|
}
|
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
qb := r.repository.Gallery
|
|
|
|
|
2022-05-19 07:49:32 +00:00
|
|
|
originalGallery, err := qb.Find(ctx, galleryID)
|
2020-10-12 23:12:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if originalGallery == nil {
|
2023-06-15 02:46:09 +00:00
|
|
|
return nil, fmt.Errorf("gallery with id %d not found", galleryID)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
// Populate gallery from the input
|
2022-07-13 06:30:54 +00:00
|
|
|
updatedGallery := models.NewGalleryPartial()
|
2020-12-04 01:42:56 +00:00
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
if input.Title != nil {
|
|
|
|
// ensure title is not empty
|
2022-11-10 03:19:13 +00:00
|
|
|
if *input.Title == "" && originalGallery.IsUserCreated() {
|
|
|
|
return nil, errors.New("title must not be empty for user-created galleries")
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-07-13 06:30:54 +00:00
|
|
|
updatedGallery.Title = models.NewOptionalString(*input.Title)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-07-13 06:30:54 +00:00
|
|
|
updatedGallery.Details = translator.optionalString(input.Details, "details")
|
|
|
|
updatedGallery.URL = translator.optionalString(input.URL, "url")
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
|
|
|
|
updatedGallery.Organized = translator.optionalBool(input.Organized, "organized")
|
|
|
|
|
2023-07-13 02:15:02 +00:00
|
|
|
updatedGallery.Date, err = translator.optionalDate(input.Date, "date")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting date: %w", err)
|
|
|
|
}
|
2022-07-13 06:30:54 +00:00
|
|
|
updatedGallery.StudioID, err = translator.optionalIntFromString(input.StudioID, "studio_id")
|
2020-10-12 23:12:46 +00:00
|
|
|
if err != nil {
|
2022-07-13 06:30:54 +00:00
|
|
|
return nil, fmt.Errorf("converting studio id: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.PrimaryFileID, err = translator.fileIDPtrFromString(input.PrimaryFileID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting primary file id: %w", err)
|
|
|
|
}
|
|
|
|
if updatedGallery.PrimaryFileID != nil {
|
|
|
|
primaryFileID := *updatedGallery.PrimaryFileID
|
2022-10-06 03:50:06 +00:00
|
|
|
|
|
|
|
if err := originalGallery.LoadFiles(ctx, r.repository.Gallery); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
// ensure that new primary file is associated with gallery
|
2023-09-01 00:39:29 +00:00
|
|
|
var f models.File
|
2022-10-06 03:50:06 +00:00
|
|
|
for _, ff := range originalGallery.Files.List() {
|
2023-09-11 02:24:15 +00:00
|
|
|
if ff.Base().ID == primaryFileID {
|
2022-10-06 03:50:06 +00:00
|
|
|
f = ff
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if f == nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("file with id %d not associated with gallery", primaryFileID)
|
2022-10-06 03:50:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.PerformerIDs, err = translator.updateIds(input.PerformerIds, "performer_ids")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting performer ids: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.TagIDs, err = translator.updateIds(input.TagIds, "tag_ids")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting tag ids: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.SceneIDs, err = translator.updateIds(input.SceneIds, "scene_ids")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting scene ids: %w", err)
|
2021-02-01 20:56:54 +00:00
|
|
|
}
|
|
|
|
|
2022-07-13 06:30:54 +00:00
|
|
|
// gallery scene is set from the scene only
|
|
|
|
|
|
|
|
gallery, err := qb.UpdatePartial(ctx, galleryID, updatedGallery)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
return gallery, nil
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *mutationResolver) BulkGalleryUpdate(ctx context.Context, input BulkGalleryUpdateInput) ([]*models.Gallery, error) {
|
2023-06-15 02:46:09 +00:00
|
|
|
galleryIDs, err := stringslice.StringSliceToIntSlice(input.Ids)
|
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting ids: %w", err)
|
2023-06-15 02:46:09 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 01:42:56 +00:00
|
|
|
translator := changesetTranslator{
|
|
|
|
inputMap: getUpdateInputMap(ctx),
|
|
|
|
}
|
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
// Populate gallery from the input
|
2022-07-13 06:30:54 +00:00
|
|
|
updatedGallery := models.NewGalleryPartial()
|
|
|
|
|
|
|
|
updatedGallery.Details = translator.optionalString(input.Details, "details")
|
|
|
|
updatedGallery.URL = translator.optionalString(input.URL, "url")
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
|
|
|
|
updatedGallery.Organized = translator.optionalBool(input.Organized, "organized")
|
|
|
|
|
2023-07-13 02:15:02 +00:00
|
|
|
updatedGallery.Date, err = translator.optionalDate(input.Date, "date")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting date: %w", err)
|
|
|
|
}
|
2022-07-13 06:30:54 +00:00
|
|
|
updatedGallery.StudioID, err = translator.optionalIntFromString(input.StudioID, "studio_id")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting studio id: %w", err)
|
|
|
|
}
|
|
|
|
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.PerformerIDs, err = translator.updateIdsBulk(input.PerformerIds, "performer_ids")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting performer ids: %w", err)
|
2022-07-13 06:30:54 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.TagIDs, err = translator.updateIdsBulk(input.TagIds, "tag_ids")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting tag ids: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
2023-09-11 02:24:15 +00:00
|
|
|
updatedGallery.SceneIDs, err = translator.updateIdsBulk(input.SceneIds, "scene_ids")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("converting scene ids: %w", err)
|
2022-07-13 06:30:54 +00:00
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
|
|
|
|
ret := []*models.Gallery{}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
// Start the transaction and save the galleries
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
qb := r.repository.Gallery
|
2020-10-12 23:12:46 +00:00
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
for _, galleryID := range galleryIDs {
|
2022-07-13 06:30:54 +00:00
|
|
|
gallery, err := qb.UpdatePartial(ctx, galleryID, updatedGallery)
|
2020-10-12 23:12:46 +00:00
|
|
|
if err != nil {
|
2021-01-18 01:23:20 +00:00
|
|
|
return err
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
ret = append(ret, gallery)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2020-10-12 23:12:46 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-06-11 07:24:58 +00:00
|
|
|
// execute post hooks outside of txn
|
|
|
|
var newRet []*models.Gallery
|
|
|
|
for _, gallery := range ret {
|
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, gallery.ID, plugin.GalleryUpdatePost, input, translator.getFields())
|
|
|
|
|
|
|
|
gallery, err := r.getGallery(ctx, gallery.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
newRet = append(newRet, gallery)
|
|
|
|
}
|
|
|
|
|
|
|
|
return newRet, nil
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) GalleryDestroy(ctx context.Context, input models.GalleryDestroyInput) (bool, error) {
|
2022-03-17 00:33:59 +00:00
|
|
|
galleryIDs, err := stringslice.StringSliceToIntSlice(input.Ids)
|
2021-01-18 01:23:20 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return false, fmt.Errorf("converting ids: %w", err)
|
2021-01-18 01:23:20 +00:00
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
|
|
|
|
var galleries []*models.Gallery
|
2021-11-29 03:08:32 +00:00
|
|
|
var imgsDestroyed []*models.Image
|
|
|
|
fileDeleter := &image.FileDeleter{
|
2022-07-13 06:30:54 +00:00
|
|
|
Deleter: file.NewDeleter(),
|
2021-11-29 03:08:32 +00:00
|
|
|
Paths: manager.GetInstance().Paths,
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteGenerated := utils.IsTrue(input.DeleteGenerated)
|
|
|
|
deleteFile := utils.IsTrue(input.DeleteFile)
|
2020-10-15 23:35:50 +00:00
|
|
|
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
qb := r.repository.Gallery
|
2020-10-12 23:12:46 +00:00
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
for _, id := range galleryIDs {
|
2022-05-19 07:49:32 +00:00
|
|
|
gallery, err := qb.Find(ctx, id)
|
2020-10-12 23:12:46 +00:00
|
|
|
if err != nil {
|
2021-01-18 01:23:20 +00:00
|
|
|
return err
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
if gallery == nil {
|
|
|
|
return fmt.Errorf("gallery with id %d not found", id)
|
|
|
|
}
|
|
|
|
|
2022-09-05 01:46:18 +00:00
|
|
|
if err := gallery.LoadFiles(ctx, qb); err != nil {
|
|
|
|
return fmt.Errorf("loading files for gallery %d", id)
|
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
galleries = append(galleries, gallery)
|
|
|
|
|
2022-07-13 06:30:54 +00:00
|
|
|
imgsDestroyed, err = r.galleryService.Destroy(ctx, gallery, fileDeleter, deleteGenerated, deleteFile)
|
|
|
|
if err != nil {
|
2021-01-18 01:23:20 +00:00
|
|
|
return err
|
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 01:23:20 +00:00
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-11-29 03:08:32 +00:00
|
|
|
fileDeleter.Rollback()
|
2020-10-12 23:12:46 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
2021-11-29 03:08:32 +00:00
|
|
|
// perform the post-commit actions
|
|
|
|
fileDeleter.Commit()
|
2021-10-24 22:29:03 +00:00
|
|
|
|
2021-11-29 03:08:32 +00:00
|
|
|
for _, gallery := range galleries {
|
|
|
|
// don't delete stash library paths
|
2022-09-01 07:54:34 +00:00
|
|
|
path := gallery.Path
|
2022-07-13 06:30:54 +00:00
|
|
|
if deleteFile && path != "" && !isStashPath(path) {
|
2021-11-29 03:08:32 +00:00
|
|
|
// try to remove the folder - it is possible that it is not empty
|
|
|
|
// so swallow the error if present
|
2022-07-13 06:30:54 +00:00
|
|
|
_ = os.Remove(path)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-11 07:24:58 +00:00
|
|
|
// call post hook after performing the other actions
|
|
|
|
for _, gallery := range galleries {
|
2021-12-13 03:38:00 +00:00
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, gallery.ID, plugin.GalleryDestroyPost, plugin.GalleryDestroyInput{
|
|
|
|
GalleryDestroyInput: input,
|
2022-09-19 06:50:04 +00:00
|
|
|
Checksum: gallery.PrimaryChecksum(),
|
2022-09-01 07:54:34 +00:00
|
|
|
Path: gallery.Path,
|
2021-12-13 03:38:00 +00:00
|
|
|
}, nil)
|
2021-06-11 07:24:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// call image destroy post hook as well
|
2021-11-29 03:08:32 +00:00
|
|
|
for _, img := range imgsDestroyed {
|
2021-12-13 03:38:00 +00:00
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, img.ID, plugin.ImageDestroyPost, plugin.ImageDestroyInput{
|
2022-09-01 07:54:34 +00:00
|
|
|
Checksum: img.Checksum,
|
|
|
|
Path: img.Path,
|
2021-12-13 03:38:00 +00:00
|
|
|
}, nil)
|
2021-06-11 07:24:58 +00:00
|
|
|
}
|
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2021-11-29 03:08:32 +00:00
|
|
|
func isStashPath(path string) bool {
|
|
|
|
stashConfigs := manager.GetInstance().Config.GetStashPaths()
|
|
|
|
for _, config := range stashConfigs {
|
|
|
|
if path == config.Path {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *mutationResolver) AddGalleryImages(ctx context.Context, input GalleryAddInput) (bool, error) {
|
2021-01-18 01:23:20 +00:00
|
|
|
galleryID, err := strconv.Atoi(input.GalleryID)
|
2020-10-12 23:12:46 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return false, fmt.Errorf("converting gallery id: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-03-17 00:33:59 +00:00
|
|
|
imageIDs, err := stringslice.StringSliceToIntSlice(input.ImageIds)
|
2021-01-18 01:23:20 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return false, fmt.Errorf("converting image ids: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
qb := r.repository.Gallery
|
|
|
|
gallery, err := qb.Find(ctx, galleryID)
|
2021-01-18 01:23:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if gallery == nil {
|
2023-06-15 02:46:09 +00:00
|
|
|
return fmt.Errorf("gallery with id %d not found", galleryID)
|
2021-01-18 01:23:20 +00:00
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
|
2022-09-29 23:18:58 +00:00
|
|
|
return r.galleryService.AddImages(ctx, gallery, imageIDs...)
|
2021-01-18 01:23:20 +00:00
|
|
|
}); err != nil {
|
2020-10-12 23:12:46 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *mutationResolver) RemoveGalleryImages(ctx context.Context, input GalleryRemoveInput) (bool, error) {
|
2021-01-18 01:23:20 +00:00
|
|
|
galleryID, err := strconv.Atoi(input.GalleryID)
|
2020-10-12 23:12:46 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return false, fmt.Errorf("converting gallery id: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-03-17 00:33:59 +00:00
|
|
|
imageIDs, err := stringslice.StringSliceToIntSlice(input.ImageIds)
|
2021-01-18 01:23:20 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return false, fmt.Errorf("converting image ids: %w", err)
|
2020-10-12 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2022-05-19 07:49:32 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
qb := r.repository.Gallery
|
|
|
|
gallery, err := qb.Find(ctx, galleryID)
|
2021-01-18 01:23:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if gallery == nil {
|
2023-06-15 02:46:09 +00:00
|
|
|
return fmt.Errorf("gallery with id %d not found", galleryID)
|
2021-01-18 01:23:20 +00:00
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
|
2022-09-29 23:18:58 +00:00
|
|
|
return r.galleryService.RemoveImages(ctx, gallery, imageIDs...)
|
2021-01-18 01:23:20 +00:00
|
|
|
}); err != nil {
|
2020-10-12 23:12:46 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
2023-03-16 04:04:54 +00:00
|
|
|
|
|
|
|
func (r *mutationResolver) getGalleryChapter(ctx context.Context, id int) (ret *models.GalleryChapter, err error) {
|
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
ret, err = r.repository.GalleryChapter.Find(ctx, id)
|
|
|
|
return err
|
|
|
|
}); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) GalleryChapterCreate(ctx context.Context, input GalleryChapterCreateInput) (*models.GalleryChapter, error) {
|
|
|
|
galleryID, err := strconv.Atoi(input.GalleryID)
|
|
|
|
if err != nil {
|
2023-07-26 23:44:06 +00:00
|
|
|
return nil, fmt.Errorf("converting gallery id: %w", err)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
2023-09-11 02:24:15 +00:00
|
|
|
// Populate a new gallery chapter from the input
|
|
|
|
newChapter := models.NewGalleryChapter()
|
|
|
|
|
|
|
|
newChapter.Title = input.Title
|
|
|
|
newChapter.ImageIndex = input.ImageIndex
|
|
|
|
newChapter.GalleryID = galleryID
|
2023-03-16 04:04:54 +00:00
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
// Start the transaction and save the gallery chapter
|
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
imageCount, err := r.repository.Image.CountByGalleryID(ctx, galleryID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-03-16 04:04:54 +00:00
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
// Sanity Check of Index
|
|
|
|
if newChapter.ImageIndex > imageCount || newChapter.ImageIndex < 1 {
|
|
|
|
return errors.New("Image # must greater than zero and in range of the gallery images")
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.repository.GalleryChapter.Create(ctx, &newChapter)
|
|
|
|
}); err != nil {
|
2023-03-16 04:04:54 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, newChapter.ID, plugin.GalleryChapterCreatePost, input, nil)
|
|
|
|
return r.getGalleryChapter(ctx, newChapter.ID)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) GalleryChapterUpdate(ctx context.Context, input GalleryChapterUpdateInput) (*models.GalleryChapter, error) {
|
2023-07-26 23:44:06 +00:00
|
|
|
chapterID, err := strconv.Atoi(input.ID)
|
2023-03-16 04:04:54 +00:00
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return nil, fmt.Errorf("converting id: %w", err)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
2023-06-15 02:46:09 +00:00
|
|
|
translator := changesetTranslator{
|
|
|
|
inputMap: getUpdateInputMap(ctx),
|
|
|
|
}
|
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
// Populate gallery chapter from the input
|
|
|
|
updatedChapter := models.NewGalleryChapterPartial()
|
|
|
|
|
|
|
|
updatedChapter.Title = translator.optionalString(input.Title, "title")
|
|
|
|
updatedChapter.ImageIndex = translator.optionalInt(input.ImageIndex, "image_index")
|
|
|
|
updatedChapter.GalleryID, err = translator.optionalIntFromString(input.GalleryID, "gallery_id")
|
2023-03-16 04:04:54 +00:00
|
|
|
if err != nil {
|
2023-07-26 23:44:06 +00:00
|
|
|
return nil, fmt.Errorf("converting gallery id: %w", err)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
// Start the transaction and save the gallery chapter
|
2023-03-16 04:04:54 +00:00
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
2023-07-26 23:44:06 +00:00
|
|
|
qb := r.repository.GalleryChapter
|
2023-03-16 04:04:54 +00:00
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
existingChapter, err := qb.Find(ctx, chapterID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if existingChapter == nil {
|
|
|
|
return fmt.Errorf("gallery chapter with id %d not found", chapterID)
|
|
|
|
}
|
2023-03-16 04:04:54 +00:00
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
galleryID := existingChapter.GalleryID
|
|
|
|
imageIndex := existingChapter.ImageIndex
|
|
|
|
|
|
|
|
if updatedChapter.GalleryID.Set {
|
|
|
|
galleryID = updatedChapter.GalleryID.Value
|
|
|
|
}
|
|
|
|
if updatedChapter.ImageIndex.Set {
|
|
|
|
imageIndex = updatedChapter.ImageIndex.Value
|
|
|
|
}
|
|
|
|
|
|
|
|
imageCount, err := r.repository.Image.CountByGalleryID(ctx, galleryID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sanity Check of Index
|
|
|
|
if imageIndex > imageCount || imageIndex < 1 {
|
|
|
|
return errors.New("Image # must greater than zero and in range of the gallery images")
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = qb.UpdatePartial(ctx, chapterID, updatedChapter)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2023-03-16 04:04:54 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-07-26 23:44:06 +00:00
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, chapterID, plugin.GalleryChapterUpdatePost, input, translator.getFields())
|
|
|
|
return r.getGalleryChapter(ctx, chapterID)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) GalleryChapterDestroy(ctx context.Context, id string) (bool, error) {
|
|
|
|
chapterID, err := strconv.Atoi(id)
|
|
|
|
if err != nil {
|
2023-09-11 02:24:15 +00:00
|
|
|
return false, fmt.Errorf("converting id: %w", err)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
|
|
|
qb := r.repository.GalleryChapter
|
|
|
|
|
|
|
|
chapter, err := qb.Find(ctx, chapterID)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if chapter == nil {
|
2023-06-15 02:46:09 +00:00
|
|
|
return fmt.Errorf("gallery chapter with id %d not found", chapterID)
|
2023-03-16 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return gallery.DestroyChapter(ctx, chapter, qb)
|
|
|
|
}); err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r.hookExecutor.ExecutePostHooks(ctx, chapterID, plugin.GalleryChapterDestroyPost, id, nil)
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|