Add scene auto-tagging from filename (#204)

* Add auto tagging for performers, studios and tags

* Fix scene title logging

* Fix golang 1.11 compile error

* Improve regex pattern. Only log when added

* Remove paging from parse query

* Add integration test

* Fix prefix detection on paths
This commit is contained in:
WithoutPants
2019-12-02 03:18:44 +11:00
committed by Leopere
parent ca2680a86d
commit 1704d3771f
17 changed files with 991 additions and 4 deletions

View File

@@ -1,6 +1,11 @@
package models
import "github.com/jmoiron/sqlx"
import (
"database/sql"
"github.com/jmoiron/sqlx"
"github.com/stashapp/stash/pkg/database"
)
type JoinsQueryBuilder struct{}
@@ -8,6 +13,41 @@ func NewJoinsQueryBuilder() JoinsQueryBuilder {
return JoinsQueryBuilder{}
}
func (qb *JoinsQueryBuilder) GetScenePerformers(sceneID int, tx *sqlx.Tx) ([]PerformersScenes, error) {
ensureTx(tx)
// Delete the existing joins and then create new ones
query := `SELECT * from performers_scenes WHERE scene_id = ?`
var rows *sqlx.Rows
var err error
if tx != nil {
rows, err = tx.Queryx(query, sceneID)
} else {
rows, err = database.DB.Queryx(query, sceneID)
}
if err != nil && err != sql.ErrNoRows {
return nil, err
}
defer rows.Close()
performerScenes := make([]PerformersScenes, 0)
for rows.Next() {
performerScene := PerformersScenes{}
if err := rows.StructScan(&performerScene); err != nil {
return nil, err
}
performerScenes = append(performerScenes, performerScene)
}
if err := rows.Err(); err != nil {
return nil, err
}
return performerScenes, nil
}
func (qb *JoinsQueryBuilder) CreatePerformersScenes(newJoins []PerformersScenes, tx *sqlx.Tx) error {
ensureTx(tx)
for _, join := range newJoins {
@@ -22,6 +62,36 @@ func (qb *JoinsQueryBuilder) CreatePerformersScenes(newJoins []PerformersScenes,
return nil
}
// AddPerformerScene adds a performer to a scene. It does not make any change
// if the performer already exists on the scene. It returns true if scene
// performer was added.
func (qb *JoinsQueryBuilder) AddPerformerScene(sceneID int, performerID int, tx *sqlx.Tx) (bool, error) {
ensureTx(tx)
existingPerformers, err := qb.GetScenePerformers(sceneID, tx)
if err != nil {
return false, err
}
// ensure not already present
for _, p := range existingPerformers {
if p.PerformerID == performerID && p.SceneID == sceneID {
return false, nil
}
}
performerJoin := PerformersScenes{
PerformerID: performerID,
SceneID: sceneID,
}
performerJoins := append(existingPerformers, performerJoin)
err = qb.UpdatePerformersScenes(sceneID, performerJoins, tx)
return err == nil, err
}
func (qb *JoinsQueryBuilder) UpdatePerformersScenes(sceneID int, updatedJoins []PerformersScenes, tx *sqlx.Tx) error {
ensureTx(tx)
@@ -41,6 +111,41 @@ func (qb *JoinsQueryBuilder) DestroyPerformersScenes(sceneID int, tx *sqlx.Tx) e
return err
}
func (qb *JoinsQueryBuilder) GetSceneTags(sceneID int, tx *sqlx.Tx) ([]ScenesTags, error) {
ensureTx(tx)
// Delete the existing joins and then create new ones
query := `SELECT * from scenes_tags WHERE scene_id = ?`
var rows *sqlx.Rows
var err error
if tx != nil {
rows, err = tx.Queryx(query, sceneID)
} else {
rows, err = database.DB.Queryx(query, sceneID)
}
if err != nil && err != sql.ErrNoRows {
return nil, err
}
defer rows.Close()
sceneTags := make([]ScenesTags, 0)
for rows.Next() {
sceneTag := ScenesTags{}
if err := rows.StructScan(&sceneTag); err != nil {
return nil, err
}
sceneTags = append(sceneTags, sceneTag)
}
if err := rows.Err(); err != nil {
return nil, err
}
return sceneTags, nil
}
func (qb *JoinsQueryBuilder) CreateScenesTags(newJoins []ScenesTags, tx *sqlx.Tx) error {
ensureTx(tx)
for _, join := range newJoins {
@@ -66,6 +171,35 @@ func (qb *JoinsQueryBuilder) UpdateScenesTags(sceneID int, updatedJoins []Scenes
return qb.CreateScenesTags(updatedJoins, tx)
}
// AddSceneTag adds a tag to a scene. It does not make any change if the tag
// already exists on the scene. It returns true if scene tag was added.
func (qb *JoinsQueryBuilder) AddSceneTag(sceneID int, tagID int, tx *sqlx.Tx) (bool, error) {
ensureTx(tx)
existingTags, err := qb.GetSceneTags(sceneID, tx)
if err != nil {
return false, err
}
// ensure not already present
for _, p := range existingTags {
if p.TagID == tagID && p.SceneID == sceneID {
return false, nil
}
}
tagJoin := ScenesTags{
TagID: tagID,
SceneID: sceneID,
}
tagJoins := append(existingTags, tagJoin)
err = qb.UpdateScenesTags(sceneID, tagJoins, tx)
return err == nil, err
}
func (qb *JoinsQueryBuilder) DestroyScenesTags(sceneID int, tx *sqlx.Tx) error {
ensureTx(tx)