2019-03-23 21:09:05 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-01-04 03:20:31 +00:00
|
|
|
"fmt"
|
2022-03-17 00:33:59 +00:00
|
|
|
"path/filepath"
|
2022-01-04 03:20:31 +00:00
|
|
|
"strings"
|
2019-07-28 09:36:52 +00:00
|
|
|
|
2022-03-17 00:33:59 +00:00
|
|
|
"github.com/stashapp/stash/internal/manager/config"
|
|
|
|
"github.com/stashapp/stash/pkg/fsutil"
|
2019-03-23 21:09:05 +00:00
|
|
|
"github.com/stashapp/stash/pkg/models"
|
2022-01-04 03:20:31 +00:00
|
|
|
"github.com/stashapp/stash/pkg/scraper/stashbox"
|
2021-10-14 04:16:45 +00:00
|
|
|
"golang.org/x/text/collate"
|
2019-03-23 21:09:05 +00:00
|
|
|
)
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *queryResolver) Configuration(ctx context.Context) (*ConfigResult, error) {
|
2019-03-23 21:09:05 +00:00
|
|
|
return makeConfigResult(), nil
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *queryResolver) Directory(ctx context.Context, path, locale *string) (*Directory, error) {
|
2021-05-25 08:40:51 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
directory := &Directory{}
|
2021-05-25 08:40:51 +00:00
|
|
|
var err error
|
|
|
|
|
2021-10-14 04:16:45 +00:00
|
|
|
col := newCollator(locale, collate.IgnoreCase, collate.Numeric)
|
|
|
|
|
2019-03-23 21:09:05 +00:00
|
|
|
var dirPath = ""
|
|
|
|
if path != nil {
|
|
|
|
dirPath = *path
|
|
|
|
}
|
2022-03-17 00:33:59 +00:00
|
|
|
currentDir := getDir(dirPath)
|
|
|
|
directories, err := listDir(col, currentDir)
|
2021-05-25 08:40:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return directory, err
|
|
|
|
}
|
|
|
|
|
|
|
|
directory.Path = currentDir
|
2022-03-17 00:33:59 +00:00
|
|
|
directory.Parent = getParent(currentDir)
|
2021-05-25 08:40:51 +00:00
|
|
|
directory.Directories = directories
|
2020-05-09 03:08:00 +00:00
|
|
|
|
2021-05-25 08:40:51 +00:00
|
|
|
return directory, err
|
2019-03-23 21:09:05 +00:00
|
|
|
}
|
|
|
|
|
2022-03-17 00:33:59 +00:00
|
|
|
func getDir(path string) string {
|
|
|
|
if path == "" {
|
|
|
|
path = fsutil.GetHomeDirectory()
|
|
|
|
}
|
|
|
|
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
|
|
|
|
func getParent(path string) *string {
|
|
|
|
isRoot := path[len(path)-1:] == "/"
|
|
|
|
if isRoot {
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
parentPath := filepath.Clean(path + "/..")
|
|
|
|
return &parentPath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func makeConfigResult() *ConfigResult {
|
|
|
|
return &ConfigResult{
|
2019-08-22 22:24:14 +00:00
|
|
|
General: makeConfigGeneralResult(),
|
|
|
|
Interface: makeConfigInterfaceResult(),
|
2021-05-20 06:58:43 +00:00
|
|
|
Dlna: makeConfigDLNAResult(),
|
2021-08-04 02:32:58 +00:00
|
|
|
Scraping: makeConfigScrapingResult(),
|
2021-10-28 03:25:17 +00:00
|
|
|
Defaults: makeConfigDefaultsResult(),
|
2022-06-14 00:34:04 +00:00
|
|
|
UI: makeConfigUIResult(),
|
2019-03-23 21:09:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func makeConfigGeneralResult() *ConfigGeneralResult {
|
2021-04-11 23:31:33 +00:00
|
|
|
config := config.GetInstance()
|
2019-10-25 00:13:44 +00:00
|
|
|
logFile := config.GetLogFile()
|
2019-11-04 21:38:33 +00:00
|
|
|
|
|
|
|
maxTranscodeSize := config.GetMaxTranscodeSize()
|
|
|
|
maxStreamingTranscodeSize := config.GetMaxStreamingTranscodeSize()
|
|
|
|
|
2021-08-10 03:51:31 +00:00
|
|
|
customPerformerImageLocation := config.GetCustomPerformerImageLocation()
|
|
|
|
|
2020-03-20 21:55:15 +00:00
|
|
|
scraperUserAgent := config.GetScraperUserAgent()
|
2020-08-04 00:42:40 +00:00
|
|
|
scraperCDPPath := config.GetScraperCDPPath()
|
2020-03-20 21:55:15 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
return &ConfigGeneralResult{
|
2023-03-10 00:25:55 +00:00
|
|
|
Stashes: config.GetStashPaths(),
|
|
|
|
DatabasePath: config.GetDatabasePath(),
|
|
|
|
BackupDirectoryPath: config.GetBackupDirectoryPath(),
|
|
|
|
GeneratedPath: config.GetGeneratedPath(),
|
|
|
|
MetadataPath: config.GetMetadataPath(),
|
|
|
|
ConfigFilePath: config.GetConfigFile(),
|
|
|
|
ScrapersPath: config.GetScrapersPath(),
|
|
|
|
CachePath: config.GetCachePath(),
|
2023-03-16 23:52:49 +00:00
|
|
|
BlobsPath: config.GetBlobsPath(),
|
|
|
|
BlobsStorage: config.GetBlobsStorage(),
|
2023-03-10 00:25:55 +00:00
|
|
|
CalculateMd5: config.IsCalculateMD5(),
|
|
|
|
VideoFileNamingAlgorithm: config.GetVideoFileNamingAlgorithm(),
|
|
|
|
ParallelTasks: config.GetParallelTasks(),
|
|
|
|
PreviewAudio: config.GetPreviewAudio(),
|
|
|
|
PreviewSegments: config.GetPreviewSegments(),
|
|
|
|
PreviewSegmentDuration: config.GetPreviewSegmentDuration(),
|
|
|
|
PreviewExcludeStart: config.GetPreviewExcludeStart(),
|
|
|
|
PreviewExcludeEnd: config.GetPreviewExcludeEnd(),
|
|
|
|
PreviewPreset: config.GetPreviewPreset(),
|
|
|
|
TranscodeHardwareAcceleration: config.GetTranscodeHardwareAcceleration(),
|
|
|
|
MaxTranscodeSize: &maxTranscodeSize,
|
|
|
|
MaxStreamingTranscodeSize: &maxStreamingTranscodeSize,
|
|
|
|
WriteImageThumbnails: config.IsWriteImageThumbnails(),
|
2023-05-16 23:30:51 +00:00
|
|
|
CreateImageClipsFromVideos: config.IsCreateImageClipsFromVideos(),
|
2023-03-10 00:25:55 +00:00
|
|
|
GalleryCoverRegex: config.GetGalleryCoverRegex(),
|
|
|
|
APIKey: config.GetAPIKey(),
|
|
|
|
Username: config.GetUsername(),
|
|
|
|
Password: config.GetPasswordHash(),
|
|
|
|
MaxSessionAge: config.GetMaxSessionAge(),
|
|
|
|
LogFile: &logFile,
|
|
|
|
LogOut: config.GetLogOut(),
|
|
|
|
LogLevel: config.GetLogLevel(),
|
|
|
|
LogAccess: config.GetLogAccess(),
|
|
|
|
VideoExtensions: config.GetVideoExtensions(),
|
|
|
|
ImageExtensions: config.GetImageExtensions(),
|
|
|
|
GalleryExtensions: config.GetGalleryExtensions(),
|
|
|
|
CreateGalleriesFromFolders: config.GetCreateGalleriesFromFolders(),
|
|
|
|
Excludes: config.GetExcludes(),
|
|
|
|
ImageExcludes: config.GetImageExcludes(),
|
|
|
|
CustomPerformerImageLocation: &customPerformerImageLocation,
|
|
|
|
ScraperUserAgent: &scraperUserAgent,
|
|
|
|
ScraperCertCheck: config.GetScraperCertCheck(),
|
|
|
|
ScraperCDPPath: &scraperCDPPath,
|
|
|
|
StashBoxes: config.GetStashBoxes(),
|
|
|
|
PythonPath: config.GetPythonPath(),
|
|
|
|
TranscodeInputArgs: config.GetTranscodeInputArgs(),
|
|
|
|
TranscodeOutputArgs: config.GetTranscodeOutputArgs(),
|
|
|
|
LiveTranscodeInputArgs: config.GetLiveTranscodeInputArgs(),
|
|
|
|
LiveTranscodeOutputArgs: config.GetLiveTranscodeOutputArgs(),
|
|
|
|
DrawFunscriptHeatmapRange: config.GetDrawFunscriptHeatmapRange(),
|
2019-03-23 21:09:05 +00:00
|
|
|
}
|
2019-03-24 17:04:31 +00:00
|
|
|
}
|
2019-08-22 22:24:14 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func makeConfigInterfaceResult() *ConfigInterfaceResult {
|
2021-04-11 23:31:33 +00:00
|
|
|
config := config.GetInstance()
|
2020-12-09 00:59:09 +00:00
|
|
|
menuItems := config.GetMenuItems()
|
2019-11-29 01:41:17 +00:00
|
|
|
soundOnPreview := config.GetSoundOnPreview()
|
|
|
|
wallShowTitle := config.GetWallShowTitle()
|
2022-02-20 00:08:05 +00:00
|
|
|
showScrubber := config.GetShowScrubber()
|
2020-05-26 23:33:49 +00:00
|
|
|
wallPlayback := config.GetWallPlayback()
|
2021-11-07 23:14:11 +00:00
|
|
|
noBrowser := config.GetNoBrowser()
|
2022-02-03 00:20:34 +00:00
|
|
|
notificationsEnabled := config.GetNotificationsEnabled()
|
2019-11-29 01:41:17 +00:00
|
|
|
maximumLoopDuration := config.GetMaximumLoopDuration()
|
|
|
|
autostartVideo := config.GetAutostartVideo()
|
2021-11-06 22:55:51 +00:00
|
|
|
autostartVideoOnPlaySelected := config.GetAutostartVideoOnPlaySelected()
|
|
|
|
continuePlaylistDefault := config.GetContinuePlaylistDefault()
|
2019-12-05 17:24:22 +00:00
|
|
|
showStudioAsText := config.GetShowStudioAsText()
|
2019-08-22 22:24:14 +00:00
|
|
|
css := config.GetCSS()
|
|
|
|
cssEnabled := config.GetCSSEnabled()
|
2022-11-16 22:37:06 +00:00
|
|
|
javascript := config.GetJavascript()
|
|
|
|
javascriptEnabled := config.GetJavascriptEnabled()
|
2022-09-22 09:49:35 +00:00
|
|
|
customLocales := config.GetCustomLocales()
|
|
|
|
customLocalesEnabled := config.GetCustomLocalesEnabled()
|
2020-02-26 09:07:03 +00:00
|
|
|
language := config.GetLanguage()
|
2021-05-24 03:34:28 +00:00
|
|
|
handyKey := config.GetHandyKey()
|
2021-08-26 01:50:02 +00:00
|
|
|
scriptOffset := config.GetFunscriptOffset()
|
2022-03-22 21:18:12 +00:00
|
|
|
imageLightboxOptions := config.GetImageLightboxOptions()
|
2021-12-14 04:06:05 +00:00
|
|
|
// FIXME - misnamed output field means we have redundant fields
|
|
|
|
disableDropdownCreate := config.GetDisableDropdownCreate()
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
return &ConfigInterfaceResult{
|
2021-11-06 22:55:51 +00:00
|
|
|
MenuItems: menuItems,
|
|
|
|
SoundOnPreview: &soundOnPreview,
|
|
|
|
WallShowTitle: &wallShowTitle,
|
|
|
|
WallPlayback: &wallPlayback,
|
2022-02-20 00:08:05 +00:00
|
|
|
ShowScrubber: &showScrubber,
|
2021-11-06 22:55:51 +00:00
|
|
|
MaximumLoopDuration: &maximumLoopDuration,
|
|
|
|
NoBrowser: &noBrowser,
|
2022-02-03 00:20:34 +00:00
|
|
|
NotificationsEnabled: ¬ificationsEnabled,
|
2021-11-06 22:55:51 +00:00
|
|
|
AutostartVideo: &autostartVideo,
|
|
|
|
ShowStudioAsText: &showStudioAsText,
|
|
|
|
AutostartVideoOnPlaySelected: &autostartVideoOnPlaySelected,
|
|
|
|
ContinuePlaylistDefault: &continuePlaylistDefault,
|
|
|
|
CSS: &css,
|
|
|
|
CSSEnabled: &cssEnabled,
|
2022-11-16 22:37:06 +00:00
|
|
|
Javascript: &javascript,
|
|
|
|
JavascriptEnabled: &javascriptEnabled,
|
2022-09-22 09:49:35 +00:00
|
|
|
CustomLocales: &customLocales,
|
|
|
|
CustomLocalesEnabled: &customLocalesEnabled,
|
2021-11-06 22:55:51 +00:00
|
|
|
Language: &language,
|
2022-03-22 21:18:12 +00:00
|
|
|
|
|
|
|
ImageLightbox: &imageLightboxOptions,
|
2021-12-14 04:06:05 +00:00
|
|
|
|
|
|
|
// FIXME - see above
|
|
|
|
DisabledDropdownCreate: disableDropdownCreate,
|
|
|
|
DisableDropdownCreate: disableDropdownCreate,
|
|
|
|
|
|
|
|
HandyKey: &handyKey,
|
|
|
|
FunscriptOffset: &scriptOffset,
|
2019-08-22 22:24:14 +00:00
|
|
|
}
|
|
|
|
}
|
2021-05-20 06:58:43 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func makeConfigDLNAResult() *ConfigDLNAResult {
|
2021-05-20 06:58:43 +00:00
|
|
|
config := config.GetInstance()
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
return &ConfigDLNAResult{
|
2021-05-20 06:58:43 +00:00
|
|
|
ServerName: config.GetDLNAServerName(),
|
|
|
|
Enabled: config.GetDLNADefaultEnabled(),
|
|
|
|
WhitelistedIPs: config.GetDLNADefaultIPWhitelist(),
|
|
|
|
Interfaces: config.GetDLNAInterfaces(),
|
2023-05-03 03:33:32 +00:00
|
|
|
VideoSortOrder: config.GetVideoSortOrder(),
|
2021-05-20 06:58:43 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-04 02:32:58 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func makeConfigScrapingResult() *ConfigScrapingResult {
|
2021-08-04 02:32:58 +00:00
|
|
|
config := config.GetInstance()
|
|
|
|
|
|
|
|
scraperUserAgent := config.GetScraperUserAgent()
|
|
|
|
scraperCDPPath := config.GetScraperCDPPath()
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
return &ConfigScrapingResult{
|
2021-08-10 04:07:01 +00:00
|
|
|
ScraperUserAgent: &scraperUserAgent,
|
|
|
|
ScraperCertCheck: config.GetScraperCertCheck(),
|
|
|
|
ScraperCDPPath: &scraperCDPPath,
|
|
|
|
ExcludeTagPatterns: config.GetScraperExcludeTagPatterns(),
|
2021-08-04 02:32:58 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-28 03:25:17 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func makeConfigDefaultsResult() *ConfigDefaultSettingsResult {
|
2021-10-28 03:25:17 +00:00
|
|
|
config := config.GetInstance()
|
2021-10-28 05:45:44 +00:00
|
|
|
deleteFileDefault := config.GetDeleteFileDefault()
|
|
|
|
deleteGeneratedDefault := config.GetDeleteGeneratedDefault()
|
2021-10-28 03:25:17 +00:00
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
return &ConfigDefaultSettingsResult{
|
2021-10-28 05:45:44 +00:00
|
|
|
Identify: config.GetDefaultIdentifySettings(),
|
2021-11-23 22:09:47 +00:00
|
|
|
Scan: config.GetDefaultScanSettings(),
|
|
|
|
AutoTag: config.GetDefaultAutoTagSettings(),
|
|
|
|
Generate: config.GetDefaultGenerateSettings(),
|
2021-10-28 05:45:44 +00:00
|
|
|
DeleteFile: &deleteFileDefault,
|
|
|
|
DeleteGenerated: &deleteGeneratedDefault,
|
2021-10-28 03:25:17 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-04 03:20:31 +00:00
|
|
|
|
2022-06-14 00:34:04 +00:00
|
|
|
func makeConfigUIResult() map[string]interface{} {
|
|
|
|
return config.GetInstance().GetUIConfiguration()
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
func (r *queryResolver) ValidateStashBoxCredentials(ctx context.Context, input config.StashBoxInput) (*StashBoxValidationResult, error) {
|
2022-05-19 07:49:32 +00:00
|
|
|
client := stashbox.NewClient(models.StashBox{Endpoint: input.Endpoint, APIKey: input.APIKey}, r.txnManager, r.stashboxRepository())
|
2022-01-04 03:20:31 +00:00
|
|
|
user, err := client.GetUser(ctx)
|
|
|
|
|
|
|
|
valid := user != nil && user.Me != nil
|
|
|
|
var status string
|
|
|
|
if valid {
|
|
|
|
status = fmt.Sprintf("Successfully authenticated as %s", user.Me.Name)
|
|
|
|
} else {
|
|
|
|
switch {
|
|
|
|
case strings.Contains(strings.ToLower(err.Error()), "doctype"):
|
|
|
|
// Index file returned rather than graphql
|
|
|
|
status = "Invalid endpoint"
|
|
|
|
case strings.Contains(err.Error(), "request failed"):
|
|
|
|
status = "No response from server"
|
|
|
|
case strings.HasPrefix(err.Error(), "invalid character") ||
|
|
|
|
strings.HasPrefix(err.Error(), "illegal base64 data") ||
|
|
|
|
err.Error() == "unexpected end of JSON input" ||
|
|
|
|
err.Error() == "token contains an invalid number of segments":
|
|
|
|
status = "Malformed API key."
|
|
|
|
case err.Error() == "" || err.Error() == "signature is invalid":
|
|
|
|
status = "Invalid or expired API key."
|
|
|
|
default:
|
|
|
|
status = fmt.Sprintf("Unknown error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-25 05:55:05 +00:00
|
|
|
result := StashBoxValidationResult{
|
2022-01-04 03:20:31 +00:00
|
|
|
Valid: valid,
|
|
|
|
Status: status,
|
|
|
|
}
|
|
|
|
|
|
|
|
return &result, nil
|
|
|
|
}
|