mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Added created / updated timestamp to exported JSON
This commit is contained in:
@@ -3,6 +3,7 @@ package jsonschema
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -24,6 +25,8 @@ type Performer struct {
|
||||
Aliases string `json:"aliases,omitempty"`
|
||||
Favorite bool `json:"favorite,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
func LoadPerformerFile(filePath string) (*Performer, error) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package jsonschema
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -11,6 +12,8 @@ type SceneMarker struct {
|
||||
Seconds string `json:"seconds,omitempty"`
|
||||
PrimaryTag string `json:"primary_tag,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
type SceneFile struct {
|
||||
@@ -36,6 +39,8 @@ type Scene struct {
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Markers []SceneMarker `json:"markers,omitempty"`
|
||||
File *SceneFile `json:"file,omitempty"`
|
||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
func LoadSceneFile(filePath string) (*Scene, error) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package jsonschema
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -10,6 +11,8 @@ type Studio struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
func LoadStudioFile(filePath string) (*Studio, error) {
|
||||
|
||||
@@ -60,7 +60,10 @@ func (t *ExportTask) ExportScenes(ctx context.Context) {
|
||||
logger.Progressf("[scenes] %d of %d", index, len(scenes))
|
||||
|
||||
t.Mappings.Scenes = append(t.Mappings.Scenes, jsonschema.PathMapping{Path: scene.Path, Checksum: scene.Checksum})
|
||||
newSceneJSON := jsonschema.Scene{}
|
||||
newSceneJSON := jsonschema.Scene{
|
||||
CreatedAt: models.JSONTime{Time: scene.CreatedAt.Timestamp},
|
||||
UpdatedAt: models.JSONTime{Time: scene.UpdatedAt.Timestamp},
|
||||
}
|
||||
|
||||
var studioName string
|
||||
if scene.StudioID.Valid {
|
||||
@@ -129,6 +132,8 @@ func (t *ExportTask) ExportScenes(ctx context.Context) {
|
||||
Seconds: t.getDecimalString(sceneMarker.Seconds),
|
||||
PrimaryTag: primaryTag.Name,
|
||||
Tags: t.getTagNames(sceneMarkerTags),
|
||||
CreatedAt: models.JSONTime{Time: sceneMarker.CreatedAt.Timestamp},
|
||||
UpdatedAt: models.JSONTime{Time: sceneMarker.UpdatedAt.Timestamp},
|
||||
}
|
||||
|
||||
newSceneJSON.Markers = append(newSceneJSON.Markers, sceneMarkerJSON)
|
||||
@@ -208,7 +213,10 @@ func (t *ExportTask) ExportPerformers(ctx context.Context) {
|
||||
|
||||
t.Mappings.Performers = append(t.Mappings.Performers, jsonschema.NameMapping{Name: performer.Name.String, Checksum: performer.Checksum})
|
||||
|
||||
newPerformerJSON := jsonschema.Performer{}
|
||||
newPerformerJSON := jsonschema.Performer{
|
||||
CreatedAt: models.JSONTime{Time: performer.CreatedAt.Timestamp},
|
||||
UpdatedAt: models.JSONTime{Time: performer.UpdatedAt.Timestamp},
|
||||
}
|
||||
|
||||
if performer.Name.Valid {
|
||||
newPerformerJSON.Name = performer.Name.String
|
||||
@@ -291,7 +299,10 @@ func (t *ExportTask) ExportStudios(ctx context.Context) {
|
||||
|
||||
t.Mappings.Studios = append(t.Mappings.Studios, jsonschema.NameMapping{Name: studio.Name.String, Checksum: studio.Checksum})
|
||||
|
||||
newStudioJSON := jsonschema.Studio{}
|
||||
newStudioJSON := jsonschema.Studio{
|
||||
CreatedAt: models.JSONTime{Time: studio.CreatedAt.Timestamp},
|
||||
UpdatedAt: models.JSONTime{Time: studio.UpdatedAt.Timestamp},
|
||||
}
|
||||
|
||||
if studio.Name.Valid {
|
||||
newStudioJSON.Name = studio.Name.String
|
||||
|
||||
@@ -73,13 +73,12 @@ func (t *ImportTask) ImportPerformers(ctx context.Context) {
|
||||
}
|
||||
|
||||
// Populate a new performer from the input
|
||||
currentTime := time.Now()
|
||||
newPerformer := models.Performer{
|
||||
Image: imageData,
|
||||
Checksum: checksum,
|
||||
Favorite: sql.NullBool{Bool: performerJSON.Favorite, Valid: true},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(performerJSON.CreatedAt)},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(performerJSON.UpdatedAt)},
|
||||
}
|
||||
|
||||
if performerJSON.Name != "" {
|
||||
@@ -169,14 +168,13 @@ func (t *ImportTask) ImportStudios(ctx context.Context) {
|
||||
}
|
||||
|
||||
// Populate a new studio from the input
|
||||
currentTime := time.Now()
|
||||
newStudio := models.Studio{
|
||||
Image: imageData,
|
||||
Checksum: checksum,
|
||||
Name: sql.NullString{String: studioJSON.Name, Valid: true},
|
||||
URL: sql.NullString{String: studioJSON.URL, Valid: true},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(studioJSON.CreatedAt)},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(studioJSON.UpdatedAt)},
|
||||
}
|
||||
|
||||
_, err = qb.Create(newStudio, tx)
|
||||
@@ -308,12 +306,6 @@ func (t *ImportTask) ImportScrapedItems(ctx context.Context) {
|
||||
index := i + 1
|
||||
logger.Progressf("[scraped sites] %d of %d", index, len(t.Mappings.Scenes))
|
||||
|
||||
var updatedAt time.Time
|
||||
if currentTime.Location() != nil {
|
||||
updatedAt = mappingJSON.UpdatedAt.Time.In(currentTime.Location())
|
||||
} else {
|
||||
updatedAt = mappingJSON.UpdatedAt.Time
|
||||
}
|
||||
newScrapedItem := models.ScrapedItem{
|
||||
Title: sql.NullString{String: mappingJSON.Title, Valid: true},
|
||||
Description: sql.NullString{String: mappingJSON.Description, Valid: true},
|
||||
@@ -328,7 +320,7 @@ func (t *ImportTask) ImportScrapedItems(ctx context.Context) {
|
||||
VideoFilename: sql.NullString{String: mappingJSON.VideoFilename, Valid: true},
|
||||
VideoURL: sql.NullString{String: mappingJSON.VideoURL, Valid: true},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: updatedAt},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(mappingJSON.UpdatedAt)},
|
||||
}
|
||||
|
||||
studio, err := sqb.FindByName(mappingJSON.Studio, tx)
|
||||
@@ -356,7 +348,6 @@ func (t *ImportTask) ImportScenes(ctx context.Context) {
|
||||
tx := database.DB.MustBeginTx(ctx, nil)
|
||||
qb := models.NewSceneQueryBuilder()
|
||||
jqb := models.NewJoinsQueryBuilder()
|
||||
currentTime := time.Now()
|
||||
|
||||
for i, mappingJSON := range t.Mappings.Scenes {
|
||||
index := i + 1
|
||||
@@ -371,8 +362,6 @@ func (t *ImportTask) ImportScenes(ctx context.Context) {
|
||||
newScene := models.Scene{
|
||||
Checksum: mappingJSON.Checksum,
|
||||
Path: mappingJSON.Path,
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
}
|
||||
|
||||
sceneJSON, err := instance.JSON.getScene(mappingJSON.Checksum)
|
||||
@@ -398,6 +387,8 @@ func (t *ImportTask) ImportScenes(ctx context.Context) {
|
||||
if sceneJSON.Rating != 0 {
|
||||
newScene.Rating = sql.NullInt64{Int64: int64(sceneJSON.Rating), Valid: true}
|
||||
}
|
||||
newScene.CreatedAt = models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(sceneJSON.CreatedAt)}
|
||||
newScene.UpdatedAt = models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(sceneJSON.UpdatedAt)}
|
||||
|
||||
if sceneJSON.File != nil {
|
||||
if sceneJSON.File.Size != "" {
|
||||
@@ -520,8 +511,8 @@ func (t *ImportTask) ImportScenes(ctx context.Context) {
|
||||
Title: marker.Title,
|
||||
Seconds: seconds,
|
||||
SceneID: sql.NullInt64{Int64: int64(scene.ID), Valid: true},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(marker.CreatedAt)},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(marker.UpdatedAt)},
|
||||
}
|
||||
|
||||
primaryTag, err := tqb.FindByName(marker.PrimaryTag, tx)
|
||||
@@ -636,3 +627,21 @@ func (t *ImportTask) getUnique(s []string) []string {
|
||||
}
|
||||
return s[:j]
|
||||
}
|
||||
|
||||
var currentLocation = time.Now().Location()
|
||||
|
||||
func (t *ImportTask) getTimeFromJSONTime(jsonTime models.JSONTime) time.Time {
|
||||
if currentLocation != nil {
|
||||
if jsonTime.IsZero() {
|
||||
return time.Now().In(currentLocation)
|
||||
} else {
|
||||
return jsonTime.Time.In(currentLocation)
|
||||
}
|
||||
} else {
|
||||
if jsonTime.IsZero() {
|
||||
return time.Now()
|
||||
} else {
|
||||
return jsonTime.Time
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package utils
|
||||
|
||||
// Btoi transforms a boolean to an int. 1 for true, false otherwise
|
||||
func Btoi(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// FileType uses the filetype package to determine the given file path's type
|
||||
func FileType(filePath string) (types.Type, error) {
|
||||
file, _ := os.Open(filePath)
|
||||
|
||||
@@ -20,6 +21,7 @@ func FileType(filePath string) (types.Type, error) {
|
||||
return filetype.Match(head)
|
||||
}
|
||||
|
||||
// FileExists returns true if the given path exists
|
||||
func FileExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
@@ -31,6 +33,7 @@ func FileExists(path string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// DirExists returns true if the given path exists and is a directory
|
||||
func DirExists(path string) (bool, error) {
|
||||
exists, _ := FileExists(path)
|
||||
fileInfo, _ := os.Stat(path)
|
||||
@@ -40,6 +43,7 @@ func DirExists(path string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Touch creates an empty file at the given path if it doesn't already exist
|
||||
func Touch(path string) error {
|
||||
var _, err = os.Stat(path)
|
||||
if os.IsNotExist(err) {
|
||||
@@ -52,6 +56,7 @@ func Touch(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnsureDir will create a directory at the given path if it doesn't already exist
|
||||
func EnsureDir(path string) error {
|
||||
exists, err := FileExists(path)
|
||||
if !exists {
|
||||
@@ -61,10 +66,12 @@ func EnsureDir(path string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveDir removes the given file path along with all of its contents
|
||||
func RemoveDir(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
// EmptyDir will recursively remove the contents of a directory at the given path
|
||||
func EmptyDir(path string) error {
|
||||
d, err := os.Open(path)
|
||||
if err != nil {
|
||||
@@ -87,6 +94,7 @@ func EmptyDir(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListDir will return the contents of a given directory path as a string slice
|
||||
func ListDir(path string) []string {
|
||||
if path == "" {
|
||||
path = GetHomeDirectory()
|
||||
@@ -117,6 +125,7 @@ func ListDir(path string) []string {
|
||||
return dirPaths
|
||||
}
|
||||
|
||||
// GetHomeDirectory returns the path of the user's home directory. ~ on Unix and C:\Users\UserName on Windows
|
||||
func GetHomeDirectory() string {
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// ProcessBase64Image transforms a base64 encoded string from a form post and returns the MD5 hash of the data and the
|
||||
// image itself as a byte slice.
|
||||
func ProcessBase64Image(imageString string) (string, []byte, error) {
|
||||
if imageString == "" {
|
||||
return "", nil, fmt.Errorf("empty image string")
|
||||
@@ -27,10 +29,12 @@ func ProcessBase64Image(imageString string) (string, []byte, error) {
|
||||
return MD5FromBytes(imageData), imageData, nil
|
||||
}
|
||||
|
||||
// GetDataFromBase64String returns the given base64 encoded string as a byte slice
|
||||
func GetDataFromBase64String(encodedString string) ([]byte, error) {
|
||||
return base64.StdEncoding.DecodeString(encodedString)
|
||||
}
|
||||
|
||||
// GetBase64StringFromData returns the given byte slice as a base64 encoded string
|
||||
func GetBase64StringFromData(data []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(data)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user