mirror of https://github.com/stashapp/stash.git
376 lines
8.8 KiB
Go
376 lines
8.8 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/stashapp/stash/pkg/manager"
|
|
"github.com/stashapp/stash/pkg/models"
|
|
"github.com/stashapp/stash/pkg/utils"
|
|
)
|
|
|
|
func (r *mutationResolver) ImageUpdate(ctx context.Context, input models.ImageUpdateInput) (ret *models.Image, err error) {
|
|
translator := changesetTranslator{
|
|
inputMap: getUpdateInputMap(ctx),
|
|
}
|
|
|
|
// Start the transaction and save the image
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
ret, err = r.imageUpdate(input, translator, repo)
|
|
return err
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *mutationResolver) ImagesUpdate(ctx context.Context, input []*models.ImageUpdateInput) (ret []*models.Image, err error) {
|
|
inputMaps := getUpdateInputMaps(ctx)
|
|
|
|
// Start the transaction and save the image
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
for i, image := range input {
|
|
translator := changesetTranslator{
|
|
inputMap: inputMaps[i],
|
|
}
|
|
|
|
thisImage, err := r.imageUpdate(*image, translator, repo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ret = append(ret, thisImage)
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *mutationResolver) imageUpdate(input models.ImageUpdateInput, translator changesetTranslator, repo models.Repository) (*models.Image, error) {
|
|
// Populate image from the input
|
|
imageID, err := strconv.Atoi(input.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
updatedTime := time.Now()
|
|
updatedImage := models.ImagePartial{
|
|
ID: imageID,
|
|
UpdatedAt: &models.SQLiteTimestamp{Timestamp: updatedTime},
|
|
}
|
|
|
|
updatedImage.Title = translator.nullString(input.Title, "title")
|
|
updatedImage.Rating = translator.nullInt64(input.Rating, "rating")
|
|
updatedImage.StudioID = translator.nullInt64FromString(input.StudioID, "studio_id")
|
|
updatedImage.Organized = input.Organized
|
|
|
|
qb := repo.Image()
|
|
image, err := qb.Update(updatedImage)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if translator.hasField("gallery_ids") {
|
|
if err := r.updateImageGalleries(qb, imageID, input.GalleryIds); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// Save the performers
|
|
if translator.hasField("performer_ids") {
|
|
if err := r.updateImagePerformers(qb, imageID, input.PerformerIds); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// Save the tags
|
|
if translator.hasField("tag_ids") {
|
|
if err := r.updateImageTags(qb, imageID, input.TagIds); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return image, nil
|
|
}
|
|
|
|
func (r *mutationResolver) updateImageGalleries(qb models.ImageReaderWriter, imageID int, galleryIDs []string) error {
|
|
ids, err := utils.StringSliceToIntSlice(galleryIDs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return qb.UpdateGalleries(imageID, ids)
|
|
}
|
|
|
|
func (r *mutationResolver) updateImagePerformers(qb models.ImageReaderWriter, imageID int, performerIDs []string) error {
|
|
ids, err := utils.StringSliceToIntSlice(performerIDs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return qb.UpdatePerformers(imageID, ids)
|
|
}
|
|
|
|
func (r *mutationResolver) updateImageTags(qb models.ImageReaderWriter, imageID int, tagsIDs []string) error {
|
|
ids, err := utils.StringSliceToIntSlice(tagsIDs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return qb.UpdateTags(imageID, ids)
|
|
}
|
|
|
|
func (r *mutationResolver) BulkImageUpdate(ctx context.Context, input models.BulkImageUpdateInput) (ret []*models.Image, err error) {
|
|
imageIDs, err := utils.StringSliceToIntSlice(input.Ids)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Populate image from the input
|
|
updatedTime := time.Now()
|
|
|
|
updatedImage := models.ImagePartial{
|
|
UpdatedAt: &models.SQLiteTimestamp{Timestamp: updatedTime},
|
|
}
|
|
|
|
translator := changesetTranslator{
|
|
inputMap: getUpdateInputMap(ctx),
|
|
}
|
|
|
|
updatedImage.Title = translator.nullString(input.Title, "title")
|
|
updatedImage.Rating = translator.nullInt64(input.Rating, "rating")
|
|
updatedImage.StudioID = translator.nullInt64FromString(input.StudioID, "studio_id")
|
|
updatedImage.Organized = input.Organized
|
|
|
|
// Start the transaction and save the image marker
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
qb := repo.Image()
|
|
|
|
for _, imageID := range imageIDs {
|
|
updatedImage.ID = imageID
|
|
|
|
image, err := qb.Update(updatedImage)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ret = append(ret, image)
|
|
|
|
// Save the galleries
|
|
if translator.hasField("gallery_ids") {
|
|
galleryIDs, err := adjustImageGalleryIDs(qb, imageID, *input.GalleryIds)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := qb.UpdateGalleries(imageID, galleryIDs); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Save the performers
|
|
if translator.hasField("performer_ids") {
|
|
performerIDs, err := adjustImagePerformerIDs(qb, imageID, *input.PerformerIds)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := qb.UpdatePerformers(imageID, performerIDs); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Save the tags
|
|
if translator.hasField("tag_ids") {
|
|
tagIDs, err := adjustImageTagIDs(qb, imageID, *input.TagIds)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := qb.UpdateTags(imageID, tagIDs); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func adjustImageGalleryIDs(qb models.ImageReader, imageID int, ids models.BulkUpdateIds) (ret []int, err error) {
|
|
ret, err = qb.GetGalleryIDs(imageID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return adjustIDs(ret, ids), nil
|
|
}
|
|
|
|
func adjustImagePerformerIDs(qb models.ImageReader, imageID int, ids models.BulkUpdateIds) (ret []int, err error) {
|
|
ret, err = qb.GetPerformerIDs(imageID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return adjustIDs(ret, ids), nil
|
|
}
|
|
|
|
func adjustImageTagIDs(qb models.ImageReader, imageID int, ids models.BulkUpdateIds) (ret []int, err error) {
|
|
ret, err = qb.GetTagIDs(imageID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return adjustIDs(ret, ids), nil
|
|
}
|
|
|
|
func (r *mutationResolver) ImageDestroy(ctx context.Context, input models.ImageDestroyInput) (ret bool, err error) {
|
|
imageID, err := strconv.Atoi(input.ID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
var image *models.Image
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
qb := repo.Image()
|
|
|
|
image, err = qb.Find(imageID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if image == nil {
|
|
return fmt.Errorf("image with id %d not found", imageID)
|
|
}
|
|
|
|
return qb.Destroy(imageID)
|
|
}); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// if delete generated is true, then delete the generated files
|
|
// for the image
|
|
if input.DeleteGenerated != nil && *input.DeleteGenerated {
|
|
manager.DeleteGeneratedImageFiles(image)
|
|
}
|
|
|
|
// if delete file is true, then delete the file as well
|
|
// if it fails, just log a message
|
|
if input.DeleteFile != nil && *input.DeleteFile {
|
|
manager.DeleteImageFile(image)
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (r *mutationResolver) ImagesDestroy(ctx context.Context, input models.ImagesDestroyInput) (ret bool, err error) {
|
|
imageIDs, err := utils.StringSliceToIntSlice(input.Ids)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
var images []*models.Image
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
qb := repo.Image()
|
|
|
|
for _, imageID := range imageIDs {
|
|
|
|
image, err := qb.Find(imageID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if image == nil {
|
|
return fmt.Errorf("image with id %d not found", imageID)
|
|
}
|
|
|
|
images = append(images, image)
|
|
if err := qb.Destroy(imageID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
for _, image := range images {
|
|
// if delete generated is true, then delete the generated files
|
|
// for the image
|
|
if input.DeleteGenerated != nil && *input.DeleteGenerated {
|
|
manager.DeleteGeneratedImageFiles(image)
|
|
}
|
|
|
|
// if delete file is true, then delete the file as well
|
|
// if it fails, just log a message
|
|
if input.DeleteFile != nil && *input.DeleteFile {
|
|
manager.DeleteImageFile(image)
|
|
}
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (r *mutationResolver) ImageIncrementO(ctx context.Context, id string) (ret int, err error) {
|
|
imageID, err := strconv.Atoi(id)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
qb := repo.Image()
|
|
|
|
ret, err = qb.IncrementOCounter(imageID)
|
|
return err
|
|
}); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *mutationResolver) ImageDecrementO(ctx context.Context, id string) (ret int, err error) {
|
|
imageID, err := strconv.Atoi(id)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
qb := repo.Image()
|
|
|
|
ret, err = qb.DecrementOCounter(imageID)
|
|
return err
|
|
}); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *mutationResolver) ImageResetO(ctx context.Context, id string) (ret int, err error) {
|
|
imageID, err := strconv.Atoi(id)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if err := r.withTxn(ctx, func(repo models.Repository) error {
|
|
qb := repo.Image()
|
|
|
|
ret, err = qb.ResetOCounter(imageID)
|
|
return err
|
|
}); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|