mirror of
https://github.com/stashapp/stash.git
synced 2025-12-08 09:23:38 +01:00
* Add a space after // comments
For consistency, the commentFormatting lint checker suggests a space
after each // comment block. This commit handles all the spots in
the code where that is needed.
* Rewrite documentation on functions
Use the Go idiom of commenting:
* First sentence declares the purpose.
* First word is the name being declared
The reason this style is preferred is such that grep is able to find
names the user might be interested in. Consider e.g.,
go doc -all pkg/ffmpeg | grep -i transcode
in which case a match will tell you the name of the function you are
interested in.
* Remove old code comment-blocks
There are some commented out old code blocks in the code base. These are
either 3 years old, or 2 years old. By now, I don't think their use is
going to come back any time soon, and Git will track old pieces of
deleted code anyway.
Opt for deletion.
* Reorder imports
Split stdlib imports from non-stdlib imports in files we are touching.
* Use a range over an iteration variable
Probably more go-idiomatic, and the code needed comment-fixing anyway.
* Use time.After rather than rolling our own
The idiom here is common enough that the stdlib contains a function for
it. Use the stdlib function over our own variant.
* Enable the commentFormatting linter
231 lines
6.2 KiB
Go
231 lines
6.2 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sort"
|
|
"strconv"
|
|
|
|
"github.com/stashapp/stash/pkg/logger"
|
|
"github.com/stashapp/stash/pkg/models"
|
|
"github.com/stashapp/stash/pkg/plugin"
|
|
)
|
|
|
|
var (
|
|
ErrNotImplemented = errors.New("not implemented")
|
|
ErrNotSupported = errors.New("not supported")
|
|
)
|
|
|
|
type hookExecutor interface {
|
|
ExecutePostHooks(ctx context.Context, id int, hookType plugin.HookTriggerEnum, input interface{}, inputFields []string)
|
|
}
|
|
|
|
type Resolver struct {
|
|
txnManager models.TransactionManager
|
|
hookExecutor hookExecutor
|
|
}
|
|
|
|
func (r *Resolver) Gallery() models.GalleryResolver {
|
|
return &galleryResolver{r}
|
|
}
|
|
func (r *Resolver) Mutation() models.MutationResolver {
|
|
return &mutationResolver{r}
|
|
}
|
|
func (r *Resolver) Performer() models.PerformerResolver {
|
|
return &performerResolver{r}
|
|
}
|
|
func (r *Resolver) Query() models.QueryResolver {
|
|
return &queryResolver{r}
|
|
}
|
|
func (r *Resolver) Scene() models.SceneResolver {
|
|
return &sceneResolver{r}
|
|
}
|
|
func (r *Resolver) Image() models.ImageResolver {
|
|
return &imageResolver{r}
|
|
}
|
|
func (r *Resolver) SceneMarker() models.SceneMarkerResolver {
|
|
return &sceneMarkerResolver{r}
|
|
}
|
|
func (r *Resolver) Studio() models.StudioResolver {
|
|
return &studioResolver{r}
|
|
}
|
|
func (r *Resolver) Movie() models.MovieResolver {
|
|
return &movieResolver{r}
|
|
}
|
|
func (r *Resolver) Subscription() models.SubscriptionResolver {
|
|
return &subscriptionResolver{r}
|
|
}
|
|
func (r *Resolver) Tag() models.TagResolver {
|
|
return &tagResolver{r}
|
|
}
|
|
|
|
type mutationResolver struct{ *Resolver }
|
|
type queryResolver struct{ *Resolver }
|
|
type subscriptionResolver struct{ *Resolver }
|
|
|
|
type galleryResolver struct{ *Resolver }
|
|
type performerResolver struct{ *Resolver }
|
|
type sceneResolver struct{ *Resolver }
|
|
type sceneMarkerResolver struct{ *Resolver }
|
|
type imageResolver struct{ *Resolver }
|
|
type studioResolver struct{ *Resolver }
|
|
type movieResolver struct{ *Resolver }
|
|
type tagResolver struct{ *Resolver }
|
|
|
|
func (r *Resolver) withTxn(ctx context.Context, fn func(r models.Repository) error) error {
|
|
return r.txnManager.WithTxn(ctx, fn)
|
|
}
|
|
|
|
func (r *Resolver) withReadTxn(ctx context.Context, fn func(r models.ReaderRepository) error) error {
|
|
return r.txnManager.WithReadTxn(ctx, fn)
|
|
}
|
|
|
|
func (r *queryResolver) MarkerWall(ctx context.Context, q *string) (ret []*models.SceneMarker, err error) {
|
|
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
|
|
ret, err = repo.SceneMarker().Wall(q)
|
|
return err
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *queryResolver) SceneWall(ctx context.Context, q *string) (ret []*models.Scene, err error) {
|
|
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
|
|
ret, err = repo.Scene().Wall(q)
|
|
return err
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *queryResolver) MarkerStrings(ctx context.Context, q *string, sort *string) (ret []*models.MarkerStringsResultType, err error) {
|
|
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
|
|
ret, err = repo.SceneMarker().GetMarkerStrings(q, sort)
|
|
return err
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *queryResolver) Stats(ctx context.Context) (*models.StatsResultType, error) {
|
|
var ret models.StatsResultType
|
|
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
|
|
scenesQB := repo.Scene()
|
|
imageQB := repo.Image()
|
|
galleryQB := repo.Gallery()
|
|
studiosQB := repo.Studio()
|
|
performersQB := repo.Performer()
|
|
moviesQB := repo.Movie()
|
|
tagsQB := repo.Tag()
|
|
scenesCount, _ := scenesQB.Count()
|
|
scenesSize, _ := scenesQB.Size()
|
|
scenesDuration, _ := scenesQB.Duration()
|
|
imageCount, _ := imageQB.Count()
|
|
imageSize, _ := imageQB.Size()
|
|
galleryCount, _ := galleryQB.Count()
|
|
performersCount, _ := performersQB.Count()
|
|
studiosCount, _ := studiosQB.Count()
|
|
moviesCount, _ := moviesQB.Count()
|
|
tagsCount, _ := tagsQB.Count()
|
|
|
|
ret = models.StatsResultType{
|
|
SceneCount: scenesCount,
|
|
ScenesSize: scenesSize,
|
|
ScenesDuration: scenesDuration,
|
|
ImageCount: imageCount,
|
|
ImagesSize: imageSize,
|
|
GalleryCount: galleryCount,
|
|
PerformerCount: performersCount,
|
|
StudioCount: studiosCount,
|
|
MovieCount: moviesCount,
|
|
TagCount: tagsCount,
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ret, nil
|
|
}
|
|
|
|
func (r *queryResolver) Version(ctx context.Context) (*models.Version, error) {
|
|
version, hash, buildtime := GetVersion()
|
|
|
|
return &models.Version{
|
|
Version: &version,
|
|
Hash: hash,
|
|
BuildTime: buildtime,
|
|
}, nil
|
|
}
|
|
|
|
// Latestversion returns the latest git shorthash commit.
|
|
func (r *queryResolver) Latestversion(ctx context.Context) (*models.ShortVersion, error) {
|
|
ver, url, err := GetLatestVersion(ctx, true)
|
|
if err == nil {
|
|
logger.Infof("Retrieved latest hash: %s", ver)
|
|
} else {
|
|
logger.Errorf("Error while retrieving latest hash: %s", err)
|
|
}
|
|
|
|
return &models.ShortVersion{
|
|
Shorthash: ver,
|
|
URL: url,
|
|
}, err
|
|
}
|
|
|
|
// Get scene marker tags which show up under the video.
|
|
func (r *queryResolver) SceneMarkerTags(ctx context.Context, scene_id string) ([]*models.SceneMarkerTag, error) {
|
|
sceneID, err := strconv.Atoi(scene_id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var keys []int
|
|
tags := make(map[int]*models.SceneMarkerTag)
|
|
|
|
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
|
|
sceneMarkers, err := repo.SceneMarker().FindBySceneID(sceneID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tqb := repo.Tag()
|
|
for _, sceneMarker := range sceneMarkers {
|
|
markerPrimaryTag, err := tqb.Find(sceneMarker.PrimaryTagID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, hasKey := tags[markerPrimaryTag.ID]
|
|
if !hasKey {
|
|
sceneMarkerTag := &models.SceneMarkerTag{Tag: markerPrimaryTag}
|
|
tags[markerPrimaryTag.ID] = sceneMarkerTag
|
|
keys = append(keys, markerPrimaryTag.ID)
|
|
}
|
|
tags[markerPrimaryTag.ID].SceneMarkers = append(tags[markerPrimaryTag.ID].SceneMarkers, sceneMarker)
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Sort so that primary tags that show up earlier in the video are first.
|
|
sort.Slice(keys, func(i, j int) bool {
|
|
a := tags[keys[i]]
|
|
b := tags[keys[j]]
|
|
return a.SceneMarkers[0].Seconds < b.SceneMarkers[0].Seconds
|
|
})
|
|
|
|
var result []*models.SceneMarkerTag
|
|
for _, key := range keys {
|
|
result = append(result, tags[key])
|
|
}
|
|
|
|
return result, nil
|
|
}
|