Copy disabled (too large)
Download .txt
Showing preview only (11,279K chars total). Download the full file to get everything.
Repository: stashapp/stash
Branch: develop
Commit: c832e1a8a292
Files: 1651
Total size: 10.5 MB
Directory structure:
gitextract_5pun5gxb/
├── .dockerignore
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ ├── PULL_REQUEST_TEMPLATE/
│ │ ├── BugFix.md
│ │ └── Feature.md
│ └── workflows/
│ ├── build-compiler.yml
│ ├── build.yml
│ └── golangci-lint.yml
├── .gitignore
├── .golangci.yml
├── .gqlgenc.yml
├── .idea/
│ ├── codeStyles/
│ │ └── codeStyleConfig.xml
│ ├── dataSources.xml
│ ├── encodings.xml
│ ├── go.iml
│ ├── misc.xml
│ ├── modules.xml
│ ├── sqldialects.xml
│ └── vcs.xml
├── .mockery.yml
├── LICENSE
├── Makefile
├── README.md
├── cmd/
│ ├── phasher/
│ │ └── main.go
│ └── stash/
│ ├── main.go
│ └── main_test.go
├── docker/
│ ├── build/
│ │ └── x86_64/
│ │ ├── Dockerfile
│ │ ├── Dockerfile-CUDA
│ │ └── README.md
│ ├── ci/
│ │ └── x86_64/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ └── docker_push.sh
│ ├── compiler/
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ └── README.md
│ └── production/
│ ├── README.md
│ └── docker-compose.yml
├── docs/
│ ├── CONTRIBUTING.md
│ └── DEVELOPMENT.md
├── go.mod
├── go.sum
├── gqlgen.yml
├── graphql/
│ ├── schema/
│ │ ├── schema.graphql
│ │ └── types/
│ │ ├── config.graphql
│ │ ├── dlna.graphql
│ │ ├── file.graphql
│ │ ├── filters.graphql
│ │ ├── gallery-chapter.graphql
│ │ ├── gallery.graphql
│ │ ├── group.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── logging.graphql
│ │ ├── metadata.graphql
│ │ ├── migration.graphql
│ │ ├── movie.graphql
│ │ ├── package.graphql
│ │ ├── performer.graphql
│ │ ├── plugin.graphql
│ │ ├── scalars.graphql
│ │ ├── scene-marker-tag.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene.graphql
│ │ ├── scraped-group.graphql
│ │ ├── scraped-performer.graphql
│ │ ├── scraper.graphql
│ │ ├── sql.graphql
│ │ ├── stash-box.graphql
│ │ ├── stats.graphql
│ │ ├── studio.graphql
│ │ ├── tag.graphql
│ │ └── version.graphql
│ └── stash-box/
│ └── query.graphql
├── internal/
│ ├── api/
│ │ ├── authentication.go
│ │ ├── bool_map.go
│ │ ├── changeset_translator.go
│ │ ├── check_version.go
│ │ ├── context_keys.go
│ │ ├── custom_fields.go
│ │ ├── dir_list.go
│ │ ├── doc.go
│ │ ├── error.go
│ │ ├── fields.go
│ │ ├── images.go
│ │ ├── input.go
│ │ ├── json.go
│ │ ├── json_test.go
│ │ ├── loaders/
│ │ │ ├── customfieldsloader_gen.go
│ │ │ ├── dataloaders.go
│ │ │ ├── fileloader_gen.go
│ │ │ ├── folderloader_gen.go
│ │ │ ├── folderparentfolderidsloader_gen.go
│ │ │ ├── galleryfileidsloader_gen.go
│ │ │ ├── galleryloader_gen.go
│ │ │ ├── grouploader_gen.go
│ │ │ ├── imagefileidsloader_gen.go
│ │ │ ├── imageloader_gen.go
│ │ │ ├── performerloader_gen.go
│ │ │ ├── scenefileidsloader_gen.go
│ │ │ ├── scenelastplayedloader_gen.go
│ │ │ ├── sceneloader_gen.go
│ │ │ ├── sceneocountloader_gen.go
│ │ │ ├── sceneohistoryloader_gen.go
│ │ │ ├── sceneplaycountloader_gen.go
│ │ │ ├── sceneplayhistoryloader_gen.go
│ │ │ ├── studioloader_gen.go
│ │ │ └── tagloader_gen.go
│ │ ├── locale.go
│ │ ├── models.go
│ │ ├── plugin_map.go
│ │ ├── resolver.go
│ │ ├── resolver_model_config.go
│ │ ├── resolver_model_file.go
│ │ ├── resolver_model_folder.go
│ │ ├── resolver_model_gallery.go
│ │ ├── resolver_model_gallery_chapter.go
│ │ ├── resolver_model_image.go
│ │ ├── resolver_model_movie.go
│ │ ├── resolver_model_performer.go
│ │ ├── resolver_model_plugin.go
│ │ ├── resolver_model_saved_filter.go
│ │ ├── resolver_model_scene.go
│ │ ├── resolver_model_scene_marker.go
│ │ ├── resolver_model_studio.go
│ │ ├── resolver_model_tag.go
│ │ ├── resolver_mutation_configure.go
│ │ ├── resolver_mutation_dlna.go
│ │ ├── resolver_mutation_file.go
│ │ ├── resolver_mutation_gallery.go
│ │ ├── resolver_mutation_group.go
│ │ ├── resolver_mutation_image.go
│ │ ├── resolver_mutation_job.go
│ │ ├── resolver_mutation_metadata.go
│ │ ├── resolver_mutation_migrate.go
│ │ ├── resolver_mutation_movie.go
│ │ ├── resolver_mutation_package.go
│ │ ├── resolver_mutation_performer.go
│ │ ├── resolver_mutation_plugin.go
│ │ ├── resolver_mutation_saved_filter.go
│ │ ├── resolver_mutation_scene.go
│ │ ├── resolver_mutation_scraper.go
│ │ ├── resolver_mutation_stash_box.go
│ │ ├── resolver_mutation_studio.go
│ │ ├── resolver_mutation_tag.go
│ │ ├── resolver_mutation_tag_test.go
│ │ ├── resolver_query_configuration.go
│ │ ├── resolver_query_dlna.go
│ │ ├── resolver_query_find_file.go
│ │ ├── resolver_query_find_folder.go
│ │ ├── resolver_query_find_gallery.go
│ │ ├── resolver_query_find_group.go
│ │ ├── resolver_query_find_image.go
│ │ ├── resolver_query_find_movie.go
│ │ ├── resolver_query_find_performer.go
│ │ ├── resolver_query_find_saved_filter.go
│ │ ├── resolver_query_find_scene.go
│ │ ├── resolver_query_find_scene_marker.go
│ │ ├── resolver_query_find_studio.go
│ │ ├── resolver_query_find_tag.go
│ │ ├── resolver_query_job.go
│ │ ├── resolver_query_logs.go
│ │ ├── resolver_query_metadata.go
│ │ ├── resolver_query_package.go
│ │ ├── resolver_query_plugin.go
│ │ ├── resolver_query_scene.go
│ │ ├── resolver_query_scraper.go
│ │ ├── resolver_subscription_job.go
│ │ ├── resolver_subscription_logging.go
│ │ ├── routes.go
│ │ ├── routes_custom.go
│ │ ├── routes_downloads.go
│ │ ├── routes_gallery.go
│ │ ├── routes_group.go
│ │ ├── routes_image.go
│ │ ├── routes_performer.go
│ │ ├── routes_plugin.go
│ │ ├── routes_scene.go
│ │ ├── routes_studio.go
│ │ ├── routes_tag.go
│ │ ├── scraped_content.go
│ │ ├── server.go
│ │ ├── session.go
│ │ ├── stash_box.go
│ │ ├── timestamp.go
│ │ ├── timestamp_test.go
│ │ ├── types.go
│ │ └── urlbuilders/
│ │ ├── doc.go
│ │ ├── gallery.go
│ │ ├── group.go
│ │ ├── image.go
│ │ ├── performer.go
│ │ ├── scene.go
│ │ ├── scene_markers.go
│ │ ├── studio.go
│ │ └── tag.go
│ ├── autotag/
│ │ ├── doc.go
│ │ ├── gallery.go
│ │ ├── gallery_test.go
│ │ ├── image.go
│ │ ├── image_test.go
│ │ ├── integration_test.go
│ │ ├── performer.go
│ │ ├── performer_test.go
│ │ ├── scene.go
│ │ ├── scene_test.go
│ │ ├── studio.go
│ │ ├── studio_test.go
│ │ ├── tag.go
│ │ ├── tag_test.go
│ │ └── tagger.go
│ ├── build/
│ │ └── version.go
│ ├── desktop/
│ │ ├── desktop.go
│ │ ├── desktop_platform_darwin.go
│ │ ├── desktop_platform_nixes.go
│ │ ├── desktop_platform_windows.go
│ │ ├── dialog_nonwindows.go
│ │ ├── dialog_windows.go
│ │ ├── icon_windows.syso
│ │ ├── systray_nixes.go
│ │ └── systray_nonlinux.go
│ ├── dlna/
│ │ ├── activity.go
│ │ ├── activity_test.go
│ │ ├── cd-service-desc.go
│ │ ├── cds.go
│ │ ├── cds_test.go
│ │ ├── cm-service-desc.go
│ │ ├── cms.go
│ │ ├── dms.go
│ │ ├── doc.go
│ │ ├── html.go
│ │ ├── mrrs.go
│ │ ├── paging.go
│ │ ├── service.go
│ │ ├── whitelist.go
│ │ └── xmsr-service-desc.go
│ ├── identify/
│ │ ├── identify.go
│ │ ├── identify_test.go
│ │ ├── options.go
│ │ ├── performer.go
│ │ ├── performer_test.go
│ │ ├── scene.go
│ │ ├── scene_test.go
│ │ ├── studio.go
│ │ └── studio_test.go
│ ├── log/
│ │ ├── hook.go
│ │ ├── logger.go
│ │ └── progress_formatter.go
│ ├── manager/
│ │ ├── apikey.go
│ │ ├── backup.go
│ │ ├── checksum.go
│ │ ├── config/
│ │ │ ├── config.go
│ │ │ ├── config_concurrency_test.go
│ │ │ ├── config_test.go
│ │ │ ├── enums.go
│ │ │ ├── init.go
│ │ │ ├── stash_config.go
│ │ │ ├── tasks.go
│ │ │ └── ui.go
│ │ ├── downloads.go
│ │ ├── enums.go
│ │ ├── exclude_files.go
│ │ ├── exclude_files_test.go
│ │ ├── fingerprint.go
│ │ ├── generator.go
│ │ ├── generator_interactive_heatmap_speed.go
│ │ ├── generator_sprite.go
│ │ ├── import.go
│ │ ├── init.go
│ │ ├── json_utils.go
│ │ ├── log.go
│ │ ├── manager.go
│ │ ├── manager_tasks.go
│ │ ├── models.go
│ │ ├── repository.go
│ │ ├── running_streams.go
│ │ ├── scan_stashignore_test.go
│ │ ├── scene.go
│ │ ├── subscribe.go
│ │ ├── task/
│ │ │ ├── clean_generated.go
│ │ │ ├── download_ffmpeg.go
│ │ │ ├── migrate.go
│ │ │ ├── migrate_blobs.go
│ │ │ ├── migrate_scene_screenshots.go
│ │ │ └── packages.go
│ │ ├── task.go
│ │ ├── task_autotag.go
│ │ ├── task_clean.go
│ │ ├── task_export.go
│ │ ├── task_generate.go
│ │ ├── task_generate_clip_preview.go
│ │ ├── task_generate_image_phash.go
│ │ ├── task_generate_image_thumbnail.go
│ │ ├── task_generate_interactive_heatmap_speed.go
│ │ ├── task_generate_markers.go
│ │ ├── task_generate_phash.go
│ │ ├── task_generate_preview.go
│ │ ├── task_generate_screenshot.go
│ │ ├── task_generate_sprite.go
│ │ ├── task_identify.go
│ │ ├── task_import.go
│ │ ├── task_migrate_hash.go
│ │ ├── task_optimise.go
│ │ ├── task_plugin.go
│ │ ├── task_scan.go
│ │ ├── task_stash_box_tag.go
│ │ └── task_transcode.go
│ └── static/
│ ├── embed.go
│ ├── performer/
│ │ └── attribution.md
│ └── performer_male/
│ └── attribution.md
├── pkg/
│ ├── exec/
│ │ ├── command.go
│ │ ├── shell_nonwindows.go
│ │ └── shell_windows.go
│ ├── ffmpeg/
│ │ ├── browser.go
│ │ ├── codec.go
│ │ ├── codec_hardware.go
│ │ ├── container.go
│ │ ├── downloader.go
│ │ ├── ffmpeg.go
│ │ ├── ffmpeg_test.go
│ │ ├── ffprobe.go
│ │ ├── filter.go
│ │ ├── format.go
│ │ ├── frame_rate.go
│ │ ├── generate.go
│ │ ├── media_detection.go
│ │ ├── options.go
│ │ ├── stream.go
│ │ ├── stream_segmented.go
│ │ ├── stream_transcode.go
│ │ ├── transcoder/
│ │ │ ├── image.go
│ │ │ ├── screenshot.go
│ │ │ ├── splice.go
│ │ │ └── transcode.go
│ │ └── types.go
│ ├── file/
│ │ ├── clean.go
│ │ ├── delete.go
│ │ ├── file.go
│ │ ├── folder.go
│ │ ├── folder_rename_detect.go
│ │ ├── fs.go
│ │ ├── handler.go
│ │ ├── image/
│ │ │ ├── orientation.go
│ │ │ └── scan.go
│ │ ├── import.go
│ │ ├── move.go
│ │ ├── scan.go
│ │ ├── stashignore.go
│ │ ├── stashignore_test.go
│ │ ├── video/
│ │ │ ├── caption.go
│ │ │ ├── caption_test.go
│ │ │ ├── funscript.go
│ │ │ └── scan.go
│ │ ├── walk.go
│ │ └── zip.go
│ ├── fsutil/
│ │ ├── dir.go
│ │ ├── dir_test.go
│ │ ├── file.go
│ │ ├── file_test.go
│ │ ├── fs.go
│ │ ├── fs_test.go
│ │ ├── lock_manager.go
│ │ ├── symwalk.go
│ │ └── trash.go
│ ├── gallery/
│ │ ├── chapter_import.go
│ │ ├── delete.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── filter.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── scan.go
│ │ ├── scan_test.go
│ │ ├── service.go
│ │ ├── update.go
│ │ └── validation.go
│ ├── group/
│ │ ├── create.go
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── reorder.go
│ │ ├── service.go
│ │ ├── update.go
│ │ └── validate.go
│ ├── hash/
│ │ ├── imagephash/
│ │ │ └── phash.go
│ │ ├── key.go
│ │ ├── md5/
│ │ │ └── md5.go
│ │ ├── oshash/
│ │ │ ├── oshash.go
│ │ │ └── oshash_test.go
│ │ └── videophash/
│ │ └── phash.go
│ ├── image/
│ │ ├── delete.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── filter.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── scan.go
│ │ ├── scan_test.go
│ │ ├── service.go
│ │ ├── thumbnail.go
│ │ ├── update.go
│ │ ├── vips.go
│ │ ├── webp.go
│ │ └── webp_internal_test.go
│ ├── javascript/
│ │ ├── console.go
│ │ ├── gql.go
│ │ ├── log.go
│ │ ├── util.go
│ │ └── vm.go
│ ├── job/
│ │ ├── job.go
│ │ ├── manager.go
│ │ ├── manager_test.go
│ │ ├── progress.go
│ │ ├── progress_test.go
│ │ ├── subscribe.go
│ │ └── task.go
│ ├── logger/
│ │ ├── basic.go
│ │ ├── logger.go
│ │ ├── plugin.go
│ │ └── progress_formatter.go
│ ├── match/
│ │ ├── cache.go
│ │ ├── path.go
│ │ ├── path_test.go
│ │ └── scraped.go
│ ├── models/
│ │ ├── custom_fields.go
│ │ ├── date.go
│ │ ├── date_test.go
│ │ ├── doc.go
│ │ ├── errors.go
│ │ ├── file.go
│ │ ├── filename_parser.go
│ │ ├── filter.go
│ │ ├── find_filter.go
│ │ ├── fingerprint.go
│ │ ├── fingerprint_test.go
│ │ ├── folder.go
│ │ ├── fs.go
│ │ ├── gallery.go
│ │ ├── generate.go
│ │ ├── group.go
│ │ ├── image.go
│ │ ├── import.go
│ │ ├── json/
│ │ │ └── json_time.go
│ │ ├── jsonschema/
│ │ │ ├── doc.go
│ │ │ ├── file_folder.go
│ │ │ ├── folder.go
│ │ │ ├── gallery.go
│ │ │ ├── group.go
│ │ │ ├── image.go
│ │ │ ├── load.go
│ │ │ ├── performer.go
│ │ │ ├── performer_test.go
│ │ │ ├── saved_filter.go
│ │ │ ├── scene.go
│ │ │ ├── studio.go
│ │ │ ├── tag.go
│ │ │ └── utils.go
│ │ ├── mocks/
│ │ │ ├── FileReaderWriter.go
│ │ │ ├── FolderReaderWriter.go
│ │ │ ├── GalleryChapterReaderWriter.go
│ │ │ ├── GalleryReaderWriter.go
│ │ │ ├── GroupReaderWriter.go
│ │ │ ├── ImageReaderWriter.go
│ │ │ ├── PerformerReaderWriter.go
│ │ │ ├── SavedFilterReaderWriter.go
│ │ │ ├── SceneMarkerReaderWriter.go
│ │ │ ├── SceneReaderWriter.go
│ │ │ ├── StudioReaderWriter.go
│ │ │ ├── TagReaderWriter.go
│ │ │ ├── database.go
│ │ │ └── query.go
│ │ ├── model_file.go
│ │ ├── model_folder.go
│ │ ├── model_gallery.go
│ │ ├── model_gallery_chapter.go
│ │ ├── model_group.go
│ │ ├── model_image.go
│ │ ├── model_joins.go
│ │ ├── model_performer.go
│ │ ├── model_saved_filter.go
│ │ ├── model_scene.go
│ │ ├── model_scene_marker.go
│ │ ├── model_scene_test.go
│ │ ├── model_scraped_item.go
│ │ ├── model_scraped_item_test.go
│ │ ├── model_studio.go
│ │ ├── model_tag.go
│ │ ├── orientation.go
│ │ ├── package.go
│ │ ├── paths/
│ │ │ ├── paths.go
│ │ │ ├── paths_generated.go
│ │ │ ├── paths_json.go
│ │ │ ├── paths_scene_markers.go
│ │ │ └── paths_scenes.go
│ │ ├── performer.go
│ │ ├── query.go
│ │ ├── rating.go
│ │ ├── rating_test.go
│ │ ├── relationships.go
│ │ ├── repository.go
│ │ ├── repository_blob.go
│ │ ├── repository_file.go
│ │ ├── repository_folder.go
│ │ ├── repository_gallery.go
│ │ ├── repository_gallery_chapter.go
│ │ ├── repository_group.go
│ │ ├── repository_image.go
│ │ ├── repository_performer.go
│ │ ├── repository_scene.go
│ │ ├── repository_scene_marker.go
│ │ ├── repository_studio.go
│ │ ├── repository_tag.go
│ │ ├── resolution.go
│ │ ├── saved_filter.go
│ │ ├── scene.go
│ │ ├── scene_marker.go
│ │ ├── search.go
│ │ ├── search_test.go
│ │ ├── stash_box.go
│ │ ├── stash_ids.go
│ │ ├── studio.go
│ │ ├── tag.go
│ │ ├── update.go
│ │ ├── update_test.go
│ │ └── value.go
│ ├── performer/
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── url.go
│ │ ├── validate.go
│ │ └── validate_test.go
│ ├── pkg/
│ │ ├── cache.go
│ │ ├── manager.go
│ │ ├── pkg.go
│ │ ├── repository.go
│ │ ├── repository_http.go
│ │ ├── repository_http_test.go
│ │ └── store.go
│ ├── plugin/
│ │ ├── args.go
│ │ ├── common/
│ │ │ ├── doc.go
│ │ │ ├── log/
│ │ │ │ └── log.go
│ │ │ ├── msg.go
│ │ │ └── rpc.go
│ │ ├── config.go
│ │ ├── convert.go
│ │ ├── examples/
│ │ │ ├── README.md
│ │ │ ├── common/
│ │ │ │ └── graphql.go
│ │ │ ├── goraw/
│ │ │ │ ├── goraw.yml
│ │ │ │ └── main.go
│ │ │ ├── gorpc/
│ │ │ │ ├── gorpc.yml
│ │ │ │ └── main.go
│ │ │ ├── js/
│ │ │ │ ├── js.js
│ │ │ │ └── js.yml
│ │ │ ├── python/
│ │ │ │ ├── log.py
│ │ │ │ ├── pyplugin.py
│ │ │ │ ├── pyraw.yml
│ │ │ │ └── stash_interface.py
│ │ │ └── react-component/
│ │ │ ├── README.md
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ ├── testReact.scss
│ │ │ │ ├── testReact.tsx
│ │ │ │ └── testReact.yml
│ │ │ └── tsconfig.json
│ │ ├── hook/
│ │ │ └── hooks.go
│ │ ├── hooks.go
│ │ ├── js.go
│ │ ├── log.go
│ │ ├── plugins.go
│ │ ├── raw.go
│ │ ├── rpc.go
│ │ ├── setting.go
│ │ ├── task.go
│ │ └── util/
│ │ └── client.go
│ ├── python/
│ │ ├── env.go
│ │ └── exec.go
│ ├── savedfilter/
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ └── import_test.go
│ ├── scene/
│ │ ├── create.go
│ │ ├── delete.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── filename_parser.go
│ │ ├── filter.go
│ │ ├── find.go
│ │ ├── fingerprints.go
│ │ ├── generate/
│ │ │ ├── generator.go
│ │ │ ├── marker_preview.go
│ │ │ ├── preview.go
│ │ │ ├── screenshot.go
│ │ │ ├── sprite.go
│ │ │ └── transcode.go
│ │ ├── hash.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── marker_import.go
│ │ ├── marker_import_test.go
│ │ ├── marker_query.go
│ │ ├── merge.go
│ │ ├── migrate_hash.go
│ │ ├── migrate_screenshots.go
│ │ ├── query.go
│ │ ├── scan.go
│ │ ├── scan_test.go
│ │ ├── service.go
│ │ ├── update.go
│ │ └── update_test.go
│ ├── scraper/
│ │ ├── action.go
│ │ ├── autotag.go
│ │ ├── cache.go
│ │ ├── cookies.go
│ │ ├── country.go
│ │ ├── defined_scraper.go
│ │ ├── definition.go
│ │ ├── freeones.go
│ │ ├── graphql.go
│ │ ├── image.go
│ │ ├── json.go
│ │ ├── json_test.go
│ │ ├── mapped.go
│ │ ├── mapped_config.go
│ │ ├── mapped_postprocessing.go
│ │ ├── mapped_result.go
│ │ ├── mapped_result_test.go
│ │ ├── mapped_test.go
│ │ ├── movie.go
│ │ ├── performer.go
│ │ ├── post_processing_test.go
│ │ ├── postprocessing.go
│ │ ├── query_url.go
│ │ ├── scraper.go
│ │ ├── script.go
│ │ ├── stash.go
│ │ ├── tag.go
│ │ ├── url.go
│ │ ├── xpath.go
│ │ └── xpath_test.go
│ ├── session/
│ │ ├── authentication.go
│ │ ├── authentication_test.go
│ │ ├── config.go
│ │ ├── local.go
│ │ ├── plugin.go
│ │ └── session.go
│ ├── sliceutil/
│ │ ├── collections.go
│ │ ├── collections_test.go
│ │ ├── intslice/
│ │ │ └── int_collections.go
│ │ └── stringslice/
│ │ └── string_collections.go
│ ├── sqlite/
│ │ ├── anonymise.go
│ │ ├── anonymise_test.go
│ │ ├── batch.go
│ │ ├── blob/
│ │ │ └── fs.go
│ │ ├── blob.go
│ │ ├── blob_migrate.go
│ │ ├── blob_test.go
│ │ ├── common.go
│ │ ├── criterion_handlers.go
│ │ ├── custom_fields.go
│ │ ├── custom_fields_test.go
│ │ ├── custom_migrations.go
│ │ ├── database.go
│ │ ├── date.go
│ │ ├── doc.go
│ │ ├── driver.go
│ │ ├── file.go
│ │ ├── file_filter.go
│ │ ├── file_filter_test.go
│ │ ├── file_test.go
│ │ ├── filter.go
│ │ ├── filter_hierarchical.go
│ │ ├── filter_internal_test.go
│ │ ├── fingerprint.go
│ │ ├── folder.go
│ │ ├── folder_filter.go
│ │ ├── folder_filter_test.go
│ │ ├── folder_test.go
│ │ ├── functions.go
│ │ ├── gallery.go
│ │ ├── gallery_chapter.go
│ │ ├── gallery_chapter_test.go
│ │ ├── gallery_filter.go
│ │ ├── gallery_test.go
│ │ ├── group.go
│ │ ├── group_filter.go
│ │ ├── group_relationships.go
│ │ ├── group_test.go
│ │ ├── history.go
│ │ ├── image.go
│ │ ├── image_filter.go
│ │ ├── image_test.go
│ │ ├── migrate.go
│ │ ├── migrations/
│ │ │ ├── 10_image_tables.up.sql
│ │ │ ├── 11_tag_image.up.sql
│ │ │ ├── 12_oshash.up.sql
│ │ │ ├── 12_postmigrate.go
│ │ │ ├── 13_images.up.sql
│ │ │ ├── 14_stash_box_ids.up.sql
│ │ │ ├── 15_file_mod_time.up.sql
│ │ │ ├── 16_organized_flag.up.sql
│ │ │ ├── 17_reset_scene_size.up.sql
│ │ │ ├── 18_scene_galleries.up.sql
│ │ │ ├── 19_performer_tags.up.sql
│ │ │ ├── 1_initial.down.sql
│ │ │ ├── 1_initial.up.sql
│ │ │ ├── 20_phash.up.sql
│ │ │ ├── 21_performers_studios_details.up.sql
│ │ │ ├── 22_performers_studios_rating.up.sql
│ │ │ ├── 23_scenes_interactive.up.sql
│ │ │ ├── 24_tag_aliases.up.sql
│ │ │ ├── 25_saved_filters.up.sql
│ │ │ ├── 26_tag_hierarchy.up.sql
│ │ │ ├── 27_studio_aliases.up.sql
│ │ │ ├── 28_images_indexes.up.sql
│ │ │ ├── 29_interactive_speed.up.sql
│ │ │ ├── 2_cover_image.up.sql
│ │ │ ├── 30_ignore_autotag.up..sql
│ │ │ ├── 31_scenes_captions.up.sql
│ │ │ ├── 32_files.up.sql
│ │ │ ├── 32_postmigrate.go
│ │ │ ├── 32_premigrate.go
│ │ │ ├── 33_noop.up.sql
│ │ │ ├── 34_indexes.up.sql
│ │ │ ├── 34_postmigrate.go
│ │ │ ├── 35_assoc_tables.up.sql
│ │ │ ├── 36_tags_description.up.sql
│ │ │ ├── 37_iso_country_names.up.sql
│ │ │ ├── 38_scenes_director_code.up.sql
│ │ │ ├── 39_performer_height.up.sql
│ │ │ ├── 3_o_counter.up.sql
│ │ │ ├── 40_newratings.up.sql
│ │ │ ├── 41_scene_activity.up.sql
│ │ │ ├── 42_performer_disambig_aliases.up.sql
│ │ │ ├── 42_postmigrate.go
│ │ │ ├── 43_image_date_url.up.sql
│ │ │ ├── 44_gallery_chapters.up.sql
│ │ │ ├── 45_blobs.up.sql
│ │ │ ├── 45_postmigrate.go
│ │ │ ├── 46_penis_stats.up.sql
│ │ │ ├── 47_scene_urls.up.sql
│ │ │ ├── 48_cleanup.up.sql
│ │ │ ├── 48_premigrate.go
│ │ │ ├── 49_postmigrate.go
│ │ │ ├── 49_saved_filter_refactor.up.sql
│ │ │ ├── 4_movie.up.sql
│ │ │ ├── 50_image_urls.up.sql
│ │ │ ├── 51_gallery_urls.up.sql
│ │ │ ├── 52_postmigrate.go
│ │ │ ├── 52_zip_folder_data_correct.up.sql
│ │ │ ├── 53_gallery_photographer_code.up.sql
│ │ │ ├── 54_image_code_details_photographer.up.sql
│ │ │ ├── 55_manual_history.up.sql
│ │ │ ├── 55_postmigrate.go
│ │ │ ├── 56_studio_favorite.up.sql
│ │ │ ├── 57_tag_favorite.up.sql
│ │ │ ├── 58_config_correct.up.sql
│ │ │ ├── 58_postmigrate.go
│ │ │ ├── 59_movie_urls.up.sql
│ │ │ ├── 5_performer_gender.down.sql
│ │ │ ├── 5_performer_gender.up.sql
│ │ │ ├── 60_default_filter_move.up.sql
│ │ │ ├── 60_postmigrate.go
│ │ │ ├── 61_movie_tags.up.sql
│ │ │ ├── 62_performer_urls.up.sql
│ │ │ ├── 63_studio_tags.up.sql
│ │ │ ├── 64_fixes.up.sql
│ │ │ ├── 64_postmigrate.go
│ │ │ ├── 65_movie_group_rename.up.sql
│ │ │ ├── 65_postmigrate.go
│ │ │ ├── 66_gallery_cover.up.sql
│ │ │ ├── 67_group_relationships.up.sql
│ │ │ ├── 68_image_studio_index.up.sql
│ │ │ ├── 69_stash_id_updated_at.up.sql
│ │ │ ├── 6_scenes_format.up.sql
│ │ │ ├── 70_markers_end.up.sql
│ │ │ ├── 71_custom_fields.up.sql
│ │ │ ├── 72_tag_sort_name.up.sql
│ │ │ ├── 73_studio_urls.up.sql
│ │ │ ├── 74_tag_stash_ids.up.sql
│ │ │ ├── 75_date_precision.up.sql
│ │ │ ├── 76_studio_custom_fields.up.sql
│ │ │ ├── 77_tag_custom_fields.up.sql
│ │ │ ├── 78_performer_career_dates.up.sql
│ │ │ ├── 78_postmigrate.go
│ │ │ ├── 79_scene_custom_fields.up.sql
│ │ │ ├── 7_performer_optimization.up.sql
│ │ │ ├── 80_studio_organized.up.sql
│ │ │ ├── 81_gallery_custom_fields.up.sql
│ │ │ ├── 82_group_custom_fields.up.sql
│ │ │ ├── 83_image_custom_fields.up.sql
│ │ │ ├── 84_folder_basename.up.sql
│ │ │ ├── 84_postmigrate.go
│ │ │ ├── 85_performer_career_dates.up.sql
│ │ │ ├── 8_movie_fix.up.sql
│ │ │ ├── 9_studios_parent_studio.up.sql
│ │ │ ├── README.md
│ │ │ └── custom_migration.go
│ │ ├── performer.go
│ │ ├── performer_filter.go
│ │ ├── performer_test.go
│ │ ├── phash.go
│ │ ├── query.go
│ │ ├── record.go
│ │ ├── regex.go
│ │ ├── relationships.go
│ │ ├── repository.go
│ │ ├── saved_filter.go
│ │ ├── saved_filter_test.go
│ │ ├── scene.go
│ │ ├── scene_filter.go
│ │ ├── scene_marker.go
│ │ ├── scene_marker_filter.go
│ │ ├── scene_marker_test.go
│ │ ├── scene_test.go
│ │ ├── setup_test.go
│ │ ├── sql.go
│ │ ├── stash_id_test.go
│ │ ├── studio.go
│ │ ├── studio_filter.go
│ │ ├── studio_test.go
│ │ ├── table.go
│ │ ├── tables.go
│ │ ├── tag.go
│ │ ├── tag_filter.go
│ │ ├── tag_test.go
│ │ ├── timestamp.go
│ │ ├── transaction.go
│ │ ├── transaction_test.go
│ │ ├── tx.go
│ │ └── values.go
│ ├── stashbox/
│ │ ├── client.go
│ │ ├── draft.go
│ │ ├── graphql/
│ │ │ ├── generated_client.go
│ │ │ └── generated_models.go
│ │ ├── performer.go
│ │ ├── scene.go
│ │ ├── studio.go
│ │ └── tag.go
│ ├── studio/
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── validate.go
│ │ └── validate_test.go
│ ├── tag/
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── update.go
│ │ ├── update_test.go
│ │ ├── validate.go
│ │ └── validate_test.go
│ ├── txn/
│ │ ├── hooks.go
│ │ └── transaction.go
│ └── utils/
│ ├── boolean.go
│ ├── date.go
│ ├── date_test.go
│ ├── doc.go
│ ├── func.go
│ ├── http.go
│ ├── image.go
│ ├── map.go
│ ├── map_test.go
│ ├── mutex.go
│ ├── mutex_test.go
│ ├── phash.go
│ ├── reflect.go
│ ├── reflect_test.go
│ ├── resources.go
│ ├── strings.go
│ ├── strings_test.go
│ ├── time.go
│ ├── url.go
│ ├── url_test.go
│ ├── urlmap.go
│ ├── urlmap_test.go
│ ├── user_agent.go
│ ├── vtt.go
│ └── vtt_test.go
├── scripts/
│ ├── generateLoginLocales.go
│ ├── generate_icons.sh
│ ├── getDate.go
│ ├── macos-bundle/
│ │ └── Contents/
│ │ ├── Info.plist
│ │ └── Resources/
│ │ └── icon.icns
│ └── test_db_generator/
│ ├── README.md
│ ├── config.yml
│ ├── female.txt
│ ├── makeTestDB.go
│ ├── male.txt
│ ├── naming.go
│ ├── scene.txt
│ ├── studio.txt
│ └── surname.txt
├── tools.go
└── ui/
├── login/
│ ├── login.css
│ └── login.html
├── ui.go
└── v2.5/
├── .editorconfig
├── .eslintrc.json
├── .prettierignore
├── .stylelintrc
├── README.md
├── codegen.ts
├── graphql/
│ ├── client-schema.graphql
│ ├── data/
│ │ ├── config.graphql
│ │ ├── file.graphql
│ │ ├── filter.graphql
│ │ ├── gallery-chapter.graphql
│ │ ├── gallery-slim.graphql
│ │ ├── gallery.graphql
│ │ ├── group-slim.graphql
│ │ ├── group.graphql
│ │ ├── image-slim.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── log.graphql
│ │ ├── package.graphql
│ │ ├── performer-slim.graphql
│ │ ├── performer.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene-slim.graphql
│ │ ├── scene.graphql
│ │ ├── scrapers.graphql
│ │ ├── studio-slim.graphql
│ │ ├── studio.graphql
│ │ ├── tag-slim.graphql
│ │ └── tag.graphql
│ ├── mutations/
│ │ ├── config.graphql
│ │ ├── dlna.graphql
│ │ ├── file.graphql
│ │ ├── filter.graphql
│ │ ├── gallery-chapter.graphql
│ │ ├── gallery.graphql
│ │ ├── group.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── metadata.graphql
│ │ ├── migration.graphql
│ │ ├── performer.graphql
│ │ ├── plugins.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene.graphql
│ │ ├── scrapers.graphql
│ │ ├── stash-box.graphql
│ │ ├── studio.graphql
│ │ └── tag.graphql
│ ├── queries/
│ │ ├── dlna.graphql
│ │ ├── filter.graphql
│ │ ├── folder.graphql
│ │ ├── gallery.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── legacy.graphql
│ │ ├── misc.graphql
│ │ ├── movie.graphql
│ │ ├── performer.graphql
│ │ ├── plugins.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene.graphql
│ │ ├── scrapers/
│ │ │ └── scrapers.graphql
│ │ ├── settings/
│ │ │ ├── config.graphql
│ │ │ └── metadata.graphql
│ │ ├── studio.graphql
│ │ └── tag.graphql
│ └── subscriptions.graphql
├── index.html
├── package.json
├── pnpm-workspace.yaml
├── public/
│ └── manifest.json
├── src/
│ ├── @types/
│ │ ├── mousetrap-pause.d.ts
│ │ ├── string.prototype.replaceall.d.ts
│ │ ├── videojs-abloop.d.ts
│ │ ├── videojs-contrib-dash.d.ts
│ │ ├── videojs-vr.d.ts
│ │ └── videojs-vtt.d.ts
│ ├── App.tsx
│ ├── ConnectionMonitor.tsx
│ ├── components/
│ │ ├── Changelog/
│ │ │ ├── Changelog.tsx
│ │ │ ├── Version.tsx
│ │ │ └── styles.scss
│ │ ├── Dialogs/
│ │ │ ├── GenerateDialog.tsx
│ │ │ ├── IdentifyDialog/
│ │ │ │ ├── FieldOptions.tsx
│ │ │ │ ├── IdentifyDialog.tsx
│ │ │ │ ├── Options.tsx
│ │ │ │ ├── Sources.tsx
│ │ │ │ ├── ThreeStateBoolean.tsx
│ │ │ │ ├── constants.ts
│ │ │ │ └── styles.scss
│ │ │ ├── ReleaseNotesDialog.tsx
│ │ │ ├── SubmitDraft.tsx
│ │ │ └── styles.scss
│ │ ├── ErrorBoundary.tsx
│ │ ├── FrontPage/
│ │ │ ├── Control.tsx
│ │ │ ├── FilteredRecommendationRow.tsx
│ │ │ ├── FrontPage.tsx
│ │ │ ├── FrontPageConfig.tsx
│ │ │ ├── RecommendationRow.tsx
│ │ │ └── styles.scss
│ │ ├── Galleries/
│ │ │ ├── DeleteGalleriesDialog.tsx
│ │ │ ├── EditGalleriesDialog.tsx
│ │ │ ├── Galleries.tsx
│ │ │ ├── GalleryCard.tsx
│ │ │ ├── GalleryCardGrid.tsx
│ │ │ ├── GalleryDetails/
│ │ │ │ ├── ChapterEntry.tsx
│ │ │ │ ├── Gallery.tsx
│ │ │ │ ├── GalleryAddPanel.tsx
│ │ │ │ ├── GalleryChapterForm.tsx
│ │ │ │ ├── GalleryChaptersPanel.tsx
│ │ │ │ ├── GalleryCreate.tsx
│ │ │ │ ├── GalleryDetailPanel.tsx
│ │ │ │ ├── GalleryEditPanel.tsx
│ │ │ │ ├── GalleryFileInfoPanel.tsx
│ │ │ │ ├── GalleryImagesPanel.tsx
│ │ │ │ ├── GalleryScenesPanel.tsx
│ │ │ │ └── GalleryScrapeDialog.tsx
│ │ │ ├── GalleryList.tsx
│ │ │ ├── GalleryListTable.tsx
│ │ │ ├── GalleryPreviewScrubber.tsx
│ │ │ ├── GalleryRecommendationRow.tsx
│ │ │ ├── GallerySelect.tsx
│ │ │ ├── GalleryViewer.tsx
│ │ │ ├── GalleryWallCard.tsx
│ │ │ └── styles.scss
│ │ ├── Groups/
│ │ │ ├── ContainingGroupsMultiSet.tsx
│ │ │ ├── EditGroupsDialog.tsx
│ │ │ ├── GroupCard.tsx
│ │ │ ├── GroupCardGrid.tsx
│ │ │ ├── GroupDetails/
│ │ │ │ ├── AddGroupsDialog.tsx
│ │ │ │ ├── Group.tsx
│ │ │ │ ├── GroupCreate.tsx
│ │ │ │ ├── GroupDetailsPanel.tsx
│ │ │ │ ├── GroupEditPanel.tsx
│ │ │ │ ├── GroupPerformersPanel.tsx
│ │ │ │ ├── GroupScenesPanel.tsx
│ │ │ │ ├── GroupScrapeDialog.tsx
│ │ │ │ ├── GroupSubGroupsPanel.tsx
│ │ │ │ └── RelatedGroupTable.tsx
│ │ │ ├── GroupList.tsx
│ │ │ ├── GroupRecommendationRow.tsx
│ │ │ ├── GroupSelect.tsx
│ │ │ ├── GroupTag.tsx
│ │ │ ├── Groups.tsx
│ │ │ ├── RelatedGroupPopover.tsx
│ │ │ └── styles.scss
│ │ ├── Help/
│ │ │ ├── Manual.tsx
│ │ │ ├── context.tsx
│ │ │ └── styles.scss
│ │ ├── Images/
│ │ │ ├── DeleteImagesDialog.tsx
│ │ │ ├── EditImagesDialog.tsx
│ │ │ ├── ImageCard.tsx
│ │ │ ├── ImageCardGrid.tsx
│ │ │ ├── ImageDetails/
│ │ │ │ ├── Image.tsx
│ │ │ │ ├── ImageDetailPanel.tsx
│ │ │ │ ├── ImageEditPanel.tsx
│ │ │ │ ├── ImageFileInfoPanel.tsx
│ │ │ │ └── ImageScrapeDialog.tsx
│ │ │ ├── ImageList.tsx
│ │ │ ├── ImageRecommendationRow.tsx
│ │ │ ├── ImageWallItem.tsx
│ │ │ ├── Images.tsx
│ │ │ └── styles.scss
│ │ ├── List/
│ │ │ ├── CriterionEditor.tsx
│ │ │ ├── EditFilterDialog.tsx
│ │ │ ├── FilterProvider.tsx
│ │ │ ├── FilterTags.tsx
│ │ │ ├── FilteredListToolbar.tsx
│ │ │ ├── Filters/
│ │ │ │ ├── BooleanFilter.tsx
│ │ │ │ ├── CustomFieldsFilter.tsx
│ │ │ │ ├── DateFilter.tsx
│ │ │ │ ├── DuplicateFilter.tsx
│ │ │ │ ├── DurationFilter.tsx
│ │ │ │ ├── FilterButton.tsx
│ │ │ │ ├── FilterSidebar.tsx
│ │ │ │ ├── FolderFilter.tsx
│ │ │ │ ├── HierarchicalLabelValueFilter.tsx
│ │ │ │ ├── InputFilter.tsx
│ │ │ │ ├── LabeledIdFilter.tsx
│ │ │ │ ├── NumberFilter.tsx
│ │ │ │ ├── OptionFilter.tsx
│ │ │ │ ├── PathFilter.tsx
│ │ │ │ ├── PerformersFilter.tsx
│ │ │ │ ├── PhashFilter.tsx
│ │ │ │ ├── RatingFilter.tsx
│ │ │ │ ├── SelectableFilter.tsx
│ │ │ │ ├── SidebarAgeFilter.tsx
│ │ │ │ ├── SidebarDurationFilter.tsx
│ │ │ │ ├── SidebarListFilter.tsx
│ │ │ │ ├── StashIDFilter.tsx
│ │ │ │ ├── StudiosFilter.tsx
│ │ │ │ ├── TagsFilter.tsx
│ │ │ │ └── TimestampFilter.tsx
│ │ │ ├── ItemList.tsx
│ │ │ ├── ListFilter.tsx
│ │ │ ├── ListOperationButtons.tsx
│ │ │ ├── ListProvider.tsx
│ │ │ ├── ListTable.tsx
│ │ │ ├── ListViewOptions.tsx
│ │ │ ├── ModifierSelect.tsx
│ │ │ ├── PagedList.tsx
│ │ │ ├── Pagination.tsx
│ │ │ ├── SavedFilterList.tsx
│ │ │ ├── ZoomSlider.tsx
│ │ │ ├── styles.scss
│ │ │ ├── util.ts
│ │ │ └── views.ts
│ │ ├── MainNavbar.tsx
│ │ ├── PageNotFound.tsx
│ │ ├── Performers/
│ │ │ ├── EditPerformersDialog.tsx
│ │ │ ├── GenderIcon.tsx
│ │ │ ├── PerformerCard.tsx
│ │ │ ├── PerformerCardGrid.tsx
│ │ │ ├── PerformerDetails/
│ │ │ │ ├── Performer.tsx
│ │ │ │ ├── PerformerCreate.tsx
│ │ │ │ ├── PerformerDetailsPanel.tsx
│ │ │ │ ├── PerformerEditPanel.tsx
│ │ │ │ ├── PerformerGalleriesPanel.tsx
│ │ │ │ ├── PerformerGroupsPanel.tsx
│ │ │ │ ├── PerformerImagesPanel.tsx
│ │ │ │ ├── PerformerScenesPanel.tsx
│ │ │ │ ├── PerformerScrapeDialog.tsx
│ │ │ │ ├── PerformerScrapeModal.tsx
│ │ │ │ ├── PerformerStashBoxModal.tsx
│ │ │ │ ├── PerformerSubmitButton.tsx
│ │ │ │ └── performerAppearsWithPanel.tsx
│ │ │ ├── PerformerList.tsx
│ │ │ ├── PerformerListTable.tsx
│ │ │ ├── PerformerMergeDialog.tsx
│ │ │ ├── PerformerPopover.tsx
│ │ │ ├── PerformerRecommendationRow.tsx
│ │ │ ├── PerformerSelect.tsx
│ │ │ ├── Performers.tsx
│ │ │ └── styles.scss
│ │ ├── SceneDuplicateChecker/
│ │ │ ├── SceneDuplicateChecker.tsx
│ │ │ └── styles.scss
│ │ ├── SceneFilenameParser/
│ │ │ ├── ParserField.ts
│ │ │ ├── ParserInput.tsx
│ │ │ ├── SceneFilenameParser.tsx
│ │ │ ├── SceneParserRow.tsx
│ │ │ ├── ShowFields.tsx
│ │ │ └── styles.scss
│ │ ├── ScenePlayer/
│ │ │ ├── PlaylistButtons.ts
│ │ │ ├── ScenePlayer.tsx
│ │ │ ├── ScenePlayerScrubber.tsx
│ │ │ ├── autostart-button.ts
│ │ │ ├── big-buttons.ts
│ │ │ ├── live.ts
│ │ │ ├── markers.ts
│ │ │ ├── media-session.ts
│ │ │ ├── persist-volume.ts
│ │ │ ├── source-selector.ts
│ │ │ ├── styles.scss
│ │ │ ├── track-activity.ts
│ │ │ ├── util.ts
│ │ │ ├── vrmode.ts
│ │ │ ├── vtt-thumbnails.ts
│ │ │ └── wake-sentinel.ts
│ │ ├── Scenes/
│ │ │ ├── DeleteSceneMarkersDialog.tsx
│ │ │ ├── DeleteScenesDialog.tsx
│ │ │ ├── EditSceneMarkersDialog.tsx
│ │ │ ├── EditScenesDialog.tsx
│ │ │ ├── PreviewScrubber.tsx
│ │ │ ├── SceneCard.tsx
│ │ │ ├── SceneCardGrid.tsx
│ │ │ ├── SceneDetails/
│ │ │ │ ├── ExternalPlayerButton.tsx
│ │ │ │ ├── OCounterButton.tsx
│ │ │ │ ├── OrganizedButton.tsx
│ │ │ │ ├── PrimaryTags.tsx
│ │ │ │ ├── QueueViewer.tsx
│ │ │ │ ├── Scene.tsx
│ │ │ │ ├── SceneCreate.tsx
│ │ │ │ ├── SceneDetailPanel.tsx
│ │ │ │ ├── SceneEditPanel.tsx
│ │ │ │ ├── SceneFileInfoPanel.tsx
│ │ │ │ ├── SceneGalleriesPanel.tsx
│ │ │ │ ├── SceneGroupPanel.tsx
│ │ │ │ ├── SceneGroupTable.tsx
│ │ │ │ ├── SceneHistoryPanel.tsx
│ │ │ │ ├── SceneMarkerForm.tsx
│ │ │ │ ├── SceneMarkersPanel.tsx
│ │ │ │ ├── SceneQueryModal.tsx
│ │ │ │ ├── SceneScrapeDialog.tsx
│ │ │ │ └── SceneVideoFilterPanel.tsx
│ │ │ ├── SceneList.tsx
│ │ │ ├── SceneListTable.tsx
│ │ │ ├── SceneMarkerCard.tsx
│ │ │ ├── SceneMarkerCardGrid.tsx
│ │ │ ├── SceneMarkerList.tsx
│ │ │ ├── SceneMarkerRecommendationRow.tsx
│ │ │ ├── SceneMarkerWallPanel.tsx
│ │ │ ├── SceneMergeDialog.tsx
│ │ │ ├── SceneRecommendationRow.tsx
│ │ │ ├── SceneSelect.tsx
│ │ │ ├── SceneWallPanel.tsx
│ │ │ ├── Scenes.tsx
│ │ │ └── styles.scss
│ │ ├── Settings/
│ │ │ ├── GeneratePreviewOptions.tsx
│ │ │ ├── Inputs.tsx
│ │ │ ├── PluginPackageManager.tsx
│ │ │ ├── ScraperPackageManager.tsx
│ │ │ ├── SettingSection.tsx
│ │ │ ├── Settings.tsx
│ │ │ ├── SettingsAboutPanel.tsx
│ │ │ ├── SettingsInterfacePanel/
│ │ │ │ ├── CheckboxGroup.tsx
│ │ │ │ └── SettingsInterfacePanel.tsx
│ │ │ ├── SettingsLibraryPanel.tsx
│ │ │ ├── SettingsLogsPanel.tsx
│ │ │ ├── SettingsPluginsPanel.tsx
│ │ │ ├── SettingsScrapingPanel.tsx
│ │ │ ├── SettingsSecurityPanel.tsx
│ │ │ ├── SettingsServicesPanel.tsx
│ │ │ ├── SettingsSystemPanel.tsx
│ │ │ ├── SettingsToolsPanel.tsx
│ │ │ ├── StashBoxConfiguration.tsx
│ │ │ ├── StashConfiguration.tsx
│ │ │ ├── Tasks/
│ │ │ │ ├── CleanGeneratedDialog.tsx
│ │ │ │ ├── DataManagementTasks.tsx
│ │ │ │ ├── DirectorySelectionDialog.tsx
│ │ │ │ ├── GenerateOptions.tsx
│ │ │ │ ├── ImportDialog.tsx
│ │ │ │ ├── JobTable.tsx
│ │ │ │ ├── LibraryTasks.tsx
│ │ │ │ ├── PluginTasks.tsx
│ │ │ │ ├── ScanOptions.tsx
│ │ │ │ └── SettingsTasksPanel.tsx
│ │ │ ├── context.tsx
│ │ │ └── styles.scss
│ │ ├── SettingsButton.tsx
│ │ ├── Setup/
│ │ │ ├── Migrate.tsx
│ │ │ ├── Setup.tsx
│ │ │ └── styles.scss
│ │ ├── Shared/
│ │ │ ├── Alert.tsx
│ │ │ ├── BatchModals.tsx
│ │ │ ├── BulkUpdate.tsx
│ │ │ ├── ClearableInput.tsx
│ │ │ ├── CollapseButton.tsx
│ │ │ ├── CountButton.tsx
│ │ │ ├── Counter.tsx
│ │ │ ├── CountryFlag.tsx
│ │ │ ├── CountryLabel.tsx
│ │ │ ├── CountrySelect.tsx
│ │ │ ├── CustomFields.tsx
│ │ │ ├── Date.tsx
│ │ │ ├── DateInput.tsx
│ │ │ ├── DeleteEntityDialog.tsx
│ │ │ ├── DeleteFilesDialog.tsx
│ │ │ ├── DetailImage.tsx
│ │ │ ├── DetailItem.tsx
│ │ │ ├── DetailsEditNavbar.tsx
│ │ │ ├── DetailsPage/
│ │ │ │ ├── AliasList.tsx
│ │ │ │ ├── BackgroundImage.tsx
│ │ │ │ ├── DetailTitle.tsx
│ │ │ │ ├── HeaderImage.tsx
│ │ │ │ └── Tabs.tsx
│ │ │ ├── DoubleRangeInput.tsx
│ │ │ ├── DurationInput.tsx
│ │ │ ├── ErrorMessage.tsx
│ │ │ ├── ExportDialog.tsx
│ │ │ ├── ExternalLink.tsx
│ │ │ ├── ExternalLinksButton.tsx
│ │ │ ├── FavoriteIcon.tsx
│ │ │ ├── FileSize.tsx
│ │ │ ├── FilterSelect.tsx
│ │ │ ├── FolderSelect/
│ │ │ │ ├── FolderSelect.tsx
│ │ │ │ ├── FolderSelectDialog.tsx
│ │ │ │ └── useDirectoryPaths.ts
│ │ │ ├── GridCard/
│ │ │ │ ├── GridCard.tsx
│ │ │ │ ├── StudioOverlay.tsx
│ │ │ │ ├── dragMoveSelect.ts
│ │ │ │ └── styles.scss
│ │ │ ├── HoverPopover.tsx
│ │ │ ├── HoverScrubber.tsx
│ │ │ ├── Icon.tsx
│ │ │ ├── ImageInput.tsx
│ │ │ ├── ImageSelector.tsx
│ │ │ ├── IndeterminateCheckbox.tsx
│ │ │ ├── Link.tsx
│ │ │ ├── LoadingIndicator.tsx
│ │ │ ├── MarkdownPage.tsx
│ │ │ ├── Modal.tsx
│ │ │ ├── MultiSet.tsx
│ │ │ ├── OperationButton.tsx
│ │ │ ├── PackageManager/
│ │ │ │ ├── PackageManager.tsx
│ │ │ │ └── styles.scss
│ │ │ ├── PercentInput.tsx
│ │ │ ├── PerformerPopoverButton.tsx
│ │ │ ├── PopoverCountButton.tsx
│ │ │ ├── Rating/
│ │ │ │ ├── RatingNumber.tsx
│ │ │ │ ├── RatingStars.tsx
│ │ │ │ ├── RatingSystem.tsx
│ │ │ │ └── styles.scss
│ │ │ ├── RatingBanner.tsx
│ │ │ ├── ReassignFilesDialog.tsx
│ │ │ ├── RevealInFilesystemButton.tsx
│ │ │ ├── ScrapeDialog/
│ │ │ │ ├── CreateLinkTagDialog.tsx
│ │ │ │ ├── ScrapeDialog.tsx
│ │ │ │ ├── ScrapeDialogRow.tsx
│ │ │ │ ├── ScrapedObjectsRow.tsx
│ │ │ │ ├── createObjects.ts
│ │ │ │ ├── scrapeResult.ts
│ │ │ │ └── scrapedTags.tsx
│ │ │ ├── ScraperMenu.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ ├── StashBoxIDSearchModal.tsx
│ │ │ ├── StashID.tsx
│ │ │ ├── StringListInput.tsx
│ │ │ ├── SuccessIcon.tsx
│ │ │ ├── SweatDrops.tsx
│ │ │ ├── TagLink.tsx
│ │ │ ├── ThreeStateCheckbox.tsx
│ │ │ ├── TruncatedText.tsx
│ │ │ ├── URLField.tsx
│ │ │ └── styles.scss
│ │ ├── Stats.tsx
│ │ ├── Studios/
│ │ │ ├── EditStudiosDialog.tsx
│ │ │ ├── StudioCard.tsx
│ │ │ ├── StudioCardGrid.tsx
│ │ │ ├── StudioDetails/
│ │ │ │ ├── Studio.tsx
│ │ │ │ ├── StudioChildrenPanel.tsx
│ │ │ │ ├── StudioCreate.tsx
│ │ │ │ ├── StudioDetailsPanel.tsx
│ │ │ │ ├── StudioEditPanel.tsx
│ │ │ │ ├── StudioGalleriesPanel.tsx
│ │ │ │ ├── StudioGroupsPanel.tsx
│ │ │ │ ├── StudioImagesPanel.tsx
│ │ │ │ ├── StudioPerformersPanel.tsx
│ │ │ │ └── StudioScenesPanel.tsx
│ │ │ ├── StudioList.tsx
│ │ │ ├── StudioRecommendationRow.tsx
│ │ │ ├── StudioSelect.tsx
│ │ │ ├── Studios.tsx
│ │ │ └── styles.scss
│ │ ├── Tagger/
│ │ │ ├── FieldSelector.tsx
│ │ │ ├── IncludeButton.tsx
│ │ │ ├── LinkButton.tsx
│ │ │ ├── PerformerModal.tsx
│ │ │ ├── StashBoxSelector.tsx
│ │ │ ├── TaggerConfig.tsx
│ │ │ ├── config.ts
│ │ │ ├── constants.ts
│ │ │ ├── context.tsx
│ │ │ ├── performers/
│ │ │ │ ├── PerformerTagger.tsx
│ │ │ │ └── StashSearchResult.tsx
│ │ │ ├── queries.ts
│ │ │ ├── scenes/
│ │ │ │ ├── Config.tsx
│ │ │ │ ├── PerformerResult.tsx
│ │ │ │ ├── SceneTagger.tsx
│ │ │ │ ├── StashSearchResult.tsx
│ │ │ │ ├── StudioModal.tsx
│ │ │ │ ├── StudioResult.tsx
│ │ │ │ ├── TaggerScene.tsx
│ │ │ │ ├── sceneTaggerModals.tsx
│ │ │ │ └── utils.ts
│ │ │ ├── studios/
│ │ │ │ ├── StashSearchResult.tsx
│ │ │ │ └── StudioTagger.tsx
│ │ │ ├── styles.scss
│ │ │ ├── tags/
│ │ │ │ ├── StashSearchResult.tsx
│ │ │ │ ├── TagModal.tsx
│ │ │ │ └── TagTagger.tsx
│ │ │ └── utils.ts
│ │ ├── Tags/
│ │ │ ├── EditTagsDialog.tsx
│ │ │ ├── TagCard.tsx
│ │ │ ├── TagCardGrid.tsx
│ │ │ ├── TagDetails/
│ │ │ │ ├── Tag.tsx
│ │ │ │ ├── TagCreate.tsx
│ │ │ │ ├── TagDetailsPanel.tsx
│ │ │ │ ├── TagEditPanel.tsx
│ │ │ │ ├── TagGalleriesPanel.tsx
│ │ │ │ ├── TagGroupsPanel.tsx
│ │ │ │ ├── TagImagesPanel.tsx
│ │ │ │ ├── TagMarkersPanel.tsx
│ │ │ │ ├── TagPerformersPanel.tsx
│ │ │ │ ├── TagScenesPanel.tsx
│ │ │ │ └── TagStudiosPanel.tsx
│ │ │ ├── TagList.tsx
│ │ │ ├── TagListTable.tsx
│ │ │ ├── TagMergeDialog.tsx
│ │ │ ├── TagPopover.tsx
│ │ │ ├── TagRecommendationRow.tsx
│ │ │ ├── TagSelect.tsx
│ │ │ ├── Tags.tsx
│ │ │ └── styles.scss
│ │ ├── TroubleshootingMode/
│ │ │ ├── TroubleshootingModeButton.tsx
│ │ │ ├── TroubleshootingModeOverlay.tsx
│ │ │ └── useTroubleshootingMode.ts
│ │ └── Wall/
│ │ ├── WallItem.tsx
│ │ ├── WallPanel.tsx
│ │ └── styles.scss
│ ├── core/
│ │ ├── StashService.ts
│ │ ├── config.ts
│ │ ├── createClient.ts
│ │ ├── enums.ts
│ │ ├── files.ts
│ │ ├── galleries.ts
│ │ ├── groups.ts
│ │ ├── markers.ts
│ │ ├── performers.ts
│ │ ├── recommendations.ts
│ │ ├── studios.ts
│ │ └── tags.ts
│ ├── docs/
│ │ └── en/
│ │ ├── Changelog/
│ │ │ ├── v010.md
│ │ │ ├── v0100.md
│ │ │ ├── v011.md
│ │ │ ├── v0110.md
│ │ │ ├── v0120.md
│ │ │ ├── v0130.md
│ │ │ ├── v0131.md
│ │ │ ├── v0140.md
│ │ │ ├── v0150.md
│ │ │ ├── v0160.md
│ │ │ ├── v0161.md
│ │ │ ├── v0170.md
│ │ │ ├── v0180.md
│ │ │ ├── v0190.md
│ │ │ ├── v020.md
│ │ │ ├── v0200.md
│ │ │ ├── v021.md
│ │ │ ├── v0210.md
│ │ │ ├── v0220.md
│ │ │ ├── v0230.md
│ │ │ ├── v0240.md
│ │ │ ├── v0250.md
│ │ │ ├── v0260.md
│ │ │ ├── v0270.md
│ │ │ ├── v0280.md
│ │ │ ├── v0290.md
│ │ │ ├── v030.md
│ │ │ ├── v0300.md
│ │ │ ├── v0310.md
│ │ │ ├── v040.md
│ │ │ ├── v050.md
│ │ │ ├── v060.md
│ │ │ ├── v070.md
│ │ │ ├── v080.md
│ │ │ └── v090.md
│ │ ├── Manual/
│ │ │ ├── AutoTagging.md
│ │ │ ├── Browsing.md
│ │ │ ├── Captions.md
│ │ │ ├── Configuration.md
│ │ │ ├── Contributing.md
│ │ │ ├── Deduplication.md
│ │ │ ├── EmbeddedPlugins.md
│ │ │ ├── ExternalPlugins.md
│ │ │ ├── Help.md
│ │ │ ├── Identify.md
│ │ │ ├── Images.md
│ │ │ ├── Interactive.md
│ │ │ ├── Interface.md
│ │ │ ├── Introduction.md
│ │ │ ├── JSONSpec.md
│ │ │ ├── KeyboardShortcuts.md
│ │ │ ├── Plugins.md
│ │ │ ├── SceneFilenameParser.md
│ │ │ ├── ScraperDevelopment.md
│ │ │ ├── Scraping.md
│ │ │ ├── Tagger.md
│ │ │ ├── Tasks.md
│ │ │ ├── TroubleshootingMode.md
│ │ │ └── UIPluginApi.md
│ │ ├── MigrationNotes/
│ │ │ ├── 32.md
│ │ │ ├── 39.md
│ │ │ ├── 48.md
│ │ │ ├── 58.md
│ │ │ ├── 60.md
│ │ │ └── index.ts
│ │ └── ReleaseNotes/
│ │ ├── index.ts
│ │ ├── v0170.md
│ │ ├── v0200.md
│ │ ├── v0240.md
│ │ ├── v0250.md
│ │ ├── v0260.md
│ │ ├── v0270.md
│ │ └── v0290.md
│ ├── globals.d.ts
│ ├── hooks/
│ │ ├── Config.tsx
│ │ ├── Interactive/
│ │ │ ├── context.tsx
│ │ │ ├── interactive.scss
│ │ │ ├── interactive.ts
│ │ │ ├── status.tsx
│ │ │ └── utils.ts
│ │ ├── Interval.ts
│ │ ├── Lightbox/
│ │ │ ├── Lightbox.tsx
│ │ │ ├── LightboxImage.tsx
│ │ │ ├── LightboxLink.tsx
│ │ │ ├── context.tsx
│ │ │ ├── hooks.ts
│ │ │ ├── lightbox.scss
│ │ │ └── types.ts
│ │ ├── LocalForage.ts
│ │ ├── OutsideClick.tsx
│ │ ├── PageVisibility.ts
│ │ ├── Toast.tsx
│ │ ├── data.ts
│ │ ├── debounce.ts
│ │ ├── detailsPanel.ts
│ │ ├── event.ts
│ │ ├── keybinds.ts
│ │ ├── modal.ts
│ │ ├── scrollToTop.ts
│ │ ├── sprite.ts
│ │ ├── state.ts
│ │ ├── tagsEdit.tsx
│ │ ├── throttle.ts
│ │ ├── title.ts
│ │ ├── useScript.tsx
│ │ └── useTableColumns.ts
│ ├── index.scss
│ ├── index.tsx
│ ├── locales/
│ │ ├── README.md
│ │ ├── af-ZA.json
│ │ ├── ar.json
│ │ ├── bg-BG.json
│ │ ├── bn-BD.json
│ │ ├── ca-ES.json
│ │ ├── countryNames/
│ │ │ └── zh-TW.json
│ │ ├── cs-CZ.json
│ │ ├── da-DK.json
│ │ ├── de-DE.json
│ │ ├── en-GB.json
│ │ ├── en-US.json
│ │ ├── es-ES.json
│ │ ├── et-EE.json
│ │ ├── fa-IR.json
│ │ ├── fi-FI.json
│ │ ├── fr-FR.json
│ │ ├── hi-IN.json
│ │ ├── hr-HR.json
│ │ ├── hu-HU.json
│ │ ├── id-ID.json
│ │ ├── index.ts
│ │ ├── it-IT.json
│ │ ├── ja-JP.json
│ │ ├── ko-KR.json
│ │ ├── lt-LT.json
│ │ ├── lv-LV.json
│ │ ├── nb-NO.json
│ │ ├── ne-NP.json
│ │ ├── nl-NL.json
│ │ ├── nn-NO.json
│ │ ├── pl-PL.json
│ │ ├── pt-BR.json
│ │ ├── ro-RO.json
│ │ ├── ru-RU.json
│ │ ├── sk-SK.json
│ │ ├── sv-SE.json
│ │ ├── th-TH.json
│ │ ├── tr-TR.json
│ │ ├── uk-UA.json
│ │ ├── ur-PK.json
│ │ ├── vi-VN.json
│ │ ├── zh-CN.json
│ │ └── zh-TW.json
│ ├── models/
│ │ ├── list-filter/
│ │ │ ├── criteria/
│ │ │ │ ├── captions.ts
│ │ │ │ ├── circumcised.ts
│ │ │ │ ├── country.ts
│ │ │ │ ├── criterion.ts
│ │ │ │ ├── custom-fields.ts
│ │ │ │ ├── favorite.ts
│ │ │ │ ├── folder.ts
│ │ │ │ ├── galleries.ts
│ │ │ │ ├── gender.ts
│ │ │ │ ├── groups.ts
│ │ │ │ ├── has-chapters.ts
│ │ │ │ ├── has-markers.ts
│ │ │ │ ├── interactive.ts
│ │ │ │ ├── is-missing.ts
│ │ │ │ ├── organized.ts
│ │ │ │ ├── orientation.ts
│ │ │ │ ├── path.ts
│ │ │ │ ├── performers.ts
│ │ │ │ ├── phash.ts
│ │ │ │ ├── rating.ts
│ │ │ │ ├── resolution.ts
│ │ │ │ ├── scenes.ts
│ │ │ │ ├── stash-ids.ts
│ │ │ │ ├── studios.ts
│ │ │ │ └── tags.ts
│ │ │ ├── factory.ts
│ │ │ ├── filter-options.ts
│ │ │ ├── filter.ts
│ │ │ ├── galleries.ts
│ │ │ ├── groups.ts
│ │ │ ├── images.ts
│ │ │ ├── performers.ts
│ │ │ ├── scene-markers.ts
│ │ │ ├── scenes.ts
│ │ │ ├── studios.ts
│ │ │ ├── tags.ts
│ │ │ ├── types.ts
│ │ │ └── utils.ts
│ │ └── sceneQueue.ts
│ ├── patch.tsx
│ ├── pluginApi.d.ts
│ ├── pluginApi.tsx
│ ├── plugins.tsx
│ ├── polyfills.ts
│ ├── serviceWorker.ts
│ ├── sfw-mode.scss
│ ├── styles/
│ │ ├── _range.scss
│ │ ├── _scrollbars.scss
│ │ └── _theme.scss
│ └── utils/
│ ├── apple.ts
│ ├── bulkUpdate.ts
│ ├── caption.ts
│ ├── circumcised.ts
│ ├── country.ts
│ ├── data.ts
│ ├── dlnaVideoSort.ts
│ ├── download.ts
│ ├── errors.ts
│ ├── field.tsx
│ ├── flattenMessages.ts
│ ├── focus.ts
│ ├── form.tsx
│ ├── gender.ts
│ ├── hamming.ts
│ ├── history.ts
│ ├── image.tsx
│ ├── imageWall.ts
│ ├── index.ts
│ ├── job.ts
│ ├── keyboard.ts
│ ├── lazyComponent.ts
│ ├── navigation.ts
│ ├── orientation.ts
│ ├── percent.ts
│ ├── query.ts
│ ├── rating.ts
│ ├── resolution.ts
│ ├── screen.ts
│ ├── session.ts
│ ├── stashIds.ts
│ ├── stashbox.ts
│ ├── text.ts
│ ├── units.ts
│ ├── visualFile.ts
│ └── yup.ts
├── tsconfig.json
└── vite.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
####
# Go
####
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# GraphQL generated output
pkg/models/generated_*.go
ui/v2.5/src/core/generated-graphql.ts
####
# Jetbrains
####
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
####
# Random
####
ui/v2.5/node_modules
ui/v2.5/build
*.db
stash
dist
docker
================================================
FILE: .gitattributes
================================================
go.mod text eol=lf
go.sum text eol=lf
*.go text eol=lf
vendor/** -text
ui/v2.5/**/*.ts* text eol=lf
ui/v2.5/**/*.scss text eol=lf
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: Create a report to help us fix the bug
labels: ["bug report"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: description
attributes:
label: Describe the bug
description: Provide a clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to reproduce
description: Detail the steps that would replicate this issue.
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behaviour
description: Provide clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: context
attributes:
label: Screenshots or additional context
description: Provide any additional context and SFW screenshots here to help us solve this issue.
validations:
required: false
- type: input
id: stashversion
attributes:
label: Stash version
description: This can be found in Settings > About.
placeholder: (e.g. v0.28.1)
validations:
required: true
- type: input
id: devicedetails
attributes:
label: Device details
description: |
If this is an issue that occurs when using the Stash interface, please provide details of the device/browser used which presents the reported issue.
placeholder: (e.g. Firefox 97 (64-bit) on Windows 11)
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output from Settings > Logs. This will be automatically formatted into code, so no need for backticks.
render: shell
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Community forum
url: https://discourse.stashapp.cc
about: Start a discussion on the community forum.
- name: Community Discord
url: https://discord.gg/Y8MNsvQBvZ
about: Chat with the community on Discord.
- name: Documentation
url: https://docs.stashapp.cc
about: Check out documentation for help and information.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: Request a new feature or idea to be added to Stash
labels: ["feature request"]
body:
- type: textarea
id: description
attributes:
label: Describe the feature you'd like
description: Provide a clear description of the feature you'd like implemented
validations:
required: true
- type: textarea
id: benefits
attributes:
label: Describe the benefits this would bring to existing users
description: |
Explain the measurable benefits this feature would achieve for existing users.
The benefits should be described in terms of outcomes for users, not specific implementations.
validations:
required: true
- type: textarea
id: already_possible
attributes:
label: Is there an existing way to achieve this goal?
description: |
Yes/No. If Yes, describe how your proposed feature differs from or improves upon the current method
validations:
required: true
- type: checkboxes
id: confirm-search
attributes:
label: Have you searched for an existing open/closed issue?
description: |
To help us keep these issues under control, please ensure you have first [searched our issue list](https://github.com/stashapp/stash/issues?q=is%3Aissue) for any existing issues that cover the core request or benefit of your proposal.
options:
- label: I have searched for existing issues and none cover the core request of my proposal
required: true
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
validations:
required: false
================================================
FILE: .github/PULL_REQUEST_TEMPLATE/BugFix.md
================================================
---
name: Bug Fix
about: Add a bug fix this project!
title: "[Bug Fix] Short Form Title (50 chars or less.)"
labels: bug
assignees: 'WithoutPants, bnkai, Leopere'
---
<!-- Please make sure to read https://github.com/stashapp/stash/docs/CONTRIBUTING.md and check that you understand and have followed it as best as possible -->
<!-- Explain what your bugfix seeks to remedy in a short paragraph. -->
# Scope
<!-- Declare any issues by typing `fixes #1` or `closes #1` for example so that the automation can kick in when this is merged -->
## Closes/Fixes Issues
<!-- What have you tested specifically and what possible impacts/areas there are that may need retesting by others. -->
## Other testing QA Notes
================================================
FILE: .github/PULL_REQUEST_TEMPLATE/Feature.md
================================================
---
name: Feature Addition
about: Add a feature to this project!
title: "[Feature] Short Form Title (50 chars or less.)"
labels: enhancement
assignees: 'WithoutPants, bnkai, Leopere'
---
<!-- Please make sure to read https://github.com/stashapp/stash/docs/CONTRIBUTING.md and check that you understand and have followed it as best as possible
Explain what your feature does in a short paragraph. -->
# Scope
<!-- Declare any issues by typing `fixes #1` or `closes #1` for example so that the automation can kick in when this is merged -->
## Closes/Fixes Issues
<!-- What have you tested specifically and what possible impacts/areas there are that may need retesting by others. -->
## Other testing QA Notes
================================================
FILE: .github/workflows/build-compiler.yml
================================================
name: Compiler Build
on:
workflow_dispatch:
env:
COMPILER_IMAGE: ghcr.io/stashapp/compiler:13
jobs:
build-compiler:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
push: true
context: "{{defaultContext}}:docker/compiler"
tags: |
${{ env.COMPILER_IMAGE }}
ghcr.io/stashapp/compiler:latest
cache-from: type=gha,scope=all,mode=max
cache-to: type=gha,scope=all,mode=max
================================================
FILE: .github/workflows/build.yml
================================================
name: Build
on:
push:
branches:
- develop
- master
- 'releases/**'
pull_request:
release:
types: [ published ]
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
env:
COMPILER_IMAGE: ghcr.io/stashapp/compiler:13
jobs:
# Job 1: Generate code and build UI
# Runs natively (no Docker) — go generate/gqlgen and node don't need cross-compilers.
# Produces artifacts (generated Go files + UI build) consumed by test and build jobs.
generate:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
# pnpm version is read from the packageManager field in package.json
# very broken (4.3, 4.4)
- name: Install pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061
with:
package_json_file: ui/v2.5/package.json
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'pnpm'
cache-dependency-path: ui/v2.5/pnpm-lock.yaml
- name: Install UI dependencies
run: cd ui/v2.5 && pnpm install --frozen-lockfile
- name: Generate
run: make generate
- name: Cache UI build
uses: actions/cache@v5
id: cache-ui
with:
path: ui/v2.5/build
key: ${{ runner.os }}-ui-build-${{ hashFiles('ui/v2.5/pnpm-lock.yaml', 'ui/v2.5/public/**', 'ui/v2.5/src/**', 'graphql/**/*.graphql') }}
- name: Validate UI
# skip UI validation for pull requests if UI is unchanged
if: ${{ github.event_name != 'pull_request' || steps.cache-ui.outputs.cache-hit != 'true' }}
run: make validate-ui
- name: Build UI
# skip UI build for pull requests if UI is unchanged (UI was cached)
if: ${{ github.event_name != 'pull_request' || steps.cache-ui.outputs.cache-hit != 'true' }}
run: make ui
# Bundle generated Go files + UI build for downstream jobs (test + build)
- name: Upload generated artifacts
uses: actions/upload-artifact@v7
with:
name: generated
retention-days: 1
path: |
internal/api/generated_exec.go
internal/api/generated_models.go
ui/v2.5/build/
ui/login/locales/
# Job 2: Integration tests
# Runs natively (no Docker) — only needs Go + GCC (for CGO/SQLite), both on ubuntu-22.04.
# Runs in parallel with the build matrix jobs.
test:
needs: generate
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
# Places generated Go files + UI build into the working tree so the build compiles
- name: Download generated artifacts
uses: actions/download-artifact@v8
with:
name: generated
- name: Test Backend
run: make it
# Job 3: Cross-compile for all platforms
# Each platform gets its own runner and Docker container (ghcr.io/stashapp/compiler:13).
# Each build-cc-* make target is self-contained (sets its own GOOS/GOARCH/CC),
# so running them in separate containers is functionally identical to one container.
# Runs in parallel with the test job.
build:
needs: generate
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- platform: windows
make-target: build-cc-windows
artifact-paths: |
dist/stash-win.exe
tag: win
- platform: macos
make-target: build-cc-macos
artifact-paths: |
dist/stash-macos
dist/Stash.app.zip
tag: osx
- platform: linux
make-target: build-cc-linux
artifact-paths: |
dist/stash-linux
tag: linux
- platform: linux-arm64v8
make-target: build-cc-linux-arm64v8
artifact-paths: |
dist/stash-linux-arm64v8
tag: arm
- platform: linux-arm32v7
make-target: build-cc-linux-arm32v7
artifact-paths: |
dist/stash-linux-arm32v7
tag: arm
- platform: linux-arm32v6
make-target: build-cc-linux-arm32v6
artifact-paths: |
dist/stash-linux-arm32v6
tag: arm
- platform: freebsd
make-target: build-cc-freebsd
artifact-paths: |
dist/stash-freebsd
tag: freebsd
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
fetch-tags: true
- name: Download generated artifacts
uses: actions/download-artifact@v8
with:
name: generated
- name: Cache Go build
uses: actions/cache@v5
with:
path: .go-cache
key: ${{ runner.os }}-go-cache-${{ matrix.platform }}-${{ hashFiles('go.mod', '**/go.sum') }}
# kept seperate to test timings
- name: pull compiler image
run: docker pull $COMPILER_IMAGE
- name: Start build container
env:
official-build: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/develop') || (github.event_name == 'release' && github.ref != 'refs/tags/latest_develop') }}
run: |
mkdir -p .go-cache
docker run -d --name build --mount type=bind,source="$(pwd)",target=/stash,consistency=delegated --mount type=bind,source="$(pwd)/.go-cache",target=/root/.cache/go-build,consistency=delegated --env OFFICIAL_BUILD=${{ env.official-build }} -w /stash $COMPILER_IMAGE tail -f /dev/null
- name: Build (${{ matrix.platform }})
run: docker exec -t build /bin/bash -c "make ${{ matrix.make-target }}"
- name: Cleanup build container
run: docker rm -f -v build
- name: Upload build artifact
uses: actions/upload-artifact@v7
with:
name: build-${{ matrix.platform }}
retention-days: 1
path: ${{ matrix.artifact-paths }}
# Job 4: Release
# Waits for both test and build to pass, then collects all platform artifacts
# into dist/ for checksums, GitHub releases, and multi-arch Docker push.
release:
needs: [test, build]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
# Downloads all artifacts (generated + 7 platform builds) into artifacts/ subdirectories
- name: Download all build artifacts
uses: actions/download-artifact@v8
with:
path: artifacts
# Reassemble platform binaries from matrix job artifacts into a single dist/ directory
# make sure that artifacts have executable bit set
# upload-artifact@v4 strips the common path prefix (dist/), so files are at the artifact root
- name: Collect binaries
run: |
mkdir -p dist
cp artifacts/build-*/* dist/
chmod +x dist/*
- name: Zip UI
run: |
cd artifacts/generated/ui/v2.5/build && zip -r ../../../../../dist/stash-ui.zip .
- name: Generate checksums
run: |
git describe --tags --exclude latest_develop | tee CHECKSUMS_SHA1
sha1sum dist/Stash.app.zip dist/stash-* dist/stash-ui.zip | sed 's/dist\///g' | tee -a CHECKSUMS_SHA1
echo "STASH_VERSION=$(git describe --tags --exclude latest_develop)" >> $GITHUB_ENV
echo "RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S %Z')" >> $GITHUB_ENV
- name: Upload Windows binary
# only upload binaries for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v7
with:
name: stash-win.exe
path: dist/stash-win.exe
- name: Upload macOS binary
# only upload binaries for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v7
with:
name: stash-macos
path: dist/stash-macos
- name: Upload Linux binary
# only upload binaries for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v7
with:
name: stash-linux
path: dist/stash-linux
- name: Upload UI
# only upload for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v7
with:
name: stash-ui.zip
path: dist/stash-ui.zip
- name: Update latest_develop tag
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
run: git tag -f latest_develop; git push -f --tags
- name: Development Release
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
uses: marvinpinto/action-automatic-releases@v1.1.2
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true
automatic_release_tag: latest_develop
title: "${{ env.STASH_VERSION }}: Latest development build"
files: |
dist/Stash.app.zip
dist/stash-macos
dist/stash-win.exe
dist/stash-linux
dist/stash-linux-arm64v8
dist/stash-linux-arm32v7
dist/stash-linux-arm32v6
dist/stash-freebsd
dist/stash-ui.zip
CHECKSUMS_SHA1
- name: Master release
# NOTE: this isn't perfect, but should cover most scenarios
# DON'T create tag names starting with "v" if they are not stable releases
if: ${{ github.event_name == 'release' && startsWith(github.ref, 'refs/tags/v') }}
uses: WithoutPants/github-release@v2.0.4
with:
token: "${{ secrets.GITHUB_TOKEN }}"
allow_override: true
files: |
dist/Stash.app.zip
dist/stash-macos
dist/stash-win.exe
dist/stash-linux
dist/stash-linux-arm64v8
dist/stash-linux-arm32v7
dist/stash-linux-arm32v6
dist/stash-freebsd
dist/stash-ui.zip
CHECKSUMS_SHA1
gzip: false
- name: Development Docker
if: ${{ github.repository == 'stashapp/stash' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
env:
DOCKER_CLI_EXPERIMENTAL: enabled
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
docker run --rm --privileged tonistiigi/binfmt
docker info
docker buildx create --name builder --use
docker buildx inspect --bootstrap
docker buildx ls
bash ./docker/ci/x86_64/docker_push.sh development
- name: Release Docker
# NOTE: this isn't perfect, but should cover most scenarios
# DON'T create tag names starting with "v" if they are not stable releases
if: ${{ github.repository == 'stashapp/stash' && github.event_name == 'release' && startsWith(github.ref, 'refs/tags/v') }}
env:
DOCKER_CLI_EXPERIMENTAL: enabled
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
docker run --rm --privileged tonistiigi/binfmt
docker info
docker buildx create --name builder --use
docker buildx inspect --bootstrap
docker buildx ls
bash ./docker/ci/x86_64/docker_push.sh latest "${{ github.event.release.tag_name }}"
================================================
FILE: .github/workflows/golangci-lint.yml
================================================
name: Lint (golangci-lint)
on:
push:
tags:
- v*
branches:
- master
- develop
- 'releases/**'
pull_request:
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
# no tags or depth needed for lint
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
# generate-backend runs natively (just go generate + touch-ui) — no Docker needed
- name: Generate Backend
run: make generate-backend
## WARN
## using v1, update in a later PR
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
================================================
FILE: .gitignore
================================================
####
# Go
####
# Vendored dependencies
vendor
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# GraphQL generated output
internal/api/generated_*.go
# Generated locale files
ui/login/locales/*
####
# Visual Studio
####
/.vs
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
.vscode
.devcontainer
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
####
# Random
####
node_modules
*.db
/stash
/Stash.app
/phasher
dist
.DS_Store
/.local*
================================================
FILE: .golangci.yml
================================================
# options for analysis running
run:
timeout: 5m
linters:
disable-all: true
enable:
# Default set of linters from golangci-lint
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
# Linters added by the stash project.
# - contextcheck
- copyloopvar
- dogsled
- errchkjson
- errorlint
# - exhaustive
- gocritic
# - goerr113
- gofmt
# - gomnd
# - ifshort
- misspell
# - nakedret
- noctx
- revive
- rowserrcheck
- sqlclosecheck
# Project-specific linter overrides
linters-settings:
gofmt:
simplify: false
errorlint:
# Disable errorf because there are false positives, where you don't want to wrap
# an error.
errorf: false
asserts: true
comparison: true
revive:
ignore-generated-header: true
severity: error
confidence: 0.8
rules:
- name: blank-imports
disabled: true
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
disabled: true
- name: if-return
disabled: true
- name: increment-decrement
- name: var-naming
disabled: true
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
disabled: true
- name: indent-error-flow
disabled: true
- name: errorf
- name: empty-block
disabled: true
- name: superfluous-else
- name: unused-parameter
disabled: true
- name: unreachable-code
- name: redefines-builtin-id
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
================================================
FILE: .gqlgenc.yml
================================================
model:
package: graphql
filename: ./pkg/stashbox/graphql/generated_models.go
client:
package: graphql
filename: ./pkg/stashbox/graphql/generated_client.go
models:
Date:
model: github.com/99designs/gqlgen/graphql.String
endpoint:
# This points to stashdb.org currently, but can be directed at any stash-box
# instance. It is used for generation only.
url: https://stashdb.org/graphql
query:
- "./graphql/stash-box/*.graphql"
generate:
clientV2: false
clientInterfaceName: "StashBoxGraphQLClient"
================================================
FILE: .idea/codeStyles/codeStyleConfig.xml
================================================
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
================================================
FILE: .idea/dataSources.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="stash-go" uuid="b8d0eb6d-e8e4-4865-8c0f-2798f78345a7">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$USER_HOME$/.stash/stash-go.sqlite</jdbc-url>
<driver-properties>
<property name="enable_load_extension" value="true" />
</driver-properties>
</data-source>
</component>
</project>
================================================
FILE: .idea/encodings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>
================================================
FILE: .idea/go.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/certs" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
<excludeFolder url="file://$MODULE_DIR$/ui/v2.5/build" />
<excludeFolder url="file://$MODULE_DIR$/ui/v2.5/node_modules" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/go.iml" filepath="$PROJECT_DIR$/.idea/go.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/sqldialects.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="PROJECT" dialect="SQLite" />
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
================================================
FILE: .mockery.yml
================================================
dir: ./pkg/models
name: ".*ReaderWriter"
outpkg: mocks
output: ./pkg/models/mocks
================================================
FILE: LICENSE
================================================
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
================================================
FILE: Makefile
================================================
IS_WIN_SHELL =
ifeq (${SHELL}, sh.exe)
IS_WIN_SHELL = true
endif
ifeq (${SHELL}, cmd)
IS_WIN_SHELL = true
endif
ifdef IS_WIN_SHELL
RM := del /s /q
RMDIR := rmdir /s /q
NOOP := @@
else
RM := rm -f
RMDIR := rm -rf
NOOP := @:
endif
# set LDFLAGS environment variable to any extra ldflags required
LDFLAGS := $(LDFLAGS)
# set OUTPUT environment variable to generate a specific binary name
# this will apply to both `stash` and `phasher`, so build them separately
# alternatively use STASH_OUTPUT or PHASHER_OUTPUT to set the value individually
ifdef OUTPUT
STASH_OUTPUT := $(OUTPUT)
PHASHER_OUTPUT := $(OUTPUT)
endif
ifdef STASH_OUTPUT
STASH_OUTPUT := -o $(STASH_OUTPUT)
endif
ifdef PHASHER_OUTPUT
PHASHER_OUTPUT := -o $(PHASHER_OUTPUT)
endif
# set GO_BUILD_FLAGS environment variable to any extra build flags required
GO_BUILD_FLAGS := $(GO_BUILD_FLAGS)
# set GO_BUILD_TAGS environment variable to any extra build tags required
GO_BUILD_TAGS := $(GO_BUILD_TAGS)
GO_BUILD_TAGS += sqlite_stat4 sqlite_math_functions
# set STASH_NOLEGACY environment variable or uncomment to disable legacy browser support
# STASH_NOLEGACY := true
# set STASH_SOURCEMAPS environment variable or uncomment to enable UI sourcemaps
# STASH_SOURCEMAPS := true
export CGO_ENABLED := 1
# define COMPILER_IMAGE for cross-compilation docker container
ifndef COMPILER_IMAGE
COMPILER_IMAGE := ghcr.io/stashapp/compiler:latest
endif
.PHONY: release
release: pre-ui generate ui build-release
# targets to set various build flags
# use combinations on the make command-line to configure a build, e.g.:
# for a static-pie release build: `make flags-static-pie flags-release stash`
# for a static windows debug build: `make flags-static-windows stash`
# $(NOOP) prevents "nothing to be done" warnings
.PHONY: flags-release
flags-release:
$(NOOP)
$(eval LDFLAGS += -s -w)
$(eval GO_BUILD_FLAGS += -trimpath)
.PHONY: flags-pie
flags-pie:
$(NOOP)
$(eval GO_BUILD_FLAGS += -buildmode=pie)
.PHONY: flags-static
flags-static:
$(NOOP)
$(eval LDFLAGS += -extldflags=-static)
$(eval GO_BUILD_TAGS += sqlite_omit_load_extension osusergo netgo)
.PHONY: flags-static-pie
flags-static-pie:
$(NOOP)
$(eval LDFLAGS += -extldflags=-static-pie)
$(eval GO_BUILD_FLAGS += -buildmode=pie)
$(eval GO_BUILD_TAGS += sqlite_omit_load_extension osusergo netgo)
# identical to flags-static-pie, but excluding netgo, which is not needed on windows
.PHONY: flags-static-windows
flags-static-windows:
$(NOOP)
$(eval LDFLAGS += -extldflags=-static-pie)
$(eval GO_BUILD_FLAGS += -buildmode=pie)
$(eval GO_BUILD_TAGS += sqlite_omit_load_extension osusergo)
.PHONY: build-info
build-info:
ifndef BUILD_DATE
$(eval BUILD_DATE := $(shell go run scripts/getDate.go))
endif
ifndef GITHASH
$(eval GITHASH := $(shell git rev-parse --short HEAD))
endif
ifndef STASH_VERSION
$(eval STASH_VERSION := $(shell git describe --tags --exclude latest_develop))
endif
ifndef OFFICIAL_BUILD
$(eval OFFICIAL_BUILD := false)
endif
.PHONY: build-flags
build-flags: build-info
$(eval BUILD_LDFLAGS := $(LDFLAGS))
$(eval BUILD_LDFLAGS += -X 'github.com/stashapp/stash/internal/build.buildstamp=$(BUILD_DATE)')
$(eval BUILD_LDFLAGS += -X 'github.com/stashapp/stash/internal/build.githash=$(GITHASH)')
$(eval BUILD_LDFLAGS += -X 'github.com/stashapp/stash/internal/build.version=$(STASH_VERSION)')
$(eval BUILD_LDFLAGS += -X 'github.com/stashapp/stash/internal/build.officialBuild=$(OFFICIAL_BUILD)')
$(eval BUILD_FLAGS := -v -tags "$(GO_BUILD_TAGS)" $(GO_BUILD_FLAGS) -ldflags "$(BUILD_LDFLAGS)")
.PHONY: stash
stash: build-flags
go build $(STASH_OUTPUT) $(BUILD_FLAGS) ./cmd/stash
.PHONY: phasher
phasher: build-flags
go build $(PHASHER_OUTPUT) $(BUILD_FLAGS) ./cmd/phasher
# builds dynamically-linked debug binaries
.PHONY: build
build: stash
# builds dynamically-linked PIE release binaries
.PHONY: build-release
build-release: flags-release flags-pie build
# compile and bundle into Stash.app
# for when on macOS itself
.PHONY: stash-macapp
stash-macapp: STASH_OUTPUT := -o stash
stash-macapp: flags-release flags-pie stash
rm -rf Stash.app
cp -R scripts/macos-bundle Stash.app
mkdir Stash.app/Contents/MacOS
cp stash Stash.app/Contents/MacOS/stash
# build-cc- targets should be run within the compiler docker container
.PHONY: build-cc-windows
build-cc-windows: export GOOS := windows
build-cc-windows: export GOARCH := amd64
build-cc-windows: export CC := x86_64-w64-mingw32-gcc
build-cc-windows: STASH_OUTPUT := -o dist/stash-win.exe
build-cc-windows: PHASHER_OUTPUT :=-o dist/phasher-win.exe
build-cc-windows: flags-release
build-cc-windows: flags-static-windows
build-cc-windows: build
.PHONY: build-cc-macos-intel
build-cc-macos-intel: export GOOS := darwin
build-cc-macos-intel: export GOARCH := amd64
build-cc-macos-intel: export CC := o64-clang
build-cc-macos-intel: STASH_OUTPUT := -o dist/stash-macos-intel
build-cc-macos-intel: PHASHER_OUTPUT := -o dist/phasher-macos-intel
build-cc-macos-intel: flags-release
# can't use static build for macOS
build-cc-macos-intel: flags-pie
build-cc-macos-intel: build
.PHONY: build-cc-macos-arm
build-cc-macos-arm: export GOOS := darwin
build-cc-macos-arm: export GOARCH := arm64
build-cc-macos-arm: export CC := oa64e-clang
build-cc-macos-arm: STASH_OUTPUT := -o dist/stash-macos-arm
build-cc-macos-arm: PHASHER_OUTPUT := -o dist/phasher-macos-arm
build-cc-macos-arm: flags-release
# can't use static build for macOS
build-cc-macos-arm: flags-pie
build-cc-macos-arm: build
.PHONY: build-cc-macos
build-cc-macos:
make build-cc-macos-arm
make build-cc-macos-intel
# Combine into universal binaries
lipo -create -output dist/stash-macos dist/stash-macos-intel dist/stash-macos-arm
rm dist/stash-macos-intel dist/stash-macos-arm
# Place into bundle and zip up
rm -rf dist/Stash.app
cp -R scripts/macos-bundle dist/Stash.app
mkdir dist/Stash.app/Contents/MacOS
cp dist/stash-macos dist/Stash.app/Contents/MacOS/stash
cd dist && rm -f Stash.app.zip && zip -r Stash.app.zip Stash.app
rm -rf dist/Stash.app
.PHONY: build-cc-macos-phasher
build-cc-macos-phasher:
make build-cc-macos-arm
make build-cc-macos-intel
# Combine into universal binaries
lipo -create -output dist/phasher-macos dist/phasher-macos-intel dist/phasher-macos-arm
rm dist/phasher-macos-intel dist/phasher-macos-arm
# do not bundle phasher
.PHONY: build-cc-freebsd
build-cc-freebsd: export GOOS := freebsd
build-cc-freebsd: export GOARCH := amd64
build-cc-freebsd: export CC := clang -target x86_64-unknown-freebsd12.0 --sysroot=/opt/cross-freebsd
build-cc-freebsd: STASH_OUTPUT := -o dist/stash-freebsd
build-cc-freebsd: PHASHER_OUTPUT := -o dist/phasher-freebsd
build-cc-freebsd: flags-release
build-cc-freebsd: flags-static-pie
build-cc-freebsd: build
.PHONY: build-cc-linux
build-cc-linux: export GOOS := linux
build-cc-linux: export GOARCH := amd64
build-cc-linux: STASH_OUTPUT := -o dist/stash-linux
build-cc-linux: PHASHER_OUTPUT := -o dist/phasher-linux
build-cc-linux: flags-release
build-cc-linux: flags-static-pie
build-cc-linux: build
.PHONY: build-cc-linux-arm64v8
build-cc-linux-arm64v8: export GOOS := linux
build-cc-linux-arm64v8: export GOARCH := arm64
build-cc-linux-arm64v8: export CC := aarch64-linux-gnu-gcc
build-cc-linux-arm64v8: STASH_OUTPUT := -o dist/stash-linux-arm64v8
build-cc-linux-arm64v8: PHASHER_OUTPUT := -o dist/phasher-linux-arm64v8
build-cc-linux-arm64v8: flags-release
build-cc-linux-arm64v8: flags-static-pie
build-cc-linux-arm64v8: build
.PHONY: build-cc-linux-arm32v7
build-cc-linux-arm32v7: export GOOS := linux
build-cc-linux-arm32v7: export GOARCH := arm
build-cc-linux-arm32v7: export GOARM := 7
build-cc-linux-arm32v7: export CC := arm-linux-gnueabi-gcc -march=armv7-a
build-cc-linux-arm32v7: STASH_OUTPUT := -o dist/stash-linux-arm32v7
build-cc-linux-arm32v7: PHASHER_OUTPUT := -o dist/phasher-linux-arm32v7
build-cc-linux-arm32v7: flags-release
build-cc-linux-arm32v7: flags-static
build-cc-linux-arm32v7: build
.PHONY: build-cc-linux-arm32v6
build-cc-linux-arm32v6: export GOOS := linux
build-cc-linux-arm32v6: export GOARCH := arm
build-cc-linux-arm32v6: export GOARM := 6
build-cc-linux-arm32v6: export CC := arm-linux-gnueabi-gcc
build-cc-linux-arm32v6: STASH_OUTPUT := -o dist/stash-linux-arm32v6
build-cc-linux-arm32v6: PHASHER_OUTPUT := -o dist/phasher-linux-arm32v6
build-cc-linux-arm32v6: flags-release
build-cc-linux-arm32v6: flags-static
build-cc-linux-arm32v6: build
.PHONY: build-cc-all
build-cc-all:
make build-cc-windows
make build-cc-macos
make build-cc-linux
make build-cc-linux-arm64v8
make build-cc-linux-arm32v7
make build-cc-linux-arm32v6
make build-cc-freebsd
.PHONY: touch-ui
touch-ui:
ifdef IS_WIN_SHELL
@if not exist "ui\\v2.5\\build" mkdir ui\\v2.5\\build
@type nul >> ui/v2.5/build/index.html
else
@mkdir -p ui/v2.5/build
@touch ui/v2.5/build/index.html
endif
# Regenerates GraphQL files
.PHONY: generate
generate: generate-backend generate-ui
.PHONY: generate-ui
generate-ui:
cd ui/v2.5 && npm run gqlgen
.PHONY: generate-backend
generate-backend: touch-ui
go generate ./cmd/stash
.PHONY: generate-login-locale
generate-login-locale:
go generate ./ui
.PHONY: generate-dataloaders
generate-dataloaders:
go generate ./internal/api/loaders
# Regenerates stash-box client files
.PHONY: generate-stash-box-client
generate-stash-box-client:
go run github.com/Yamashou/gqlgenc
# Runs gofmt -w on the project's source code, modifying any files that do not match its style.
.PHONY: fmt
fmt:
go fmt ./...
.PHONY: lint
lint:
golangci-lint run
# runs unit tests - excluding integration tests
.PHONY: test
test:
go test ./...
# runs all tests - including integration tests
.PHONY: it
it:
$(eval GO_BUILD_TAGS += integration)
go test -tags "$(GO_BUILD_TAGS)" ./...
# generates test mocks
.PHONY: generate-test-mocks
generate-test-mocks:
go run github.com/vektra/mockery/v2
# runs server
# sets the config file to use the local dev config
.PHONY: server-start
server-start: export STASH_CONFIG_FILE := config.yml
server-start: build-flags
ifdef IS_WIN_SHELL
@if not exist ".local" mkdir .local
else
@mkdir -p .local
endif
cd .local && go run $(BUILD_FLAGS) ../cmd/stash
# removes local dev config files
.PHONY: server-clean
server-clean:
$(RMDIR) .local
# installs UI dependencies. Run when first cloning repository, or if UI
# dependencies have changed
# If CI is set, configures pnpm to use a local store to avoid
# putting .pnpm-store in /stash
# NOTE: to run in the docker build container, using the existing
# node_modules folder, rename the .modules.yaml to .modules.yaml.bak
# and a new one will be generated. This will need to be reversed after
# building.
.PHONY: pre-ui
pre-ui:
ifdef CI
cd ui/v2.5 && pnpm config set store-dir ~/.pnpm-store && pnpm install --frozen-lockfile
else
cd ui/v2.5 && pnpm install --frozen-lockfile
endif
.PHONY: ui-env
ui-env: build-info
$(eval export VITE_APP_DATE := $(BUILD_DATE))
$(eval export VITE_APP_GITHASH := $(GITHASH))
$(eval export VITE_APP_STASH_VERSION := $(STASH_VERSION))
ifdef STASH_NOLEGACY
$(eval export VITE_APP_NOLEGACY := true)
endif
ifdef STASH_SOURCEMAPS
$(eval export VITE_APP_SOURCEMAPS := true)
endif
.PHONY: ui
ui: ui-only generate-login-locale
.PHONY: ui-only
ui-only: ui-env
cd ui/v2.5 && npm run build
.PHONY: zip-ui
zip-ui:
rm -f dist/stash-ui.zip
cd ui/v2.5/build && zip -r ../../../dist/stash-ui.zip .
.PHONY: ui-start
ui-start: ui-env
cd ui/v2.5 && npm run start -- --host
.PHONY: fmt-ui
fmt-ui:
cd ui/v2.5 && npm run format
# runs all of the frontend PR-acceptance steps
.PHONY: validate-ui
validate-ui:
cd ui/v2.5 && npm run validate
# these targets run the same steps as fmt-ui and validate-ui, but only on files that have changed
fmt-ui-quick:
cd ui/v2.5 && \
files=$$(git diff --name-only --relative --diff-filter d . ../../graphql); \
if [ -n "$$files" ]; then \
npm run prettier -- --write $$files; \
fi
# does not run tsc checks, as they are slow
validate-ui-quick:
cd ui/v2.5 && \
tsfiles=$$(git diff --name-only --relative --diff-filter d src | grep -e "\.tsx\?\$$"); \
scssfiles=$$(git diff --name-only --relative --diff-filter d src | grep "\.scss"); \
prettyfiles=$$(git diff --name-only --relative --diff-filter d . ../../graphql); \
if [ -n "$$tsfiles" ]; then npm run eslint -- $$tsfiles; fi && \
if [ -n "$$scssfiles" ]; then npm run stylelint -- $$scssfiles; fi && \
if [ -n "$$prettyfiles" ]; then npm run prettier -- --check $$prettyfiles; fi
# runs all of the backend PR-acceptance steps
.PHONY: validate-backend
validate-backend: lint it
# runs all of the tests and checks required for a PR to be accepted
.PHONY: validate
validate: validate-ui validate-backend
# locally builds and tags a 'stash/build' docker image
.PHONY: docker-build
docker-build: build-info
docker build --build-arg GITHASH=$(GITHASH) --build-arg STASH_VERSION=$(STASH_VERSION) -t stash/build -f docker/build/x86_64/Dockerfile .
# locally builds and tags a 'stash/cuda-build' docker image
.PHONY: docker-cuda-build
docker-cuda-build: build-info
docker build --build-arg GITHASH=$(GITHASH) --build-arg STASH_VERSION=$(STASH_VERSION) -t stash/cuda-build -f docker/build/x86_64/Dockerfile-CUDA .
# start the build container - for cross compilation
# this is adapted from the github actions build.yml file
.PHONY: start-compiler-container
start-compiler-container:
docker run -d --name build --mount type=bind,source="$(PWD)",target=/stash,consistency=delegated $(EXTRA_CONTAINER_ARGS) -w /stash $(COMPILER_IMAGE) tail -f /dev/null
# run the cross-compilation using
# docker exec -t build /bin/bash -c "make build-cc-<platform>"
.PHONY: remove-compiler-container
remove-compiler-container:
docker rm -f -v build
================================================
FILE: README.md
================================================
# Stash
[](https://github.com/stashapp/stash/actions/workflows/build.yml)
[](https://hub.docker.com/r/stashapp/stash 'DockerHub')
[](https://github.com/sponsors/stashapp)
[](https://opencollective.com/stashapp)
[](https://goreportcard.com/report/github.com/stashapp/stash)
[](https://discord.gg/2TsNFKt)
[](https://github.com/stashapp/stash/releases/latest)
[](https://github.com/stashapp/stash/labels/bounty)
### **Stash is a self-hosted webapp written in Go which organizes and serves your diverse content collection, catering to both your SFW and NSFW needs.**

* Stash gathers information about videos in your collection from the internet, and is extensible through the use of community-built plugins for a large number of content producers and sites.
* Stash supports a wide variety of both video and image formats.
* You can tag videos and find them later.
* Stash provides statistics about performers, tags, studios and more.
You can [watch a SFW demo video](https://vimeo.com/545323354) to see it in action.
For further information you can consult the [documentation](https://docs.stashapp.cc) or access the in-app manual from within the application (also available at [docs.stashapp.cc/in-app-manual](https://docs.stashapp.cc/in-app-manual)).
# Installing Stash
Step-by-step instructions are available at [docs.stashapp.cc/installation](https://docs.stashapp.cc/installation/).
#### Windows Users:
As of version 0.27.0, Stash no longer supports _Windows 7, 8, Server 2008 and Server 2012._
At least Windows 10 or Server 2016 is required.
#### Mac Users:
As of version 0.29.0, Stash requires _macOS 11 Big Sur_ or later.
Stash can still be run through docker on older versions of macOS.
<img src="docs/readme_assets/windows_logo.svg" width="100%" height="75"> Windows | <img src="docs/readme_assets/mac_logo.svg" width="100%" height="75"> macOS | <img src="docs/readme_assets/linux_logo.svg" width="100%" height="75"> Linux | <img src="docs/readme_assets/docker_logo.svg" width="100%" height="75"> Docker
:---:|:---:|:---:|:---:
[Latest Release](https://github.com/stashapp/stash/releases/latest/download/stash-win.exe) <br /> <sup><sub>[Development Preview](https://github.com/stashapp/stash/releases/download/latest_develop/stash-win.exe)</sub></sup> | [Latest Release](https://github.com/stashapp/stash/releases/latest/download/Stash.app.zip) <br /> <sup><sub>[Development Preview](https://github.com/stashapp/stash/releases/download/latest_develop/Stash.app.zip)</sub></sup> | [Latest Release (amd64)](https://github.com/stashapp/stash/releases/latest/download/stash-linux) <br /> <sup><sub>[Development Preview (amd64)](https://github.com/stashapp/stash/releases/download/latest_develop/stash-linux)</sub></sup> <br /> [More Architectures...](https://github.com/stashapp/stash/releases/latest) | [Instructions](docker/production/README.md) <br /> <sup><sub>[Sample docker-compose.yml](docker/production/docker-compose.yml)</sub></sup>
Download links for other platforms and architectures are available on the [Releases](https://github.com/stashapp/stash/releases) page.
## First Run
#### Windows/macOS Users: Security Prompt
On Windows or macOS, running the app might present a security prompt since the application binary isn't yet signed.
- On Windows, bypass this by clicking "more info" and then the "run anyway" button.
- On macOS, Control+Click the app, click "Open", and then "Open" again.
#### ffmpeg
Stash requires FFmpeg. If you don't have it installed, Stash will prompt you to download a copy during setup. It is recommended that Linux users install `ffmpeg` from their distro's package manager.
# Usage
## Quickstart Guide
Stash is a web-based application. Once the application is running, the interface is available (by default) from `http://localhost:9999`.
On first run, Stash will prompt you for some configuration options and media directories to index, called "Scanning" in Stash. After scanning, your media will be available for browsing, curating, editing, and tagging.
Stash can pull metadata (performers, tags, descriptions, studios, and more) directly from many sites through the use of [scrapers](https://github.com/stashapp/stash/blob/develop/ui/v2.5/src/docs/en/Manual/Scraping.md), which integrate directly into Stash. Identifying an entire collection will typically require a mix of multiple sources:
- The stashapp team maintains [StashDB](https://stashdb.org/), a crowd-sourced repository of scene, studio, and performer information. Connecting it to Stash will allow you to automatically identify much of a typical media collection. It runs on our stash-box software and is primarily focused on mainstream digital scenes and studios. Instructions, invite codes, and more can be found in this guide to [Accessing StashDB](https://guidelines.stashdb.org/docs/faq_getting-started/stashdb/accessing-stashdb/).
- Several community-managed stash-box databases can also be connected to Stash in a similar manner. Each one serves a slightly different niche and follows their own methodology. A rundown of each stash-box, their differences, and the information you need to sign up can be found in this guide to [Accessing Stash-Boxes](https://guidelines.stashdb.org/docs/faq_getting-started/stashdb/accessing-stash-boxes/).
- Many community-maintained scrapers can also be downloaded, installed, and updated from within Stash, allowing you to pull data from a wide range of other websites and databases. They can be found by navigating to `Settings → Metadata Providers → Available Scrapers → Community (stable)`. These can be trickier to use than a stash-box because every scraper works a little differently. For more information, please visit the [CommunityScrapers repository](https://github.com/stashapp/CommunityScrapers).
- All of the above methods of scraping data into Stash are also covered in more detail in our [Guide to Scraping](https://docs.stashapp.cc/beginner-guides/guide-to-scraping/).
<sub>[StashDB](http://stashdb.org) is the canonical instance of our open source metadata API, [stash-box](https://github.com/stashapp/stash-box).</sub>
# Translation
[](https://translate.codeberg.org/engage/stash/)
Stash is available in 32 languages (so far!) and it could be in your language too. We use Weblate to coordinate community translations. If you want to help us translate Stash, you can make an account at [Codeberg's Weblate](https://translate.codeberg.org/projects/stash/stash/) to contribute to new or existing languages. Thanks!
The badge below shows the current translation status of Stash across all supported languages:
[](https://translate.codeberg.org/engage/stash/)
# Support & Resources
Need help or want to get involved? Start with the documentation, then reach out to the community if you need further assistance.
- Documentation
- Official docs: https://docs.stashapp.cc - official guides guides and troubleshooting.
- In-app manual: press <kbd>Shift</kbd> + <kbd>?</kbd> in the app or view the manual online: https://docs.stashapp.cc/in-app-manual.
- FAQ: https://discourse.stashapp.cc/c/support/faq/28 - common questions and answers.
- Community wiki: https://discourse.stashapp.cc/tags/c/community-wiki/22/stash - guides, how-to’s and tips.
- Community & discussion
- Community forum: https://discourse.stashapp.cc - community support, feature requests and discussions.
- Discord: https://discord.gg/2TsNFKt - real-time chat and community support.
- GitHub discussions: https://github.com/stashapp/stash/discussions - community support and feature discussions.
- Lemmy community: https://discuss.online/c/stashapp - Reddit-style community space.
- Community scrapers & plugins
- Metadata sources: https://docs.stashapp.cc/metadata-sources/
- Plugins: https://docs.stashapp.cc/plugins/
- Themes: https://docs.stashapp.cc/themes/
- Other projects: https://docs.stashapp.cc/other-projects/
# For Developers
Pull requests are welcome!
See [Development](docs/DEVELOPMENT.md) and [Contributing](docs/CONTRIBUTING.md) for information on working with the codebase, getting a local development setup, and contributing changes.
================================================
FILE: cmd/phasher/main.go
================================================
// TODO: document in README.md
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
flag "github.com/spf13/pflag"
"github.com/stashapp/stash/pkg/ffmpeg"
"github.com/stashapp/stash/pkg/hash/imagephash"
"github.com/stashapp/stash/pkg/hash/videophash"
"github.com/stashapp/stash/pkg/models"
)
func customUsage() {
fmt.Fprintf(os.Stderr, "Usage:\n")
fmt.Fprintf(os.Stderr, "%s [OPTIONS] FILE...\n\nOptions:\n", os.Args[0])
flag.PrintDefaults()
}
func printPhash(ff *ffmpeg.FFMpeg, ffp *ffmpeg.FFProbe, inputfile string, quiet *bool) error {
// Determine if this is a video or image file based on extension
ext := filepath.Ext(inputfile)
ext = ext[1:] // remove the leading dot
// Common image extensions
imageExts := map[string]bool{
"jpg": true, "jpeg": true, "png": true, "gif": true, "webp": true, "bmp": true, "avif": true,
}
if imageExts[ext] {
return printImagePhash(ff, inputfile, quiet)
}
return printVideoPhash(ff, ffp, inputfile, quiet)
}
func printVideoPhash(ff *ffmpeg.FFMpeg, ffp *ffmpeg.FFProbe, inputfile string, quiet *bool) error {
ffvideoFile, err := ffp.NewVideoFile(inputfile)
if err != nil {
return err
}
// All we need for videophash.Generate() is
// videoFile.Path (from BaseFile)
// videoFile.Duration
// The rest of the struct isn't needed.
vf := &models.VideoFile{
BaseFile: &models.BaseFile{Path: inputfile},
Duration: ffvideoFile.FileDuration,
}
phash, err := videophash.Generate(ff, vf)
if err != nil {
return err
}
if *quiet {
fmt.Printf("%x\n", *phash)
} else {
fmt.Printf("%x %v\n", *phash, vf.Path)
}
return nil
}
func printImagePhash(ff *ffmpeg.FFMpeg, inputfile string, quiet *bool) error {
imgFile := &models.ImageFile{
BaseFile: &models.BaseFile{Path: inputfile},
}
phash, err := imagephash.Generate(ff, imgFile)
if err != nil {
return err
}
if *quiet {
fmt.Printf("%x\n", *phash)
} else {
fmt.Printf("%x %v\n", *phash, imgFile.Path)
}
return nil
}
func getPaths() (string, string) {
ffmpegPath, _ := exec.LookPath("ffmpeg")
ffprobePath, _ := exec.LookPath("ffprobe")
return ffmpegPath, ffprobePath
}
func main() {
flag.Usage = customUsage
quiet := flag.BoolP("quiet", "q", false, "print only the phash")
help := flag.BoolP("help", "h", false, "print this help output")
flag.Parse()
if *help {
flag.Usage()
os.Exit(2)
}
args := flag.Args()
if len(args) < 1 {
fmt.Fprintf(os.Stderr, "Missing FILE argument.\n")
flag.Usage()
os.Exit(2)
}
if len(args) > 1 {
fmt.Fprintln(os.Stderr, "Files will be processed sequentially! If required, use e.g. GNU Parallel to run concurrently.")
fmt.Fprintf(os.Stderr, "Example: parallel %v ::: *.mp4\n", os.Args[0])
}
ffmpegPath, ffprobePath := getPaths()
encoder := ffmpeg.NewEncoder(ffmpegPath)
// don't need to InitHWSupport, phashing doesn't use hw acceleration
ffprobe := ffmpeg.NewFFProbe(ffprobePath)
for _, item := range args {
if err := printPhash(encoder, ffprobe, item, quiet); err != nil {
fmt.Fprintln(os.Stderr, err)
}
}
}
================================================
FILE: cmd/stash/main.go
================================================
//go:generate go run github.com/99designs/gqlgen
package main
import (
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"runtime/debug"
"runtime/pprof"
"syscall"
"github.com/spf13/pflag"
"github.com/stashapp/stash/internal/api"
"github.com/stashapp/stash/internal/build"
"github.com/stashapp/stash/internal/desktop"
"github.com/stashapp/stash/internal/log"
"github.com/stashapp/stash/internal/manager"
"github.com/stashapp/stash/internal/manager/config"
"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/ui"
_ "github.com/golang-migrate/migrate/v4/database/sqlite3"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
var exitCode = 0
func main() {
defer func() {
if exitCode != 0 {
os.Exit(exitCode)
}
}()
defer recoverPanic()
initLogTemp()
helpFlag := false
pflag.BoolVarP(&helpFlag, "help", "h", false, "show this help text and exit")
versionFlag := false
pflag.BoolVarP(&versionFlag, "version", "v", false, "show version number and exit")
cpuProfilePath := ""
pflag.StringVar(&cpuProfilePath, "cpuprofile", "", "write cpu profile to file")
pflag.Parse()
if helpFlag {
pflag.Usage()
return
}
if versionFlag {
fmt.Println(build.VersionString())
return
}
cfg, err := config.Initialize()
if err != nil {
exitError(fmt.Errorf("config initialization error: %w", err))
return
}
l := initLog(cfg)
if cpuProfilePath != "" {
if err := initProfiling(cpuProfilePath); err != nil {
exitError(err)
return
}
defer pprof.StopCPUProfile()
}
// initialise desktop.IsDesktop here so that it doesn't get affected by
// ffmpeg hardware checks later on
desktop.InitIsDesktop()
mgr, err := manager.Initialize(cfg, l)
if err != nil {
exitError(fmt.Errorf("manager initialization error: %w", err))
return
}
defer mgr.Shutdown()
server, err := api.Initialize()
if err != nil {
exitError(fmt.Errorf("api initialization error: %w", err))
return
}
defer server.Shutdown()
exit := make(chan int)
go func() {
err := server.Start()
if !errors.Is(err, http.ErrServerClosed) {
exitError(fmt.Errorf("http server error: %w", err))
exit <- 1
}
}()
go handleSignals(exit)
desktop.Start(exit, &ui.FaviconProvider)
exitCode = <-exit
}
// initLogTemp initializes a temporary logger for use before the config is loaded.
// Logs only error level message to stderr.
func initLogTemp() *log.Logger {
l := log.NewLogger()
l.Init("", true, "Error", 0)
logger.Logger = l
return l
}
func initLog(cfg *config.Config) *log.Logger {
l := log.NewLogger()
l.Init(cfg.GetLogFile(), cfg.GetLogOut(), cfg.GetLogLevel(), cfg.GetLogFileMaxSize())
logger.Logger = l
return l
}
func initProfiling(path string) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("unable to create CPU profile file: %v", err)
}
if err = pprof.StartCPUProfile(f); err != nil {
return fmt.Errorf("could not start CPU profiling: %v", err)
}
logger.Infof("profiling to %s", path)
return nil
}
func recoverPanic() {
if err := recover(); err != nil {
exitCode = 1
logger.Errorf("panic: %v\n%s", err, debug.Stack())
if desktop.IsDesktop() {
desktop.FatalError(fmt.Errorf("Panic: %v", err))
}
}
}
func exitError(err error) {
exitCode = 1
logger.Error(err)
// #5784 - log to stdout as well as the logger
// this does mean that it will log twice if the logger is set to stdout
fmt.Println(err)
if desktop.IsDesktop() {
desktop.FatalError(err)
}
}
func handleSignals(exit chan<- int) {
// handle signals
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
<-signals
exit <- 0
}
================================================
FILE: cmd/stash/main_test.go
================================================
package main
import "testing"
func TestStub(t *testing.T) {
}
================================================
FILE: docker/build/x86_64/Dockerfile
================================================
# This dockerfile should be built with `make docker-build` from the stash root.
# Build Frontend
FROM node:24-alpine AS frontend
RUN apk add --no-cache make git
## cache node_modules separately
COPY ./ui/v2.5/package.json ./ui/v2.5/pnpm-lock.yaml /stash/ui/v2.5/
WORKDIR /stash
COPY Makefile /stash/
COPY ./graphql /stash/graphql/
COPY ./ui /stash/ui/
# pnpm install with npm
RUN npm install -g pnpm
RUN make pre-ui
RUN make generate-ui
ARG GITHASH
ARG STASH_VERSION
RUN BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") make ui-only
# Build Backend
FROM golang:1.24.3-alpine AS backend
RUN apk add --no-cache make alpine-sdk
WORKDIR /stash
COPY ./go* ./*.go Makefile gqlgen.yml .gqlgenc.yml /stash/
COPY ./graphql /stash/graphql/
COPY ./scripts /stash/scripts/
COPY ./pkg /stash/pkg/
COPY ./cmd /stash/cmd/
COPY ./internal /stash/internal/
# needed for generate-login-locale
COPY ./ui /stash/ui/
RUN make generate-backend generate-login-locale
COPY --from=frontend /stash /stash/
ARG GITHASH
ARG STASH_VERSION
RUN make flags-release flags-pie stash
# Final Runnable Image
FROM alpine:latest
RUN apk add --no-cache ca-certificates vips-tools ffmpeg
COPY --from=backend /stash/stash /usr/bin/
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
EXPOSE 9999
ENTRYPOINT ["stash"]
================================================
FILE: docker/build/x86_64/Dockerfile-CUDA
================================================
# This dockerfile should be built with `make docker-cuda-build` from the stash root.
ARG CUDA_VERSION=12.8.0
# Build Frontend
FROM node:20-alpine AS frontend
RUN apk add --no-cache make git
## cache node_modules separately
COPY ./ui/v2.5/package.json ./ui/v2.5/pnpm-lock.yaml /stash/ui/v2.5/
WORKDIR /stash
COPY Makefile /stash/
COPY ./graphql /stash/graphql/
COPY ./ui /stash/ui/
# pnpm install with npm
RUN npm install -g pnpm
RUN make pre-ui
RUN make generate-ui
ARG GITHASH
ARG STASH_VERSION
RUN BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") make ui-only
# Build Backend
FROM golang:1.24.3-bullseye AS backend
RUN apt update && apt install -y build-essential golang
WORKDIR /stash
COPY ./go* ./*.go Makefile gqlgen.yml .gqlgenc.yml /stash/
COPY ./graphql /stash/graphql/
COPY ./scripts /stash/scripts/
COPY ./pkg /stash/pkg/
COPY ./cmd /stash/cmd
COPY ./internal /stash/internal
# needed for generate-login-locale
COPY ./ui /stash/ui/
RUN make generate-backend generate-login-locale
COPY --from=frontend /stash /stash/
ARG GITHASH
ARG STASH_VERSION
RUN make flags-release flags-pie stash
# Final Runnable Image
FROM nvidia/cuda:${CUDA_VERSION}-base-ubuntu24.04
RUN apt update && apt upgrade -y && apt install -y \
# stash dependencies
ca-certificates libvips-tools ffmpeg \
# intel dependencies
intel-media-va-driver-non-free vainfo \
# python tools
python3 python3-pip && \
# cleanup
apt autoremove -y && apt clean && \
rm -rf /var/lib/apt/lists/*
COPY --from=backend --chmod=555 /stash/stash /usr/bin/
# NVENC Patch
RUN mkdir -p /usr/local/bin /patched-lib
ADD --chmod=555 https://raw.githubusercontent.com/keylase/nvidia-patch/master/patch.sh /usr/local/bin/patch.sh
ADD --chmod=555 https://raw.githubusercontent.com/keylase/nvidia-patch/master/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
ENV LANG=C.UTF-8
ENV NVIDIA_VISIBLE_DEVICES=all
ENV NVIDIA_DRIVER_CAPABILITIES=video,utility
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
EXPOSE 9999
ENTRYPOINT ["docker-entrypoint.sh", "stash"]
# vim: ft=dockerfile
================================================
FILE: docker/build/x86_64/README.md
================================================
# Introduction
This dockerfile is used to build a stash docker container using the current source code. This is ideal for testing your current branch in docker. Note that it does not include python, so python-based scrapers will not work in this image. The production docker images distributed by the project contain python and the necessary packages.
# Building the docker container
From the top-level directory (should contain `tools.go` file):
```
make docker-build
```
# Running the docker container
## Using docker-compose
See the `README.md` file in `docker/production` for instructions on how to get docker-compose if needed.
The `stash/build` container can be run with the `docker-compose.yml` file in `docker/production` by changing the `image` value to be `stash/build`. See the instructions in `docker/production` for how to run docker-compose.
## Using `docker run`
After building the container:
```
docker run \
-e STASH_STASH=/data/ \
-e STASH_METADATA=/metadata/ \
-e STASH_CACHE=/cache/ \
-e STASH_GENERATED=/generated/ \
-v <path to config dir>:/root/.stash \
-v <path to media>:/data \
-v <path to metadata>:/metadata \
-v <path to cache>:/cache \
-v <path to generated>:/generated \
-p 9999:9999 \
stash/build:latest
```
Change the `<xxx>` to the appropriate paths. Note that the `<path to media>` directory should be separate from the cache, generated and metadata directories. It is recommended to have the cache, generated and metadata directories in the same parent directory, for example:
```
/stash
/config
/metadata
/generated
/cache
/media
```
Using this example directory structure, the above command would be:
```
docker run \
-e STASH_STASH=/data/ \
-e STASH_METADATA=/metadata/ \
-e STASH_CACHE=/cache/ \
-e STASH_GENERATED=/generated/ \
-v /stash/config:/root/.stash \
-v /media:/data \
-v /stash/metadata:/metadata \
-v /stash/cache:/cache \
-v /stash/generated:/generated \
-p 9999:9999 \
stash/build:latest
```
================================================
FILE: docker/ci/x86_64/Dockerfile
================================================
FROM --platform=$BUILDPLATFORM alpine:latest AS binary
ARG TARGETPLATFORM
WORKDIR /
COPY stash-* /
RUN if [ "$TARGETPLATFORM" = "linux/arm/v6" ]; then BIN=stash-linux-arm32v6; \
elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then BIN=stash-linux-arm32v7; \
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then BIN=stash-linux-arm64v8; \
elif [ "$TARGETPLATFORM" = "linux/amd64" ]; then BIN=stash-linux; \
fi; \
mv $BIN /stash
FROM --platform=$TARGETPLATFORM alpine:latest AS app
COPY --from=binary /stash /usr/bin/
RUN apk add --no-cache ca-certificates python3 py3-requests py3-requests-toolbelt py3-lxml py3-pip ffmpeg tzdata vips vips-tools \
&& pip install --break-system-packages mechanicalsoup cloudscraper stashapp-tools
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
# Basic build-time metadata as defined at https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
LABEL org.opencontainers.image.title="Stash" \
org.opencontainers.image.description="An organizer for your porn, written in Go." \
org.opencontainers.image.url="https://stashapp.cc" \
org.opencontainers.image.documentation="https://docs.stashapp.cc" \
org.opencontainers.image.source="https://github.com/stashapp/stash" \
org.opencontainers.image.licenses="AGPL-3.0"
EXPOSE 9999
CMD ["stash"]
================================================
FILE: docker/ci/x86_64/README.md
================================================
This Dockerfile is used by CI to build the `stashapp/stash` Docker image. It must be run after cross-compiling - that is, `stash-linux` must exist in the `dist` directory. This image must be built from the `dist` directory.
================================================
FILE: docker/ci/x86_64/docker_push.sh
================================================
#!/bin/bash
DOCKER_TAGS=""
for TAG in "$@"
do
DOCKER_TAGS="$DOCKER_TAGS -t stashapp/stash:$TAG"
done
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
# must build the image from dist directory
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 --push $DOCKER_TAGS -f docker/ci/x86_64/Dockerfile dist/
================================================
FILE: docker/compiler/Dockerfile
================================================
### OSXCROSS
FROM debian:bookworm AS osxcross
# add osxcross
WORKDIR /tmp/osxcross
ARG OSXCROSS_REVISION=5e1b71fcceb23952f3229995edca1b6231525b5b
ADD --checksum=sha256:d3f771bbc20612fea577b18a71be3af2eb5ad2dd44624196cf55de866d008647 https://codeload.github.com/tpoechtrager/osxcross/tar.gz/${OSXCROSS_REVISION} /tmp/osxcross.tar.gz
ARG OSX_SDK_VERSION=11.3
ARG OSX_SDK_DOWNLOAD_FILE=MacOSX${OSX_SDK_VERSION}.sdk.tar.xz
ARG OSX_SDK_DOWNLOAD_URL=https://github.com/phracker/MacOSX-SDKs/releases/download/${OSX_SDK_VERSION}/${OSX_SDK_DOWNLOAD_FILE}
ADD --checksum=sha256:cd4f08a75577145b8f05245a2975f7c81401d75e9535dcffbb879ee1deefcbf4 ${OSX_SDK_DOWNLOAD_URL} /tmp/osxcross/tarballs/${OSX_SDK_DOWNLOAD_FILE}
ENV UNATTENDED=yes \
SDK_VERSION=${OSX_SDK_VERSION} \
OSX_VERSION_MIN=10.10
RUN apt update && \
apt install -y --no-install-recommends \
bash ca-certificates clang cmake git patch libssl-dev bzip2 cpio libbz2-dev libxml2-dev make python3 xz-utils zlib1g-dev
# lzma-dev libxml2-dev xz
RUN tar --strip=1 -C /tmp/osxcross -xf /tmp/osxcross.tar.gz
RUN ./build.sh
### FREEBSD cross-compilation stage
# use alpine for cacheable image since apt is notorous for not caching
FROM alpine:3 AS freebsd
# match golang latest
# https://go.dev/wiki/FreeBSD
ARG FREEBSD_VERSION=12.4
ADD --checksum=sha256:581c7edacfd2fca2bdf5791f667402d22fccd8a5e184635e0cac075564d57aa8 \
http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/old-releases/amd64/${FREEBSD_VERSION}-RELEASE/base.txz \
/tmp/base.txz
WORKDIR /opt/cross-freebsd
RUN apk add --no-cache tar xz
RUN tar -xf /tmp/base.txz --strip-components=1 ./usr/lib ./usr/include ./lib
RUN cd /opt/cross-freebsd/usr/lib && \
find . -type l -exec sh -c ' \
for link; do \
target=$(readlink "$link"); \
case "$target" in \
/lib/*) ln -sf "/opt/cross-freebsd$target" "$link";; \
esac; \
done \
' sh {} + && \
ln -s libc++.a libstdc++.a && \
ln -s libc++.so libstdc++.so
### BUILDER
FROM golang:1.24.3 AS builder
ENV PATH=/opt/osx-ndk-x86/bin:$PATH
# copy in nodejs instead of using nodesource :thumbsup:
COPY --from=docker.io/library/node:24-bookworm /usr/local /usr/local
# copy in osxcross
COPY --from=osxcross /tmp/osxcross/target/lib /usr/lib
COPY --from=osxcross /tmp/osxcross/target /opt/osx-ndk-x86
# copy in cross-freebsd
COPY --from=freebsd /opt/cross-freebsd /opt/cross-freebsd
# pnpm install with npm
RUN npm install -g pnpm
# git for getting hash
# make and bash for building
# clang for macos
# zip for stashapp.zip
# gcc-extensions for cross-arch build
# we still target arm soft float?
RUN apt-get update && \
apt-get install -y --no-install-recommends \
git make bash \
clang zip \
gcc-mingw-w64 \
gcc-arm-linux-gnueabi \
libc-dev-armel-cross linux-libc-dev-armel-cross \
gcc-aarch64-linux-gnu libc-dev-arm64-cross && \
rm -rf /var/lib/apt/lists/*;
RUN git config --global safe.directory '*'
# To test locally:
# make generate
# make ui
# cd docker/compiler
# docker build . -t ghcr.io/stashapp/compiler:latest
# docker run --rm -v /PATH_TO_STASH:/stash -w /stash -i -t ghcr.io/stashapp/compiler:latest make build-cc-all
# # binaries will show up in /dist
================================================
FILE: docker/compiler/Makefile
================================================
host=ghcr.io
user=stashapp
repo=compiler
version=13
VERSION_IMAGE = ${host}/${user}/${repo}:${version}
LATEST_IMAGE = ${host}/${user}/${repo}:latest
latest:
docker build -t ${LATEST_IMAGE} .
build:
docker build -t ${VERSION_IMAGE} -t ${LATEST_IMAGE} .
build-no-cache:
docker build --no-cache -t ${VERSION_IMAGE} -t ${LATEST_IMAGE} .
# requires docker login ghcr.io
# echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
push:
docker push ${VERSION_IMAGE}
docker push ${LATEST_IMAGE}
================================================
FILE: docker/compiler/README.md
================================================
Modified from https://github.com/bep/dockerfiles/tree/master/ci-goreleaser
When the Dockerfile is changed, the version number should be incremented in [.github/workflows/build-compiler.yml](../../.github/workflows/build-compiler.yml) and the workflow [manually ran](). `env: COMPILER_IMAGE` in [.github/workflows/build.yml](../../.github/workflows/build.yml) also needs to be updated to pull the correct image tag.
================================================
FILE: docker/production/README.md
================================================
# Docker Installation (for most 64-bit GNU/Linux systems)
StashApp is supported on most systems that support Docker. Your OS likely ships with or makes available the necessary packages.
## Dependencies
Only `docker` is required. For the most part your understanding of the technologies can be superficial. So long as you can follow commands and are open to reading a bit, you should be fine.
Installation instructions are available below, and if your distributions's repository ships a current version of docker, you may use that.
https://docs.docker.com/engine/install/
On some distributions, `docker compose` is shipped seperately, usually as `docker-cli-compose`. docker-compose is not recommended.
### Get the docker-compose.yml file
Now you can either navigate to the [docker-compose.yml](https://raw.githubusercontent.com/stashapp/stash/develop/docker/production/docker-compose.yml) in the repository, or if you have curl, you can make your Linux console do it for you:
```
mkdir stashapp && cd stashapp
curl -o docker-compose.yml https://raw.githubusercontent.com/stashapp/stash/develop/docker/production/docker-compose.yml
```
Once you have that file where you want it, modify the settings as you please, and then run:
```
docker compose up -d
```
Installing StashApp this way will by default bind stash to port 9999. This is available in your web browser locally at http://localhost:9999 or on your network as http://YOUR-LOCAL-IP:9999
Good luck and have fun!
### Docker
Docker is effectively a cross-platform software package repository. It allows you to ship an entire environment in what's referred to as a container. Containers are intended to hold everything that is needed to run an application from one place to another, making it easy for everyone along the way to reproduce the environment.
The StashApp docker container ships with everything you need to automatically run stash, including ffmpeg.
### docker compose
Docker Compose lets you specify how and where to run your containers, and to manage their environment. The docker-compose.yml file in this folder gets you a fully working instance of StashApp exactly as you would need it to have a reasonable instance for testing / developing on. If you are deploying a live instance for production, a [reverse proxy](https://docs.stashapp.cc/guides/reverse-proxy/) (such as NGINX or Traefik) is recommended, but not required.
The latest version is always recommended.
================================================
FILE: docker/production/docker-compose.yml
================================================
# APPNICENAME=Stash
# APPDESCRIPTION=An organizer for your porn, written in Go
services:
stash:
image: stashapp/stash:latest
container_name: stash
restart: unless-stopped
## the container's port must be the same with the STASH_PORT in the environment section
ports:
- "9999:9999"
## If you intend to use stash's DLNA functionality uncomment the below network mode and comment out the above ports section
# network_mode: host
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "2m"
environment:
- STASH_STASH=/data/
- STASH_GENERATED=/generated/
- STASH_METADATA=/metadata/
- STASH_CACHE=/cache/
## Adjust below to change default port (9999)
- STASH_PORT=9999
volumes:
- /etc/localtime:/etc/localtime:ro
## Adjust below paths (the left part) to your liking.
## E.g. you can change ./config:/root/.stash to ./stash:/root/.stash
## The left part is the path on your host, the right part is the path in the stash container.
## Keep configs, scrapers, and plugins here.
- ./config:/root/.stash
## Point this at your collection.
## The left side is where your collection is on your host, the right side is where it will be in stash.
- ./data:/data
## This is where your stash's metadata lives
- ./metadata:/metadata
## Any other cache content.
- ./cache:/cache
## Where to store binary blob data (scene covers, images)
- ./blobs:/blobs
## Where to store generated content (screenshots,previews,transcodes,sprites)
- ./generated:/generated
================================================
FILE: docs/CONTRIBUTING.md
================================================
## Goals and design vision
The goal of stash is to be:
- an application for organising and viewing adult content - currently this is videos and images, in future this will be extended to include audio and text content
- organising includes scraping of metadata from websites and metadata repositories
- free and open-source
- portable and offline - can be run on a USB stick without needing to install dependencies (with the exception of ffmpeg)
- minimal, but highly extensible. The core feature set should be the minimum required to achieve the primary goal, while being extensible enough to extend via plugins
- easy to learn and use, with minimal technical knowledge required
The core stash system is not intended for:
- managing downloading of content
- managing content on external websites
- publically sharing content
Other requirements:
- support as many video and image formats as possible
- interfaces with external systems (for example stash-box) should be made as generic as possible.
Design considerations:
- features are easy to add and difficult to remove. Large superfluous features should be scrutinised and avoided where possible (eg DLNA, filename parser). Such features should be considered for third-party plugins instead.
## Technical Debt
Please be sure to consider how heavily your contribution impacts the maintainability of the project long term, sometimes less is more. We don't want to merge collossal pull requests with hundreds of dependencies by a driveby contributor.
## Contributor Checklist
Please make sure that you've considered the following before you submit your Pull Requests as ready for merging.
* I've run Code linters and [gofmt](https://golang.org/cmd/gofmt/) to make sure that my code is readable.
* I have read through formerly submitted [pull requests](https://github.com/stashapp/stash/pulls) and [git issues](https://github.com/stashapp/stash/issues) to make sure that this contribution is required and isn't a duplicate. Also, so that I can manage to close any git Issues needing closed relating to this feature submission.
* I commented adequately on my code with the expectation in mind that anyone else should be able to look at this code I've submitted and know exactly what's happening and what the expectations are.
### Legal Agreements
* I acknowledge that if applicable to me, submitting and subsequent acceptance of this Pull Request I, the code contributor of this Pull Request, agree and acknowledge my understanding that the new code license has now been updated to [AGPL](/LICENSE.md). I agree that all code before this Pull Request, which I've previously submitted, is now to be re-licensed under the new license AGPL and no longer the former MIT license.
**In case you were unable to follow any of the above include an explanation as to why not in your Pull Request.**
================================================
FILE: docs/DEVELOPMENT.md
================================================
# Building from Source
## Pre-requisites
* [Go](https://golang.org/dl/)
* [GolangCI](https://golangci-lint.run/) - A meta-linter which runs several linters in parallel
* To install, follow the [local installation instructions](https://golangci-lint.run/welcome/install/#local-installation)
* [nodejs](https://nodejs.org/en/download) - nodejs runtime
* corepack/[pnpm](https://pnpm.io/installation) - nodejs package manager (included with nodejs)
## Environment
### Windows
1. Download and install [Go for Windows](https://golang.org/dl/)
2. Download and extract [MinGW64](https://sourceforge.net/projects/mingw-w64/files/) (scroll down and select x86_64-posix-seh, don't use the autoinstaller, it doesn't work)
3. Search for "Advanced System Settings" and open the System Properties dialog.
1. Click the `Environment Variables` button
2. Under System Variables find `Path`. Edit and add `C:\MinGW\bin` (replace with the correct path to where you extracted MingW64).
NOTE: The `make` command in Windows will be `mingw32-make` with MinGW. For example, `make pre-ui` will be `mingw32-make pre-ui`.
### macOS
1. If you don't have it already, install the [Homebrew package manager](https://brew.sh).
2. Install dependencies: `brew install go git gcc make node ffmpeg`
### Linux
#### Arch Linux
1. Install dependencies: `sudo pacman -S go git gcc make nodejs ffmpeg --needed`
#### Ubuntu
1. Install dependencies: `sudo apt-get install golang git gcc nodejs ffmpeg -y`
### OpenBSD
1. Install dependencies `doas pkg_add gmake go git node cmake ffmpeg`
2. Follow the instructions below to build a release, but replace the final step `make build-release` with `gmake flags-release stash`, to [avoid the PIE buildmode](https://github.com/golang/go/issues/59866).
NOTE: The `make` command in OpenBSD will be `gmake`. For example, `make pre-ui` will be `gmake pre-ui`.
## Commands
* `make pre-ui` - Installs the UI dependencies. This only needs to be run once after cloning the repository, or if the dependencies are updated.
* `make generate` - Generates Go and UI GraphQL files. Requires `make pre-ui` to have been run.
* `make generate-stash-box-client` - Generate Go files for the Stash-box client code.
* `make ui` - Builds the UI. Requires `make pre-ui` to have been run.
* `make stash` - Builds the `stash` binary (make sure to build the UI as well... see below)
* `make stash-macapp` - Builds the `Stash.app` macOS app (only works when on macOS, for cross-compilation see below)
* `make phasher` - Builds the `phasher` binary
* `make build` - Builds both the `stash` and `phasher` binaries, alias for `make stash phasher`
* `make build-release` - Builds release versions (debug information removed) of both the `stash` and `phasher` binaries, alias for `make flags-release flags-pie build`
* `make docker-build` - Locally builds and tags a complete 'stash/build' docker image
* `make docker-cuda-build` - Locally builds and tags a complete 'stash/cuda-build' docker image
* `make validate` - Runs all of the tests and checks required to submit a PR
* `make lint` - Runs `golangci-lint` on the backend
* `make it` - Runs all unit and integration tests
* `make fmt` - Formats the Go source code
* `make fmt-ui` - Formats the UI source code
* `make validate-ui` - Runs tests and checks for the UI only
* `make fmt-ui-quick` - (experimental) Formats only changed UI source code
* `make validate-ui-quick` - (experimental) Runs tests and checks of changed UI code
* `make server-start` - Runs a development stash server in the `.local` directory
* `make server-clean` - Removes the `.local` directory and all of its contents
* `make ui-start` - Runs the UI in development mode. Requires a running Stash server to connect to - the server URL can be changed from the default of `http://localhost:9999` using the environment variable `VITE_APP_PLATFORM_URL`, but keep in mind that authentication cannot be used since the session authorization cookie cannot be sent cross-origin. The UI runs on port `3000` or the next available port.
When building, you can optionally prepend `flags-*` targets to the target list in your `make` command to use different build flags:
* `flags-release` (e.g. `make flags-release stash`) - Remove debug information from the binary.
* `flags-pie` (e.g. `make flags-pie build`) - Build a PIE (Position Independent Executable) binary. This provides increased security, but it is unsupported on some systems (notably 32-bit ARM and OpenBSD).
* `flags-static` (e.g. `make flags-static phasher`) - Build a statically linked binary (the default is a dynamically linked binary).
* `flags-static-pie` (e.g. `make flags-static-pie stash`) - Build a statically linked PIE binary (using `flags-static` and `flags-pie` separately will not work).
* `flags-static-windows` (e.g. `make flags-static-windows build`) - Identical to `flags-static-pie`, but does not enable the `netgo` build tag, which is not needed for static builds on Windows.
## Local development quickstart
1. Run `make pre-ui` to install UI dependencies
2. Run `make generate` to create generated files
3. In one terminal, run `make server-start` to run the server code
4. In a separate terminal, run `make ui-start` to run the UI in development mode
5. Open the UI in a browser: `http://localhost:3000/`
Changes to the UI code can be seen by reloading the browser page.
Changes to the backend code require a server restart (`CTRL-C` in the server terminal, followed by `make server-start` again) to be seen.
On first launch:
1. On the "Stash Setup Wizard" screen, choose a directory with some files to test with
2. Press "Next" to use the default locations for the database and generated content
3. Press the "Confirm" and "Finish" buttons to get into the UI
4. On the side menu, navigate to "Tasks -> Library -> Scan" and press the "Scan" button
5. You're all set! Set any other configurations you'd like and test your code changes.
To start fresh with new configuration:
1. Stop the server (`CTRL-C` in the server terminal)
2. Run `make server-clean` to clear all config, database, and generated files (under `.local`)
3. Run `make server-start` to restart the server
4. Follow the "On first launch" steps above
## Building a release
Simply run `make` or `make release`, or equivalently:
1. Run `make pre-ui` to install UI dependencies
2. Run `make generate` to create generated files
3. Run `make ui` to build the frontend
4. Run `make build-release` to build a release executable for your current platform
## Cross-compiling
This project uses a modification of the [CI-GoReleaser](https://github.com/bep/dockerfiles/tree/master/ci-goreleaser) Docker container for cross-compilation, defined in `docker/compiler/Dockerfile`.
To cross-compile the app yourself:
1. Run `make pre-ui`, `make generate` and `make ui` outside the container, to generate files and build the UI.
2. Pull the latest compiler image from GHCR: `docker pull ghcr.io/stashapp/compiler`
3. Run `docker run --rm --mount type=bind,source="$(pwd)",target=/stash -w /stash -it ghcr.io/stashapp/compiler /bin/bash` to open a shell inside the container.
4. From inside the container, run `make build-cc-all` to build for all platforms, or run `make build-cc-{platform}` to build for a specific platform (have a look at the `Makefile` for the list of targets).
5. You will find the compiled binaries in `dist/`.
NOTE: Since the container is run as UID 0 (root), the resulting binaries (and the `dist/` folder itself, if it had to be created) will be owned by root.
## Profiling
Stash can be profiled using the `--cpuprofile <output profile filename>` command line flag.
The resulting file can then be used with pprof as follows:
`go tool pprof <path to binary> <path to profile filename>`
With `graphviz` installed and in the path, a call graph can be generated with:
`go tool pprof -svg <path to binary> <path to profile filename> > <output svg file>`
================================================
FILE: go.mod
================================================
module github.com/stashapp/stash
go 1.24.3
require (
github.com/99designs/gqlgen v0.17.73
github.com/WithoutPants/sortorder v0.0.0-20230616003020-921c9ef69552
github.com/Yamashou/gqlgenc v0.32.1
github.com/anacrolix/dms v1.2.2
github.com/antchfx/htmlquery v1.3.5
github.com/asticode/go-astisub v0.25.1
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d
github.com/chromedp/chromedp v0.14.2
github.com/corona10/goimagehash v1.1.0
github.com/disintegration/imaging v1.6.2
github.com/dop251/goja v0.0.0-20231027120936-b396bb4c349d
github.com/doug-martin/goqu/v9 v9.18.0
github.com/go-chi/chi/v5 v5.2.2
github.com/go-chi/cors v1.2.1
github.com/go-chi/httplog v0.3.1
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
github.com/golang-jwt/jwt/v4 v4.5.2
github.com/golang-migrate/migrate/v4 v4.16.2
github.com/google/uuid v1.6.0
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.2.1
github.com/gorilla/websocket v1.5.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/hasura/go-graphql-client v0.13.1
github.com/jinzhu/copier v0.4.0
github.com/jmoiron/sqlx v1.4.0
github.com/json-iterator/go v1.1.12
github.com/kermieisinthehouse/gosx-notifier v0.1.2
github.com/kermieisinthehouse/systray v1.2.4
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/env v1.1.0
github.com/knadh/koanf/providers/file v1.2.0
github.com/knadh/koanf/providers/posflag v1.0.1
github.com/knadh/koanf/v2 v2.2.1
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mattn/go-sqlite3 v1.14.22
github.com/mitchellh/mapstructure v1.5.0
github.com/natefinch/pie v0.0.0-20170715172608-9a0d72014007
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/remeh/sizedwaitgroup v1.0.0
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cast v1.6.0
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
github.com/tidwall/gjson v1.16.0
github.com/vearutop/statigz v1.4.0
github.com/vektah/dataloaden v0.3.0
github.com/vektah/gqlparser/v2 v2.5.27
github.com/vektra/mockery/v2 v2.10.0
github.com/xWTF/chardet v0.0.0-20230208095535-c780f2ac244e
github.com/zencoder/go-dash/v3 v3.0.2
golang.org/x/crypto v0.45.0
golang.org/x/image v0.18.0
golang.org/x/net v0.47.0
golang.org/x/sys v0.38.0
golang.org/x/term v0.37.0
golang.org/x/text v0.31.0
golang.org/x/time v0.10.0
gopkg.in/guregu/null.v4 v4.0.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v2 v2.4.0
)
require (
github.com/agnivade/levenshtein v1.2.1 // indirect
github.com/antchfx/xpath v1.3.5 // indirect
github.com/asticode/go-astikit v0.20.0 // indirect
github.com/asticode/go-astits v1.8.0 // indirect
github.com/chromedp/sysutil v1.1.0 // indirect
github.com/coder/websocket v1.8.12 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.4.0 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/knadh/koanf/maps v0.1.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/zerolog v1.30.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sosodev/duration v1.3.1 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/urfave/cli/v2 v2.27.6 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.3 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/tools v0.38.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
================================================
FILE: go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/99designs/gqlgen v0.17.73 h1:A3Ki+rHWqKbAOlg5fxiZBnz6OjW3nwupDHEG15gEsrg=
github.com/99designs/gqlgen v0.17.73/go.mod h1:2RyGWjy2k7W9jxrs8MOQthXGkD3L3oGr0jXW3Pu8lGg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
github.com/WithoutPants/sortorder v0.0.0-20230616003020-921c9ef69552 h1:eukVk+mGmbSZppLw8WJGpEUgMC570eb32y7FOsPW4Kc=
github.com/WithoutPants/sortorder v0.0.0-20230616003020-921c9ef69552/go.mod h1:LKbO1i6L1lSlwWx4NHWVECxubHNKFz2YQoEMGXAFVy8=
github.com/Yamashou/gqlgenc v0.32.1 h1:EHs9//xQxXlyltkSFXM+fhO2rTXcWNw6FPKRJ6t+iQQ=
github.com/Yamashou/gqlgenc v0.32.1/go.mod h1:o5SxKt9d3+oUZ2i0V3CW8lHFyunfLR+KcKHubS4zf5E=
github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anacrolix/dms v1.2.2 h1:0mk2/DXNqa5KDDbaLgFPf3oMV6VCGdFNh3d/gt4oafM=
github.com/anacrolix/dms v1.2.2/go.mod h1:msPKAoppoNRfrYplJqx63FZ+VipDZ4Xsj3KzIQxyU7k=
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
github.com/anacrolix/ffprobe v1.0.0/go.mod h1:BIw+Bjol6CWjm/CRWrVLk2Vy+UYlkgmBZ05vpSYqZPw=
github.com/anacrolix/missinggo v1.1.0/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/antchfx/htmlquery v1.3.5 h1:aYthDDClnG2a2xePf6tys/UyyM/kRcsFRm+ifhFKoU0=
github.com/antchfx/htmlquery v1.3.5/go.mod h1:5oyIPIa3ovYGtLqMPNjBF2Uf25NPCKsMjCnQ8lvjaoA=
github.com/antchfx/xpath v1.3.5 h1:PqbXLC3TkfeZyakF5eeh3NTWEbYl4VHNVeufANzDbKQ=
github.com/antchfx/xpath v1.3.5/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8=
github.com/asticode/go-astikit v0.20.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
github.com/asticode/go-astisub v0.25.1 h1:RZMGfZPp7CXOkI6g+zCU7DRLuciGPGup921uKZnMXPI=
github.com/asticode/go-astisub v0.25.1/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8=
github.com/asticode/go-astits v1.8.0 h1:rf6aiiGn/QhlFjNON1n5plqF3Fs025XLUwiQ0NB6oZg=
github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bool64/dev v0.2.28 h1:6ayDfrB/jnNr2iQAZHI+uT3Qi6rErSbJYQs1y8rSrwM=
github.com/bool64/dev v0.2.28/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d h1:ZtA1sedVbEW7EW80Iz2GR3Ye6PwbJAJXjv7D74xG6HU=
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k=
github.com/chromedp/chromedp v0.14.2 h1:r3b/WtwM50RsBZHMUm9fsNhhzRStTHrKdr2zmwbZSzM=
github.com/chromedp/chromedp v0.14.2/go.mod h1:rHzAv60xDE7VNy/MYtTUrYreSc0ujt2O1/C3bzctYBo=
github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM=
github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo=
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja v0.0.0-20231027120936-b396bb4c349d h1:wi6jN5LVt/ljaBG4ue79Ekzb12QfJ52L9Q98tl8SWhw=
github.com/dop251/goja v0.0.0-20231027120936-b396bb4c349d/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
github.com/doug-martin/goqu/v9 v9.18.0 h1:/6bcuEtAe6nsSMVK/M+fOiXUNfyFF3yYtE07DBPFMYY=
github.com/doug-martin/goqu/v9 v9.18.0/go.mod h1:nf0Wc2/hV3gYK9LiyqIrzBEVGlI8qW3GuDCEobC4wBQ=
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/httplog v0.3.1 h1:uC3IUWCZagtbCinb3ypFh36SEcgd6StWw2Bu0XSXRtg=
github.com/go-chi/httplog v0.3.1/go.mod h1:UoiQQ/MTZH5V6JbNB2FzF0DynTh5okpXxlhsyxoP5m8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs=
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE=
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8qQDT2iKfuoA=
github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hasura/go-graphql-client v0.13.1 h1:kKbjhxhpwz58usVl+Xvgah/TDha5K2akNTRQdsEHN6U=
github.com/hasura/go-graphql-client v0.13.1/go.mod h1:k7FF7h53C+hSNFRG3++DdVZWIuHdCaTbI7siTJ//zGQ=
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kermieisinthehouse/gosx-notifier v0.1.2 h1:KV0KBeKK2B24kIHY7iK0jgS64Q05f4oB+hUZmsPodxQ=
github.com/kermieisinthehouse/gosx-notifier v0.1.2/go.mod h1:xyWT07azFtUOcHl96qMVvKhvKzsMcS7rKTHQyv8WTho=
github.com/kermieisinthehouse/systray v1.2.4 h1:pdH5vnl+KKjRrVCRU4g/2W1/0HVzuuJ6WXHlPPHYY6s=
github.com/kermieisinthehouse/systray v1.2.4/go.mod h1:axh6C/jNuSyC0QGtidZJURc9h+h41HNoMySoLVrhVR4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
github.com/knadh/koanf/parsers/yaml v1.1.0/go.mod h1:HHmcHXUrp9cOPcuC+2wrr44GTUB0EC+PyfN3HZD9tFg=
github.com/knadh/koanf/providers/env v1.1.0 h1:U2VXPY0f+CsNDkvdsG8GcsnK4ah85WwWyJgef9oQMSc=
github.com/knadh/koanf/providers/env v1.1.0/go.mod h1:QhHHHZ87h9JxJAn2czdEl6pdkNnDh/JS1Vtsyt65hTY=
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/providers/posflag v1.0.1 h1:EnMxHSrPkYCFnKgBUl5KBgrjed8gVFrcXDzaW4l/C6Y=
github.com/knadh/koanf/providers/posflag v1.0.1/go.mod h1:3Wn3+YG3f4ljzRyCUgIwH7G0sZ1pMjCOsNBovrbKmAk=
github.com/knadh/koanf/v2 v2.2.1 h1:jaleChtw85y3UdBnI0wCqcg1sj1gPoz6D3caGNHtrNE=
github.com/knadh/koanf/v2 v2.2.1/go.mod h1:PSFru3ufQgTsI7IF+95rf9s8XA1+aHxKuO/W+dPoHEY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/natefinch/pie v0.0.0-20170715172608-9a0d72014007 h1:Ohgj9L0EYOgXxkDp+bczlMBiulwmqYzQpvQNUdtt3oc=
github.com/natefinch/pie v0.0.0-20170715172608-9a0d72014007/go.mod h1:wKCOWMb6iNlvKiOToY2cNuaovSXvIiv1zDi9QDR7aGQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4=
github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/vearutop/statigz v1.4.0 h1:RQL0KG3j/uyA/PFpHeZ/L6l2ta920/MxlOAIGEOuwmU=
github.com/vearutop/statigz v1.4.0/go.mod h1:LYTolBLiz9oJISwiVKnOQoIwhO1LWX1A7OECawGS8XE=
github.com/vektah/dataloaden v0.3.0 h1:ZfVN2QD6swgvp+tDqdH/OIT/wu3Dhu0cus0k5gIZS84=
github.com/vektah/dataloaden v0.3.0/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s=
github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
github.com/vektra/mockery/v2 v2.10.0 h1:MiiQWxwdq7/ET6dCXLaJzSGEN17k758H7JHS9kOdiks=
github.com/vektra/mockery/v2 v2.10.0/go.mod h1:m/WO2UzWzqgVX3nvqpRQq70I4Z7jbSCRhdmkgtp+Ab4=
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/xWTF/chardet v0.0.0-20230208095535-c780f2ac244e h1:GruPsb+44XvYAzuAgJW1d1WHqmcI73L2XSjsbx/eJZw=
github.com/xWTF/chardet v0.0.0-20230208095535-c780f2ac244e/go.mod h1:wA8kQ8WFipMciY9WcWzqQgZordm/P7l8IZdvx1crwmc=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zencoder/go-dash/v3 v3.0.2 h1:oP1+dOh+Gp57PkvdCyMfbHtrHaxfl3w4kR3KBBbuqQE=
github.com/zencoder/go-dash/v3 v3.0.2/go.mod h1:30R5bKy1aUYY45yesjtZ9l8trNc2TwNqbS17WVQmCzk=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190415214537-1da14a5a36f2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net
gitextract_5pun5gxb/
├── .dockerignore
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ ├── PULL_REQUEST_TEMPLATE/
│ │ ├── BugFix.md
│ │ └── Feature.md
│ └── workflows/
│ ├── build-compiler.yml
│ ├── build.yml
│ └── golangci-lint.yml
├── .gitignore
├── .golangci.yml
├── .gqlgenc.yml
├── .idea/
│ ├── codeStyles/
│ │ └── codeStyleConfig.xml
│ ├── dataSources.xml
│ ├── encodings.xml
│ ├── go.iml
│ ├── misc.xml
│ ├── modules.xml
│ ├── sqldialects.xml
│ └── vcs.xml
├── .mockery.yml
├── LICENSE
├── Makefile
├── README.md
├── cmd/
│ ├── phasher/
│ │ └── main.go
│ └── stash/
│ ├── main.go
│ └── main_test.go
├── docker/
│ ├── build/
│ │ └── x86_64/
│ │ ├── Dockerfile
│ │ ├── Dockerfile-CUDA
│ │ └── README.md
│ ├── ci/
│ │ └── x86_64/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ └── docker_push.sh
│ ├── compiler/
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ └── README.md
│ └── production/
│ ├── README.md
│ └── docker-compose.yml
├── docs/
│ ├── CONTRIBUTING.md
│ └── DEVELOPMENT.md
├── go.mod
├── go.sum
├── gqlgen.yml
├── graphql/
│ ├── schema/
│ │ ├── schema.graphql
│ │ └── types/
│ │ ├── config.graphql
│ │ ├── dlna.graphql
│ │ ├── file.graphql
│ │ ├── filters.graphql
│ │ ├── gallery-chapter.graphql
│ │ ├── gallery.graphql
│ │ ├── group.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── logging.graphql
│ │ ├── metadata.graphql
│ │ ├── migration.graphql
│ │ ├── movie.graphql
│ │ ├── package.graphql
│ │ ├── performer.graphql
│ │ ├── plugin.graphql
│ │ ├── scalars.graphql
│ │ ├── scene-marker-tag.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene.graphql
│ │ ├── scraped-group.graphql
│ │ ├── scraped-performer.graphql
│ │ ├── scraper.graphql
│ │ ├── sql.graphql
│ │ ├── stash-box.graphql
│ │ ├── stats.graphql
│ │ ├── studio.graphql
│ │ ├── tag.graphql
│ │ └── version.graphql
│ └── stash-box/
│ └── query.graphql
├── internal/
│ ├── api/
│ │ ├── authentication.go
│ │ ├── bool_map.go
│ │ ├── changeset_translator.go
│ │ ├── check_version.go
│ │ ├── context_keys.go
│ │ ├── custom_fields.go
│ │ ├── dir_list.go
│ │ ├── doc.go
│ │ ├── error.go
│ │ ├── fields.go
│ │ ├── images.go
│ │ ├── input.go
│ │ ├── json.go
│ │ ├── json_test.go
│ │ ├── loaders/
│ │ │ ├── customfieldsloader_gen.go
│ │ │ ├── dataloaders.go
│ │ │ ├── fileloader_gen.go
│ │ │ ├── folderloader_gen.go
│ │ │ ├── folderparentfolderidsloader_gen.go
│ │ │ ├── galleryfileidsloader_gen.go
│ │ │ ├── galleryloader_gen.go
│ │ │ ├── grouploader_gen.go
│ │ │ ├── imagefileidsloader_gen.go
│ │ │ ├── imageloader_gen.go
│ │ │ ├── performerloader_gen.go
│ │ │ ├── scenefileidsloader_gen.go
│ │ │ ├── scenelastplayedloader_gen.go
│ │ │ ├── sceneloader_gen.go
│ │ │ ├── sceneocountloader_gen.go
│ │ │ ├── sceneohistoryloader_gen.go
│ │ │ ├── sceneplaycountloader_gen.go
│ │ │ ├── sceneplayhistoryloader_gen.go
│ │ │ ├── studioloader_gen.go
│ │ │ └── tagloader_gen.go
│ │ ├── locale.go
│ │ ├── models.go
│ │ ├── plugin_map.go
│ │ ├── resolver.go
│ │ ├── resolver_model_config.go
│ │ ├── resolver_model_file.go
│ │ ├── resolver_model_folder.go
│ │ ├── resolver_model_gallery.go
│ │ ├── resolver_model_gallery_chapter.go
│ │ ├── resolver_model_image.go
│ │ ├── resolver_model_movie.go
│ │ ├── resolver_model_performer.go
│ │ ├── resolver_model_plugin.go
│ │ ├── resolver_model_saved_filter.go
│ │ ├── resolver_model_scene.go
│ │ ├── resolver_model_scene_marker.go
│ │ ├── resolver_model_studio.go
│ │ ├── resolver_model_tag.go
│ │ ├── resolver_mutation_configure.go
│ │ ├── resolver_mutation_dlna.go
│ │ ├── resolver_mutation_file.go
│ │ ├── resolver_mutation_gallery.go
│ │ ├── resolver_mutation_group.go
│ │ ├── resolver_mutation_image.go
│ │ ├── resolver_mutation_job.go
│ │ ├── resolver_mutation_metadata.go
│ │ ├── resolver_mutation_migrate.go
│ │ ├── resolver_mutation_movie.go
│ │ ├── resolver_mutation_package.go
│ │ ├── resolver_mutation_performer.go
│ │ ├── resolver_mutation_plugin.go
│ │ ├── resolver_mutation_saved_filter.go
│ │ ├── resolver_mutation_scene.go
│ │ ├── resolver_mutation_scraper.go
│ │ ├── resolver_mutation_stash_box.go
│ │ ├── resolver_mutation_studio.go
│ │ ├── resolver_mutation_tag.go
│ │ ├── resolver_mutation_tag_test.go
│ │ ├── resolver_query_configuration.go
│ │ ├── resolver_query_dlna.go
│ │ ├── resolver_query_find_file.go
│ │ ├── resolver_query_find_folder.go
│ │ ├── resolver_query_find_gallery.go
│ │ ├── resolver_query_find_group.go
│ │ ├── resolver_query_find_image.go
│ │ ├── resolver_query_find_movie.go
│ │ ├── resolver_query_find_performer.go
│ │ ├── resolver_query_find_saved_filter.go
│ │ ├── resolver_query_find_scene.go
│ │ ├── resolver_query_find_scene_marker.go
│ │ ├── resolver_query_find_studio.go
│ │ ├── resolver_query_find_tag.go
│ │ ├── resolver_query_job.go
│ │ ├── resolver_query_logs.go
│ │ ├── resolver_query_metadata.go
│ │ ├── resolver_query_package.go
│ │ ├── resolver_query_plugin.go
│ │ ├── resolver_query_scene.go
│ │ ├── resolver_query_scraper.go
│ │ ├── resolver_subscription_job.go
│ │ ├── resolver_subscription_logging.go
│ │ ├── routes.go
│ │ ├── routes_custom.go
│ │ ├── routes_downloads.go
│ │ ├── routes_gallery.go
│ │ ├── routes_group.go
│ │ ├── routes_image.go
│ │ ├── routes_performer.go
│ │ ├── routes_plugin.go
│ │ ├── routes_scene.go
│ │ ├── routes_studio.go
│ │ ├── routes_tag.go
│ │ ├── scraped_content.go
│ │ ├── server.go
│ │ ├── session.go
│ │ ├── stash_box.go
│ │ ├── timestamp.go
│ │ ├── timestamp_test.go
│ │ ├── types.go
│ │ └── urlbuilders/
│ │ ├── doc.go
│ │ ├── gallery.go
│ │ ├── group.go
│ │ ├── image.go
│ │ ├── performer.go
│ │ ├── scene.go
│ │ ├── scene_markers.go
│ │ ├── studio.go
│ │ └── tag.go
│ ├── autotag/
│ │ ├── doc.go
│ │ ├── gallery.go
│ │ ├── gallery_test.go
│ │ ├── image.go
│ │ ├── image_test.go
│ │ ├── integration_test.go
│ │ ├── performer.go
│ │ ├── performer_test.go
│ │ ├── scene.go
│ │ ├── scene_test.go
│ │ ├── studio.go
│ │ ├── studio_test.go
│ │ ├── tag.go
│ │ ├── tag_test.go
│ │ └── tagger.go
│ ├── build/
│ │ └── version.go
│ ├── desktop/
│ │ ├── desktop.go
│ │ ├── desktop_platform_darwin.go
│ │ ├── desktop_platform_nixes.go
│ │ ├── desktop_platform_windows.go
│ │ ├── dialog_nonwindows.go
│ │ ├── dialog_windows.go
│ │ ├── icon_windows.syso
│ │ ├── systray_nixes.go
│ │ └── systray_nonlinux.go
│ ├── dlna/
│ │ ├── activity.go
│ │ ├── activity_test.go
│ │ ├── cd-service-desc.go
│ │ ├── cds.go
│ │ ├── cds_test.go
│ │ ├── cm-service-desc.go
│ │ ├── cms.go
│ │ ├── dms.go
│ │ ├── doc.go
│ │ ├── html.go
│ │ ├── mrrs.go
│ │ ├── paging.go
│ │ ├── service.go
│ │ ├── whitelist.go
│ │ └── xmsr-service-desc.go
│ ├── identify/
│ │ ├── identify.go
│ │ ├── identify_test.go
│ │ ├── options.go
│ │ ├── performer.go
│ │ ├── performer_test.go
│ │ ├── scene.go
│ │ ├── scene_test.go
│ │ ├── studio.go
│ │ └── studio_test.go
│ ├── log/
│ │ ├── hook.go
│ │ ├── logger.go
│ │ └── progress_formatter.go
│ ├── manager/
│ │ ├── apikey.go
│ │ ├── backup.go
│ │ ├── checksum.go
│ │ ├── config/
│ │ │ ├── config.go
│ │ │ ├── config_concurrency_test.go
│ │ │ ├── config_test.go
│ │ │ ├── enums.go
│ │ │ ├── init.go
│ │ │ ├── stash_config.go
│ │ │ ├── tasks.go
│ │ │ └── ui.go
│ │ ├── downloads.go
│ │ ├── enums.go
│ │ ├── exclude_files.go
│ │ ├── exclude_files_test.go
│ │ ├── fingerprint.go
│ │ ├── generator.go
│ │ ├── generator_interactive_heatmap_speed.go
│ │ ├── generator_sprite.go
│ │ ├── import.go
│ │ ├── init.go
│ │ ├── json_utils.go
│ │ ├── log.go
│ │ ├── manager.go
│ │ ├── manager_tasks.go
│ │ ├── models.go
│ │ ├── repository.go
│ │ ├── running_streams.go
│ │ ├── scan_stashignore_test.go
│ │ ├── scene.go
│ │ ├── subscribe.go
│ │ ├── task/
│ │ │ ├── clean_generated.go
│ │ │ ├── download_ffmpeg.go
│ │ │ ├── migrate.go
│ │ │ ├── migrate_blobs.go
│ │ │ ├── migrate_scene_screenshots.go
│ │ │ └── packages.go
│ │ ├── task.go
│ │ ├── task_autotag.go
│ │ ├── task_clean.go
│ │ ├── task_export.go
│ │ ├── task_generate.go
│ │ ├── task_generate_clip_preview.go
│ │ ├── task_generate_image_phash.go
│ │ ├── task_generate_image_thumbnail.go
│ │ ├── task_generate_interactive_heatmap_speed.go
│ │ ├── task_generate_markers.go
│ │ ├── task_generate_phash.go
│ │ ├── task_generate_preview.go
│ │ ├── task_generate_screenshot.go
│ │ ├── task_generate_sprite.go
│ │ ├── task_identify.go
│ │ ├── task_import.go
│ │ ├── task_migrate_hash.go
│ │ ├── task_optimise.go
│ │ ├── task_plugin.go
│ │ ├── task_scan.go
│ │ ├── task_stash_box_tag.go
│ │ └── task_transcode.go
│ └── static/
│ ├── embed.go
│ ├── performer/
│ │ └── attribution.md
│ └── performer_male/
│ └── attribution.md
├── pkg/
│ ├── exec/
│ │ ├── command.go
│ │ ├── shell_nonwindows.go
│ │ └── shell_windows.go
│ ├── ffmpeg/
│ │ ├── browser.go
│ │ ├── codec.go
│ │ ├── codec_hardware.go
│ │ ├── container.go
│ │ ├── downloader.go
│ │ ├── ffmpeg.go
│ │ ├── ffmpeg_test.go
│ │ ├── ffprobe.go
│ │ ├── filter.go
│ │ ├── format.go
│ │ ├── frame_rate.go
│ │ ├── generate.go
│ │ ├── media_detection.go
│ │ ├── options.go
│ │ ├── stream.go
│ │ ├── stream_segmented.go
│ │ ├── stream_transcode.go
│ │ ├── transcoder/
│ │ │ ├── image.go
│ │ │ ├── screenshot.go
│ │ │ ├── splice.go
│ │ │ └── transcode.go
│ │ └── types.go
│ ├── file/
│ │ ├── clean.go
│ │ ├── delete.go
│ │ ├── file.go
│ │ ├── folder.go
│ │ ├── folder_rename_detect.go
│ │ ├── fs.go
│ │ ├── handler.go
│ │ ├── image/
│ │ │ ├── orientation.go
│ │ │ └── scan.go
│ │ ├── import.go
│ │ ├── move.go
│ │ ├── scan.go
│ │ ├── stashignore.go
│ │ ├── stashignore_test.go
│ │ ├── video/
│ │ │ ├── caption.go
│ │ │ ├── caption_test.go
│ │ │ ├── funscript.go
│ │ │ └── scan.go
│ │ ├── walk.go
│ │ └── zip.go
│ ├── fsutil/
│ │ ├── dir.go
│ │ ├── dir_test.go
│ │ ├── file.go
│ │ ├── file_test.go
│ │ ├── fs.go
│ │ ├── fs_test.go
│ │ ├── lock_manager.go
│ │ ├── symwalk.go
│ │ └── trash.go
│ ├── gallery/
│ │ ├── chapter_import.go
│ │ ├── delete.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── filter.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── scan.go
│ │ ├── scan_test.go
│ │ ├── service.go
│ │ ├── update.go
│ │ └── validation.go
│ ├── group/
│ │ ├── create.go
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── reorder.go
│ │ ├── service.go
│ │ ├── update.go
│ │ └── validate.go
│ ├── hash/
│ │ ├── imagephash/
│ │ │ └── phash.go
│ │ ├── key.go
│ │ ├── md5/
│ │ │ └── md5.go
│ │ ├── oshash/
│ │ │ ├── oshash.go
│ │ │ └── oshash_test.go
│ │ └── videophash/
│ │ └── phash.go
│ ├── image/
│ │ ├── delete.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── filter.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── scan.go
│ │ ├── scan_test.go
│ │ ├── service.go
│ │ ├── thumbnail.go
│ │ ├── update.go
│ │ ├── vips.go
│ │ ├── webp.go
│ │ └── webp_internal_test.go
│ ├── javascript/
│ │ ├── console.go
│ │ ├── gql.go
│ │ ├── log.go
│ │ ├── util.go
│ │ └── vm.go
│ ├── job/
│ │ ├── job.go
│ │ ├── manager.go
│ │ ├── manager_test.go
│ │ ├── progress.go
│ │ ├── progress_test.go
│ │ ├── subscribe.go
│ │ └── task.go
│ ├── logger/
│ │ ├── basic.go
│ │ ├── logger.go
│ │ ├── plugin.go
│ │ └── progress_formatter.go
│ ├── match/
│ │ ├── cache.go
│ │ ├── path.go
│ │ ├── path_test.go
│ │ └── scraped.go
│ ├── models/
│ │ ├── custom_fields.go
│ │ ├── date.go
│ │ ├── date_test.go
│ │ ├── doc.go
│ │ ├── errors.go
│ │ ├── file.go
│ │ ├── filename_parser.go
│ │ ├── filter.go
│ │ ├── find_filter.go
│ │ ├── fingerprint.go
│ │ ├── fingerprint_test.go
│ │ ├── folder.go
│ │ ├── fs.go
│ │ ├── gallery.go
│ │ ├── generate.go
│ │ ├── group.go
│ │ ├── image.go
│ │ ├── import.go
│ │ ├── json/
│ │ │ └── json_time.go
│ │ ├── jsonschema/
│ │ │ ├── doc.go
│ │ │ ├── file_folder.go
│ │ │ ├── folder.go
│ │ │ ├── gallery.go
│ │ │ ├── group.go
│ │ │ ├── image.go
│ │ │ ├── load.go
│ │ │ ├── performer.go
│ │ │ ├── performer_test.go
│ │ │ ├── saved_filter.go
│ │ │ ├── scene.go
│ │ │ ├── studio.go
│ │ │ ├── tag.go
│ │ │ └── utils.go
│ │ ├── mocks/
│ │ │ ├── FileReaderWriter.go
│ │ │ ├── FolderReaderWriter.go
│ │ │ ├── GalleryChapterReaderWriter.go
│ │ │ ├── GalleryReaderWriter.go
│ │ │ ├── GroupReaderWriter.go
│ │ │ ├── ImageReaderWriter.go
│ │ │ ├── PerformerReaderWriter.go
│ │ │ ├── SavedFilterReaderWriter.go
│ │ │ ├── SceneMarkerReaderWriter.go
│ │ │ ├── SceneReaderWriter.go
│ │ │ ├── StudioReaderWriter.go
│ │ │ ├── TagReaderWriter.go
│ │ │ ├── database.go
│ │ │ └── query.go
│ │ ├── model_file.go
│ │ ├── model_folder.go
│ │ ├── model_gallery.go
│ │ ├── model_gallery_chapter.go
│ │ ├── model_group.go
│ │ ├── model_image.go
│ │ ├── model_joins.go
│ │ ├── model_performer.go
│ │ ├── model_saved_filter.go
│ │ ├── model_scene.go
│ │ ├── model_scene_marker.go
│ │ ├── model_scene_test.go
│ │ ├── model_scraped_item.go
│ │ ├── model_scraped_item_test.go
│ │ ├── model_studio.go
│ │ ├── model_tag.go
│ │ ├── orientation.go
│ │ ├── package.go
│ │ ├── paths/
│ │ │ ├── paths.go
│ │ │ ├── paths_generated.go
│ │ │ ├── paths_json.go
│ │ │ ├── paths_scene_markers.go
│ │ │ └── paths_scenes.go
│ │ ├── performer.go
│ │ ├── query.go
│ │ ├── rating.go
│ │ ├── rating_test.go
│ │ ├── relationships.go
│ │ ├── repository.go
│ │ ├── repository_blob.go
│ │ ├── repository_file.go
│ │ ├── repository_folder.go
│ │ ├── repository_gallery.go
│ │ ├── repository_gallery_chapter.go
│ │ ├── repository_group.go
│ │ ├── repository_image.go
│ │ ├── repository_performer.go
│ │ ├── repository_scene.go
│ │ ├── repository_scene_marker.go
│ │ ├── repository_studio.go
│ │ ├── repository_tag.go
│ │ ├── resolution.go
│ │ ├── saved_filter.go
│ │ ├── scene.go
│ │ ├── scene_marker.go
│ │ ├── search.go
│ │ ├── search_test.go
│ │ ├── stash_box.go
│ │ ├── stash_ids.go
│ │ ├── studio.go
│ │ ├── tag.go
│ │ ├── update.go
│ │ ├── update_test.go
│ │ └── value.go
│ ├── performer/
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── url.go
│ │ ├── validate.go
│ │ └── validate_test.go
│ ├── pkg/
│ │ ├── cache.go
│ │ ├── manager.go
│ │ ├── pkg.go
│ │ ├── repository.go
│ │ ├── repository_http.go
│ │ ├── repository_http_test.go
│ │ └── store.go
│ ├── plugin/
│ │ ├── args.go
│ │ ├── common/
│ │ │ ├── doc.go
│ │ │ ├── log/
│ │ │ │ └── log.go
│ │ │ ├── msg.go
│ │ │ └── rpc.go
│ │ ├── config.go
│ │ ├── convert.go
│ │ ├── examples/
│ │ │ ├── README.md
│ │ │ ├── common/
│ │ │ │ └── graphql.go
│ │ │ ├── goraw/
│ │ │ │ ├── goraw.yml
│ │ │ │ └── main.go
│ │ │ ├── gorpc/
│ │ │ │ ├── gorpc.yml
│ │ │ │ └── main.go
│ │ │ ├── js/
│ │ │ │ ├── js.js
│ │ │ │ └── js.yml
│ │ │ ├── python/
│ │ │ │ ├── log.py
│ │ │ │ ├── pyplugin.py
│ │ │ │ ├── pyraw.yml
│ │ │ │ └── stash_interface.py
│ │ │ └── react-component/
│ │ │ ├── README.md
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ ├── testReact.scss
│ │ │ │ ├── testReact.tsx
│ │ │ │ └── testReact.yml
│ │ │ └── tsconfig.json
│ │ ├── hook/
│ │ │ └── hooks.go
│ │ ├── hooks.go
│ │ ├── js.go
│ │ ├── log.go
│ │ ├── plugins.go
│ │ ├── raw.go
│ │ ├── rpc.go
│ │ ├── setting.go
│ │ ├── task.go
│ │ └── util/
│ │ └── client.go
│ ├── python/
│ │ ├── env.go
│ │ └── exec.go
│ ├── savedfilter/
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ └── import_test.go
│ ├── scene/
│ │ ├── create.go
│ │ ├── delete.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── filename_parser.go
│ │ ├── filter.go
│ │ ├── find.go
│ │ ├── fingerprints.go
│ │ ├── generate/
│ │ │ ├── generator.go
│ │ │ ├── marker_preview.go
│ │ │ ├── preview.go
│ │ │ ├── screenshot.go
│ │ │ ├── sprite.go
│ │ │ └── transcode.go
│ │ ├── hash.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── marker_import.go
│ │ ├── marker_import_test.go
│ │ ├── marker_query.go
│ │ ├── merge.go
│ │ ├── migrate_hash.go
│ │ ├── migrate_screenshots.go
│ │ ├── query.go
│ │ ├── scan.go
│ │ ├── scan_test.go
│ │ ├── service.go
│ │ ├── update.go
│ │ └── update_test.go
│ ├── scraper/
│ │ ├── action.go
│ │ ├── autotag.go
│ │ ├── cache.go
│ │ ├── cookies.go
│ │ ├── country.go
│ │ ├── defined_scraper.go
│ │ ├── definition.go
│ │ ├── freeones.go
│ │ ├── graphql.go
│ │ ├── image.go
│ │ ├── json.go
│ │ ├── json_test.go
│ │ ├── mapped.go
│ │ ├── mapped_config.go
│ │ ├── mapped_postprocessing.go
│ │ ├── mapped_result.go
│ │ ├── mapped_result_test.go
│ │ ├── mapped_test.go
│ │ ├── movie.go
│ │ ├── performer.go
│ │ ├── post_processing_test.go
│ │ ├── postprocessing.go
│ │ ├── query_url.go
│ │ ├── scraper.go
│ │ ├── script.go
│ │ ├── stash.go
│ │ ├── tag.go
│ │ ├── url.go
│ │ ├── xpath.go
│ │ └── xpath_test.go
│ ├── session/
│ │ ├── authentication.go
│ │ ├── authentication_test.go
│ │ ├── config.go
│ │ ├── local.go
│ │ ├── plugin.go
│ │ └── session.go
│ ├── sliceutil/
│ │ ├── collections.go
│ │ ├── collections_test.go
│ │ ├── intslice/
│ │ │ └── int_collections.go
│ │ └── stringslice/
│ │ └── string_collections.go
│ ├── sqlite/
│ │ ├── anonymise.go
│ │ ├── anonymise_test.go
│ │ ├── batch.go
│ │ ├── blob/
│ │ │ └── fs.go
│ │ ├── blob.go
│ │ ├── blob_migrate.go
│ │ ├── blob_test.go
│ │ ├── common.go
│ │ ├── criterion_handlers.go
│ │ ├── custom_fields.go
│ │ ├── custom_fields_test.go
│ │ ├── custom_migrations.go
│ │ ├── database.go
│ │ ├── date.go
│ │ ├── doc.go
│ │ ├── driver.go
│ │ ├── file.go
│ │ ├── file_filter.go
│ │ ├── file_filter_test.go
│ │ ├── file_test.go
│ │ ├── filter.go
│ │ ├── filter_hierarchical.go
│ │ ├── filter_internal_test.go
│ │ ├── fingerprint.go
│ │ ├── folder.go
│ │ ├── folder_filter.go
│ │ ├── folder_filter_test.go
│ │ ├── folder_test.go
│ │ ├── functions.go
│ │ ├── gallery.go
│ │ ├── gallery_chapter.go
│ │ ├── gallery_chapter_test.go
│ │ ├── gallery_filter.go
│ │ ├── gallery_test.go
│ │ ├── group.go
│ │ ├── group_filter.go
│ │ ├── group_relationships.go
│ │ ├── group_test.go
│ │ ├── history.go
│ │ ├── image.go
│ │ ├── image_filter.go
│ │ ├── image_test.go
│ │ ├── migrate.go
│ │ ├── migrations/
│ │ │ ├── 10_image_tables.up.sql
│ │ │ ├── 11_tag_image.up.sql
│ │ │ ├── 12_oshash.up.sql
│ │ │ ├── 12_postmigrate.go
│ │ │ ├── 13_images.up.sql
│ │ │ ├── 14_stash_box_ids.up.sql
│ │ │ ├── 15_file_mod_time.up.sql
│ │ │ ├── 16_organized_flag.up.sql
│ │ │ ├── 17_reset_scene_size.up.sql
│ │ │ ├── 18_scene_galleries.up.sql
│ │ │ ├── 19_performer_tags.up.sql
│ │ │ ├── 1_initial.down.sql
│ │ │ ├── 1_initial.up.sql
│ │ │ ├── 20_phash.up.sql
│ │ │ ├── 21_performers_studios_details.up.sql
│ │ │ ├── 22_performers_studios_rating.up.sql
│ │ │ ├── 23_scenes_interactive.up.sql
│ │ │ ├── 24_tag_aliases.up.sql
│ │ │ ├── 25_saved_filters.up.sql
│ │ │ ├── 26_tag_hierarchy.up.sql
│ │ │ ├── 27_studio_aliases.up.sql
│ │ │ ├── 28_images_indexes.up.sql
│ │ │ ├── 29_interactive_speed.up.sql
│ │ │ ├── 2_cover_image.up.sql
│ │ │ ├── 30_ignore_autotag.up..sql
│ │ │ ├── 31_scenes_captions.up.sql
│ │ │ ├── 32_files.up.sql
│ │ │ ├── 32_postmigrate.go
│ │ │ ├── 32_premigrate.go
│ │ │ ├── 33_noop.up.sql
│ │ │ ├── 34_indexes.up.sql
│ │ │ ├── 34_postmigrate.go
│ │ │ ├── 35_assoc_tables.up.sql
│ │ │ ├── 36_tags_description.up.sql
│ │ │ ├── 37_iso_country_names.up.sql
│ │ │ ├── 38_scenes_director_code.up.sql
│ │ │ ├── 39_performer_height.up.sql
│ │ │ ├── 3_o_counter.up.sql
│ │ │ ├── 40_newratings.up.sql
│ │ │ ├── 41_scene_activity.up.sql
│ │ │ ├── 42_performer_disambig_aliases.up.sql
│ │ │ ├── 42_postmigrate.go
│ │ │ ├── 43_image_date_url.up.sql
│ │ │ ├── 44_gallery_chapters.up.sql
│ │ │ ├── 45_blobs.up.sql
│ │ │ ├── 45_postmigrate.go
│ │ │ ├── 46_penis_stats.up.sql
│ │ │ ├── 47_scene_urls.up.sql
│ │ │ ├── 48_cleanup.up.sql
│ │ │ ├── 48_premigrate.go
│ │ │ ├── 49_postmigrate.go
│ │ │ ├── 49_saved_filter_refactor.up.sql
│ │ │ ├── 4_movie.up.sql
│ │ │ ├── 50_image_urls.up.sql
│ │ │ ├── 51_gallery_urls.up.sql
│ │ │ ├── 52_postmigrate.go
│ │ │ ├── 52_zip_folder_data_correct.up.sql
│ │ │ ├── 53_gallery_photographer_code.up.sql
│ │ │ ├── 54_image_code_details_photographer.up.sql
│ │ │ ├── 55_manual_history.up.sql
│ │ │ ├── 55_postmigrate.go
│ │ │ ├── 56_studio_favorite.up.sql
│ │ │ ├── 57_tag_favorite.up.sql
│ │ │ ├── 58_config_correct.up.sql
│ │ │ ├── 58_postmigrate.go
│ │ │ ├── 59_movie_urls.up.sql
│ │ │ ├── 5_performer_gender.down.sql
│ │ │ ├── 5_performer_gender.up.sql
│ │ │ ├── 60_default_filter_move.up.sql
│ │ │ ├── 60_postmigrate.go
│ │ │ ├── 61_movie_tags.up.sql
│ │ │ ├── 62_performer_urls.up.sql
│ │ │ ├── 63_studio_tags.up.sql
│ │ │ ├── 64_fixes.up.sql
│ │ │ ├── 64_postmigrate.go
│ │ │ ├── 65_movie_group_rename.up.sql
│ │ │ ├── 65_postmigrate.go
│ │ │ ├── 66_gallery_cover.up.sql
│ │ │ ├── 67_group_relationships.up.sql
│ │ │ ├── 68_image_studio_index.up.sql
│ │ │ ├── 69_stash_id_updated_at.up.sql
│ │ │ ├── 6_scenes_format.up.sql
│ │ │ ├── 70_markers_end.up.sql
│ │ │ ├── 71_custom_fields.up.sql
│ │ │ ├── 72_tag_sort_name.up.sql
│ │ │ ├── 73_studio_urls.up.sql
│ │ │ ├── 74_tag_stash_ids.up.sql
│ │ │ ├── 75_date_precision.up.sql
│ │ │ ├── 76_studio_custom_fields.up.sql
│ │ │ ├── 77_tag_custom_fields.up.sql
│ │ │ ├── 78_performer_career_dates.up.sql
│ │ │ ├── 78_postmigrate.go
│ │ │ ├── 79_scene_custom_fields.up.sql
│ │ │ ├── 7_performer_optimization.up.sql
│ │ │ ├── 80_studio_organized.up.sql
│ │ │ ├── 81_gallery_custom_fields.up.sql
│ │ │ ├── 82_group_custom_fields.up.sql
│ │ │ ├── 83_image_custom_fields.up.sql
│ │ │ ├── 84_folder_basename.up.sql
│ │ │ ├── 84_postmigrate.go
│ │ │ ├── 85_performer_career_dates.up.sql
│ │ │ ├── 8_movie_fix.up.sql
│ │ │ ├── 9_studios_parent_studio.up.sql
│ │ │ ├── README.md
│ │ │ └── custom_migration.go
│ │ ├── performer.go
│ │ ├── performer_filter.go
│ │ ├── performer_test.go
│ │ ├── phash.go
│ │ ├── query.go
│ │ ├── record.go
│ │ ├── regex.go
│ │ ├── relationships.go
│ │ ├── repository.go
│ │ ├── saved_filter.go
│ │ ├── saved_filter_test.go
│ │ ├── scene.go
│ │ ├── scene_filter.go
│ │ ├── scene_marker.go
│ │ ├── scene_marker_filter.go
│ │ ├── scene_marker_test.go
│ │ ├── scene_test.go
│ │ ├── setup_test.go
│ │ ├── sql.go
│ │ ├── stash_id_test.go
│ │ ├── studio.go
│ │ ├── studio_filter.go
│ │ ├── studio_test.go
│ │ ├── table.go
│ │ ├── tables.go
│ │ ├── tag.go
│ │ ├── tag_filter.go
│ │ ├── tag_test.go
│ │ ├── timestamp.go
│ │ ├── transaction.go
│ │ ├── transaction_test.go
│ │ ├── tx.go
│ │ └── values.go
│ ├── stashbox/
│ │ ├── client.go
│ │ ├── draft.go
│ │ ├── graphql/
│ │ │ ├── generated_client.go
│ │ │ └── generated_models.go
│ │ ├── performer.go
│ │ ├── scene.go
│ │ ├── studio.go
│ │ └── tag.go
│ ├── studio/
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── validate.go
│ │ └── validate_test.go
│ ├── tag/
│ │ ├── doc.go
│ │ ├── export.go
│ │ ├── export_test.go
│ │ ├── import.go
│ │ ├── import_test.go
│ │ ├── query.go
│ │ ├── update.go
│ │ ├── update_test.go
│ │ ├── validate.go
│ │ └── validate_test.go
│ ├── txn/
│ │ ├── hooks.go
│ │ └── transaction.go
│ └── utils/
│ ├── boolean.go
│ ├── date.go
│ ├── date_test.go
│ ├── doc.go
│ ├── func.go
│ ├── http.go
│ ├── image.go
│ ├── map.go
│ ├── map_test.go
│ ├── mutex.go
│ ├── mutex_test.go
│ ├── phash.go
│ ├── reflect.go
│ ├── reflect_test.go
│ ├── resources.go
│ ├── strings.go
│ ├── strings_test.go
│ ├── time.go
│ ├── url.go
│ ├── url_test.go
│ ├── urlmap.go
│ ├── urlmap_test.go
│ ├── user_agent.go
│ ├── vtt.go
│ └── vtt_test.go
├── scripts/
│ ├── generateLoginLocales.go
│ ├── generate_icons.sh
│ ├── getDate.go
│ ├── macos-bundle/
│ │ └── Contents/
│ │ ├── Info.plist
│ │ └── Resources/
│ │ └── icon.icns
│ └── test_db_generator/
│ ├── README.md
│ ├── config.yml
│ ├── female.txt
│ ├── makeTestDB.go
│ ├── male.txt
│ ├── naming.go
│ ├── scene.txt
│ ├── studio.txt
│ └── surname.txt
├── tools.go
└── ui/
├── login/
│ ├── login.css
│ └── login.html
├── ui.go
└── v2.5/
├── .editorconfig
├── .eslintrc.json
├── .prettierignore
├── .stylelintrc
├── README.md
├── codegen.ts
├── graphql/
│ ├── client-schema.graphql
│ ├── data/
│ │ ├── config.graphql
│ │ ├── file.graphql
│ │ ├── filter.graphql
│ │ ├── gallery-chapter.graphql
│ │ ├── gallery-slim.graphql
│ │ ├── gallery.graphql
│ │ ├── group-slim.graphql
│ │ ├── group.graphql
│ │ ├── image-slim.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── log.graphql
│ │ ├── package.graphql
│ │ ├── performer-slim.graphql
│ │ ├── performer.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene-slim.graphql
│ │ ├── scene.graphql
│ │ ├── scrapers.graphql
│ │ ├── studio-slim.graphql
│ │ ├── studio.graphql
│ │ ├── tag-slim.graphql
│ │ └── tag.graphql
│ ├── mutations/
│ │ ├── config.graphql
│ │ ├── dlna.graphql
│ │ ├── file.graphql
│ │ ├── filter.graphql
│ │ ├── gallery-chapter.graphql
│ │ ├── gallery.graphql
│ │ ├── group.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── metadata.graphql
│ │ ├── migration.graphql
│ │ ├── performer.graphql
│ │ ├── plugins.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene.graphql
│ │ ├── scrapers.graphql
│ │ ├── stash-box.graphql
│ │ ├── studio.graphql
│ │ └── tag.graphql
│ ├── queries/
│ │ ├── dlna.graphql
│ │ ├── filter.graphql
│ │ ├── folder.graphql
│ │ ├── gallery.graphql
│ │ ├── image.graphql
│ │ ├── job.graphql
│ │ ├── legacy.graphql
│ │ ├── misc.graphql
│ │ ├── movie.graphql
│ │ ├── performer.graphql
│ │ ├── plugins.graphql
│ │ ├── scene-marker.graphql
│ │ ├── scene.graphql
│ │ ├── scrapers/
│ │ │ └── scrapers.graphql
│ │ ├── settings/
│ │ │ ├── config.graphql
│ │ │ └── metadata.graphql
│ │ ├── studio.graphql
│ │ └── tag.graphql
│ └── subscriptions.graphql
├── index.html
├── package.json
├── pnpm-workspace.yaml
├── public/
│ └── manifest.json
├── src/
│ ├── @types/
│ │ ├── mousetrap-pause.d.ts
│ │ ├── string.prototype.replaceall.d.ts
│ │ ├── videojs-abloop.d.ts
│ │ ├── videojs-contrib-dash.d.ts
│ │ ├── videojs-vr.d.ts
│ │ └── videojs-vtt.d.ts
│ ├── App.tsx
│ ├── ConnectionMonitor.tsx
│ ├── components/
│ │ ├── Changelog/
│ │ │ ├── Changelog.tsx
│ │ │ ├── Version.tsx
│ │ │ └── styles.scss
│ │ ├── Dialogs/
│ │ │ ├── GenerateDialog.tsx
│ │ │ ├── IdentifyDialog/
│ │ │ │ ├── FieldOptions.tsx
│ │ │ │ ├── IdentifyDialog.tsx
│ │ │ │ ├── Options.tsx
│ │ │ │ ├── Sources.tsx
│ │ │ │ ├── ThreeStateBoolean.tsx
│ │ │ │ ├── constants.ts
│ │ │ │ └── styles.scss
│ │ │ ├── ReleaseNotesDialog.tsx
│ │ │ ├── SubmitDraft.tsx
│ │ │ └── styles.scss
│ │ ├── ErrorBoundary.tsx
│ │ ├── FrontPage/
│ │ │ ├── Control.tsx
│ │ │ ├── FilteredRecommendationRow.tsx
│ │ │ ├── FrontPage.tsx
│ │ │ ├── FrontPageConfig.tsx
│ │ │ ├── RecommendationRow.tsx
│ │ │ └── styles.scss
│ │ ├── Galleries/
│ │ │ ├── DeleteGalleriesDialog.tsx
│ │ │ ├── EditGalleriesDialog.tsx
│ │ │ ├── Galleries.tsx
│ │ │ ├── GalleryCard.tsx
│ │ │ ├── GalleryCardGrid.tsx
│ │ │ ├── GalleryDetails/
│ │ │ │ ├── ChapterEntry.tsx
│ │ │ │ ├── Gallery.tsx
│ │ │ │ ├── GalleryAddPanel.tsx
│ │ │ │ ├── GalleryChapterForm.tsx
│ │ │ │ ├── GalleryChaptersPanel.tsx
│ │ │ │ ├── GalleryCreate.tsx
│ │ │ │ ├── GalleryDetailPanel.tsx
│ │ │ │ ├── GalleryEditPanel.tsx
│ │ │ │ ├── GalleryFileInfoPanel.tsx
│ │ │ │ ├── GalleryImagesPanel.tsx
│ │ │ │ ├── GalleryScenesPanel.tsx
│ │ │ │ └── GalleryScrapeDialog.tsx
│ │ │ ├── GalleryList.tsx
│ │ │ ├── GalleryListTable.tsx
│ │ │ ├── GalleryPreviewScrubber.tsx
│ │ │ ├── GalleryRecommendationRow.tsx
│ │ │ ├── GallerySelect.tsx
│ │ │ ├── GalleryViewer.tsx
│ │ │ ├── GalleryWallCard.tsx
│ │ │ └── styles.scss
│ │ ├── Groups/
│ │ │ ├── ContainingGroupsMultiSet.tsx
│ │ │ ├── EditGroupsDialog.tsx
│ │ │ ├── GroupCard.tsx
│ │ │ ├── GroupCardGrid.tsx
│ │ │ ├── GroupDetails/
│ │ │ │ ├── AddGroupsDialog.tsx
│ │ │ │ ├── Group.tsx
│ │ │ │ ├── GroupCreate.tsx
│ │ │ │ ├── GroupDetailsPanel.tsx
│ │ │ │ ├── GroupEditPanel.tsx
│ │ │ │ ├── GroupPerformersPanel.tsx
│ │ │ │ ├── GroupScenesPanel.tsx
│ │ │ │ ├── GroupScrapeDialog.tsx
│ │ │ │ ├── GroupSubGroupsPanel.tsx
│ │ │ │ └── RelatedGroupTable.tsx
│ │ │ ├── GroupList.tsx
│ │ │ ├── GroupRecommendationRow.tsx
│ │ │ ├── GroupSelect.tsx
│ │ │ ├── GroupTag.tsx
│ │ │ ├── Groups.tsx
│ │ │ ├── RelatedGroupPopover.tsx
│ │ │ └── styles.scss
│ │ ├── Help/
│ │ │ ├── Manual.tsx
│ │ │ ├── context.tsx
│ │ │ └── styles.scss
│ │ ├── Images/
│ │ │ ├── DeleteImagesDialog.tsx
│ │ │ ├── EditImagesDialog.tsx
│ │ │ ├── ImageCard.tsx
│ │ │ ├── ImageCardGrid.tsx
│ │ │ ├── ImageDetails/
│ │ │ │ ├── Image.tsx
│ │ │ │ ├── ImageDetailPanel.tsx
│ │ │ │ ├── ImageEditPanel.tsx
│ │ │ │ ├── ImageFileInfoPanel.tsx
│ │ │ │ └── ImageScrapeDialog.tsx
│ │ │ ├── ImageList.tsx
│ │ │ ├── ImageRecommendationRow.tsx
│ │ │ ├── ImageWallItem.tsx
│ │ │ ├── Images.tsx
│ │ │ └── styles.scss
│ │ ├── List/
│ │ │ ├── CriterionEditor.tsx
│ │ │ ├── EditFilterDialog.tsx
│ │ │ ├── FilterProvider.tsx
│ │ │ ├── FilterTags.tsx
│ │ │ ├── FilteredListToolbar.tsx
│ │ │ ├── Filters/
│ │ │ │ ├── BooleanFilter.tsx
│ │ │ │ ├── CustomFieldsFilter.tsx
│ │ │ │ ├── DateFilter.tsx
│ │ │ │ ├── DuplicateFilter.tsx
│ │ │ │ ├── DurationFilter.tsx
│ │ │ │ ├── FilterButton.tsx
│ │ │ │ ├── FilterSidebar.tsx
│ │ │ │ ├── FolderFilter.tsx
│ │ │ │ ├── HierarchicalLabelValueFilter.tsx
│ │ │ │ ├── InputFilter.tsx
│ │ │ │ ├── LabeledIdFilter.tsx
│ │ │ │ ├── NumberFilter.tsx
│ │ │ │ ├── OptionFilter.tsx
│ │ │ │ ├── PathFilter.tsx
│ │ │ │ ├── PerformersFilter.tsx
│ │ │ │ ├── PhashFilter.tsx
│ │ │ │ ├── RatingFilter.tsx
│ │ │ │ ├── SelectableFilter.tsx
│ │ │ │ ├── SidebarAgeFilter.tsx
│ │ │ │ ├── SidebarDurationFilter.tsx
│ │ │ │ ├── SidebarListFilter.tsx
│ │ │ │ ├── StashIDFilter.tsx
│ │ │ │ ├── StudiosFilter.tsx
│ │ │ │ ├── TagsFilter.tsx
│ │ │ │ └── TimestampFilter.tsx
│ │ │ ├── ItemList.tsx
│ │ │ ├── ListFilter.tsx
│ │ │ ├── ListOperationButtons.tsx
│ │ │ ├── ListProvider.tsx
│ │ │ ├── ListTable.tsx
│ │ │ ├── ListViewOptions.tsx
│ │ │ ├── ModifierSelect.tsx
│ │ │ ├── PagedList.tsx
│ │ │ ├── Pagination.tsx
│ │ │ ├── SavedFilterList.tsx
│ │ │ ├── ZoomSlider.tsx
│ │ │ ├── styles.scss
│ │ │ ├── util.ts
│ │ │ └── views.ts
│ │ ├── MainNavbar.tsx
│ │ ├── PageNotFound.tsx
│ │ ├── Performers/
│ │ │ ├── EditPerformersDialog.tsx
│ │ │ ├── GenderIcon.tsx
│ │ │ ├── PerformerCard.tsx
│ │ │ ├── PerformerCardGrid.tsx
│ │ │ ├── PerformerDetails/
│ │ │ │ ├── Performer.tsx
│ │ │ │ ├── PerformerCreate.tsx
│ │ │ │ ├── PerformerDetailsPanel.tsx
│ │ │ │ ├── PerformerEditPanel.tsx
│ │ │ │ ├── PerformerGalleriesPanel.tsx
│ │ │ │ ├── PerformerGroupsPanel.tsx
│ │ │ │ ├── PerformerImagesPanel.tsx
│ │ │ │ ├── PerformerScenesPanel.tsx
│ │ │ │ ├── PerformerScrapeDialog.tsx
│ │ │ │ ├── PerformerScrapeModal.tsx
│ │ │ │ ├── PerformerStashBoxModal.tsx
│ │ │ │ ├── PerformerSubmitButton.tsx
│ │ │ │ └── performerAppearsWithPanel.tsx
│ │ │ ├── PerformerList.tsx
│ │ │ ├── PerformerListTable.tsx
│ │ │ ├── PerformerMergeDialog.tsx
│ │ │ ├── PerformerPopover.tsx
│ │ │ ├── PerformerRecommendationRow.tsx
│ │ │ ├── PerformerSelect.tsx
│ │ │ ├── Performers.tsx
│ │ │ └── styles.scss
│ │ ├── SceneDuplicateChecker/
│ │ │ ├── SceneDuplicateChecker.tsx
│ │ │ └── styles.scss
│ │ ├── SceneFilenameParser/
│ │ │ ├── ParserField.ts
│ │ │ ├── ParserInput.tsx
│ │ │ ├── SceneFilenameParser.tsx
│ │ │ ├── SceneParserRow.tsx
│ │ │ ├── ShowFields.tsx
│ │ │ └── styles.scss
│ │ ├── ScenePlayer/
│ │ │ ├── PlaylistButtons.ts
│ │ │ ├── ScenePlayer.tsx
│ │ │ ├── ScenePlayerScrubber.tsx
│ │ │ ├── autostart-button.ts
│ │ │ ├── big-buttons.ts
│ │ │ ├── live.ts
│ │ │ ├── markers.ts
│ │ │ ├── media-session.ts
│ │ │ ├── persist-volume.ts
│ │ │ ├── source-selector.ts
│ │ │ ├── styles.scss
│ │ │ ├── track-activity.ts
│ │ │ ├── util.ts
│ │ │ ├── vrmode.ts
│ │ │ ├── vtt-thumbnails.ts
│ │ │ └── wake-sentinel.ts
│ │ ├── Scenes/
│ │ │ ├── DeleteSceneMarkersDialog.tsx
│ │ │ ├── DeleteScenesDialog.tsx
│ │ │ ├── EditSceneMarkersDialog.tsx
│ │ │ ├── EditScenesDialog.tsx
│ │ │ ├── PreviewScrubber.tsx
│ │ │ ├── SceneCard.tsx
│ │ │ ├── SceneCardGrid.tsx
│ │ │ ├── SceneDetails/
│ │ │ │ ├── ExternalPlayerButton.tsx
│ │ │ │ ├── OCounterButton.tsx
│ │ │ │ ├── OrganizedButton.tsx
│ │ │ │ ├── PrimaryTags.tsx
│ │ │ │ ├── QueueViewer.tsx
│ │ │ │ ├── Scene.tsx
│ │ │ │ ├── SceneCreate.tsx
│ │ │ │ ├── SceneDetailPanel.tsx
│ │ │ │ ├── SceneEditPanel.tsx
│ │ │ │ ├── SceneFileInfoPanel.tsx
│ │ │ │ ├── SceneGalleriesPanel.tsx
│ │ │ │ ├── SceneGroupPanel.tsx
│ │ │ │ ├── SceneGroupTable.tsx
│ │ │ │ ├── SceneHistoryPanel.tsx
│ │ │ │ ├── SceneMarkerForm.tsx
│ │ │ │ ├── SceneMarkersPanel.tsx
│ │ │ │ ├── SceneQueryModal.tsx
│ │ │ │ ├── SceneScrapeDialog.tsx
│ │ │ │ └── SceneVideoFilterPanel.tsx
│ │ │ ├── SceneList.tsx
│ │ │ ├── SceneListTable.tsx
│ │ │ ├── SceneMarkerCard.tsx
│ │ │ ├── SceneMarkerCardGrid.tsx
│ │ │ ├── SceneMarkerList.tsx
│ │ │ ├── SceneMarkerRecommendationRow.tsx
│ │ │ ├── SceneMarkerWallPanel.tsx
│ │ │ ├── SceneMergeDialog.tsx
│ │ │ ├── SceneRecommendationRow.tsx
│ │ │ ├── SceneSelect.tsx
│ │ │ ├── SceneWallPanel.tsx
│ │ │ ├── Scenes.tsx
│ │ │ └── styles.scss
│ │ ├── Settings/
│ │ │ ├── GeneratePreviewOptions.tsx
│ │ │ ├── Inputs.tsx
│ │ │ ├── PluginPackageManager.tsx
│ │ │ ├── ScraperPackageManager.tsx
│ │ │ ├── SettingSection.tsx
│ │ │ ├── Settings.tsx
│ │ │ ├── SettingsAboutPanel.tsx
│ │ │ ├── SettingsInterfacePanel/
│ │ │ │ ├── CheckboxGroup.tsx
│ │ │ │ └── SettingsInterfacePanel.tsx
│ │ │ ├── SettingsLibraryPanel.tsx
│ │ │ ├── SettingsLogsPanel.tsx
│ │ │ ├── SettingsPluginsPanel.tsx
│ │ │ ├── SettingsScrapingPanel.tsx
│ │ │ ├── SettingsSecurityPanel.tsx
│ │ │ ├── SettingsServicesPanel.tsx
│ │ │ ├── SettingsSystemPanel.tsx
│ │ │ ├── SettingsToolsPanel.tsx
│ │ │ ├── StashBoxConfiguration.tsx
│ │ │ ├── StashConfiguration.tsx
│ │ │ ├── Tasks/
│ │ │ │ ├── CleanGeneratedDialog.tsx
│ │ │ │ ├── DataManagementTasks.tsx
│ │ │ │ ├── DirectorySelectionDialog.tsx
│ │ │ │ ├── GenerateOptions.tsx
│ │ │ │ ├── ImportDialog.tsx
│ │ │ │ ├── JobTable.tsx
│ │ │ │ ├── LibraryTasks.tsx
│ │ │ │ ├── PluginTasks.tsx
│ │ │ │ ├── ScanOptions.tsx
│ │ │ │ └── SettingsTasksPanel.tsx
│ │ │ ├── context.tsx
│ │ │ └── styles.scss
│ │ ├── SettingsButton.tsx
│ │ ├── Setup/
│ │ │ ├── Migrate.tsx
│ │ │ ├── Setup.tsx
│ │ │ └── styles.scss
│ │ ├── Shared/
│ │ │ ├── Alert.tsx
│ │ │ ├── BatchModals.tsx
│ │ │ ├── BulkUpdate.tsx
│ │ │ ├── ClearableInput.tsx
│ │ │ ├── CollapseButton.tsx
│ │ │ ├── CountButton.tsx
│ │ │ ├── Counter.tsx
│ │ │ ├── CountryFlag.tsx
│ │ │ ├── CountryLabel.tsx
│ │ │ ├── CountrySelect.tsx
│ │ │ ├── CustomFields.tsx
│ │ │ ├── Date.tsx
│ │ │ ├── DateInput.tsx
│ │ │ ├── DeleteEntityDialog.tsx
│ │ │ ├── DeleteFilesDialog.tsx
│ │ │ ├── DetailImage.tsx
│ │ │ ├── DetailItem.tsx
│ │ │ ├── DetailsEditNavbar.tsx
│ │ │ ├── DetailsPage/
│ │ │ │ ├── AliasList.tsx
│ │ │ │ ├── BackgroundImage.tsx
│ │ │ │ ├── DetailTitle.tsx
│ │ │ │ ├── HeaderImage.tsx
│ │ │ │ └── Tabs.tsx
│ │ │ ├── DoubleRangeInput.tsx
│ │ │ ├── DurationInput.tsx
│ │ │ ├── ErrorMessage.tsx
│ │ │ ├── ExportDialog.tsx
│ │ │ ├── ExternalLink.tsx
│ │ │ ├── ExternalLinksButton.tsx
│ │ │ ├── FavoriteIcon.tsx
│ │ │ ├── FileSize.tsx
│ │ │ ├── FilterSelect.tsx
│ │ │ ├── FolderSelect/
│ │ │ │ ├── FolderSelect.tsx
│ │ │ │ ├── FolderSelectDialog.tsx
│ │ │ │ └── useDirectoryPaths.ts
│ │ │ ├── GridCard/
│ │ │ │ ├── GridCard.tsx
│ │ │ │ ├── StudioOverlay.tsx
│ │ │ │ ├── dragMoveSelect.ts
│ │ │ │ └── styles.scss
│ │ │ ├── HoverPopover.tsx
│ │ │ ├── HoverScrubber.tsx
│ │ │ ├── Icon.tsx
│ │ │ ├── ImageInput.tsx
│ │ │ ├── ImageSelector.tsx
│ │ │ ├── IndeterminateCheckbox.tsx
│ │ │ ├── Link.tsx
│ │ │ ├── LoadingIndicator.tsx
│ │ │ ├── MarkdownPage.tsx
│ │ │ ├── Modal.tsx
│ │ │ ├── MultiSet.tsx
│ │ │ ├── OperationButton.tsx
│ │ │ ├── PackageManager/
│ │ │ │ ├── PackageManager.tsx
│ │ │ │ └── styles.scss
│ │ │ ├── PercentInput.tsx
│ │ │ ├── PerformerPopoverButton.tsx
│ │ │ ├── PopoverCountButton.tsx
│ │ │ ├── Rating/
│ │ │ │ ├── RatingNumber.tsx
│ │ │ │ ├── RatingStars.tsx
│ │ │ │ ├── RatingSystem.tsx
│ │ │ │ └── styles.scss
│ │ │ ├── RatingBanner.tsx
│ │ │ ├── ReassignFilesDialog.tsx
│ │ │ ├── RevealInFilesystemButton.tsx
│ │ │ ├── ScrapeDialog/
│ │ │ │ ├── CreateLinkTagDialog.tsx
│ │ │ │ ├── ScrapeDialog.tsx
│ │ │ │ ├── ScrapeDialogRow.tsx
│ │ │ │ ├── ScrapedObjectsRow.tsx
│ │ │ │ ├── createObjects.ts
│ │ │ │ ├── scrapeResult.ts
│ │ │ │ └── scrapedTags.tsx
│ │ │ ├── ScraperMenu.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ ├── StashBoxIDSearchModal.tsx
│ │ │ ├── StashID.tsx
│ │ │ ├── StringListInput.tsx
│ │ │ ├── SuccessIcon.tsx
│ │ │ ├── SweatDrops.tsx
│ │ │ ├── TagLink.tsx
│ │ │ ├── ThreeStateCheckbox.tsx
│ │ │ ├── TruncatedText.tsx
│ │ │ ├── URLField.tsx
│ │ │ └── styles.scss
│ │ ├── Stats.tsx
│ │ ├── Studios/
│ │ │ ├── EditStudiosDialog.tsx
│ │ │ ├── StudioCard.tsx
│ │ │ ├── StudioCardGrid.tsx
│ │ │ ├── StudioDetails/
│ │ │ │ ├── Studio.tsx
│ │ │ │ ├── StudioChildrenPanel.tsx
│ │ │ │ ├── StudioCreate.tsx
│ │ │ │ ├── StudioDetailsPanel.tsx
│ │ │ │ ├── StudioEditPanel.tsx
│ │ │ │ ├── StudioGalleriesPanel.tsx
│ │ │ │ ├── StudioGroupsPanel.tsx
│ │ │ │ ├── StudioImagesPanel.tsx
│ │ │ │ ├── StudioPerformersPanel.tsx
│ │ │ │ └── StudioScenesPanel.tsx
│ │ │ ├── StudioList.tsx
│ │ │ ├── StudioRecommendationRow.tsx
│ │ │ ├── StudioSelect.tsx
│ │ │ ├── Studios.tsx
│ │ │ └── styles.scss
│ │ ├── Tagger/
│ │ │ ├── FieldSelector.tsx
│ │ │ ├── IncludeButton.tsx
│ │ │ ├── LinkButton.tsx
│ │ │ ├── PerformerModal.tsx
│ │ │ ├── StashBoxSelector.tsx
│ │ │ ├── TaggerConfig.tsx
│ │ │ ├── config.ts
│ │ │ ├── constants.ts
│ │ │ ├── context.tsx
│ │ │ ├── performers/
│ │ │ │ ├── PerformerTagger.tsx
│ │ │ │ └── StashSearchResult.tsx
│ │ │ ├── queries.ts
│ │ │ ├── scenes/
│ │ │ │ ├── Config.tsx
│ │ │ │ ├── PerformerResult.tsx
│ │ │ │ ├── SceneTagger.tsx
│ │ │ │ ├── StashSearchResult.tsx
│ │ │ │ ├── StudioModal.tsx
│ │ │ │ ├── StudioResult.tsx
│ │ │ │ ├── TaggerScene.tsx
│ │ │ │ ├── sceneTaggerModals.tsx
│ │ │ │ └── utils.ts
│ │ │ ├── studios/
│ │ │ │ ├── StashSearchResult.tsx
│ │ │ │ └── StudioTagger.tsx
│ │ │ ├── styles.scss
│ │ │ ├── tags/
│ │ │ │ ├── StashSearchResult.tsx
│ │ │ │ ├── TagModal.tsx
│ │ │ │ └── TagTagger.tsx
│ │ │ └── utils.ts
│ │ ├── Tags/
│ │ │ ├── EditTagsDialog.tsx
│ │ │ ├── TagCard.tsx
│ │ │ ├── TagCardGrid.tsx
│ │ │ ├── TagDetails/
│ │ │ │ ├── Tag.tsx
│ │ │ │ ├── TagCreate.tsx
│ │ │ │ ├── TagDetailsPanel.tsx
│ │ │ │ ├── TagEditPanel.tsx
│ │ │ │ ├── TagGalleriesPanel.tsx
│ │ │ │ ├── TagGroupsPanel.tsx
│ │ │ │ ├── TagImagesPanel.tsx
│ │ │ │ ├── TagMarkersPanel.tsx
│ │ │ │ ├── TagPerformersPanel.tsx
│ │ │ │ ├── TagScenesPanel.tsx
│ │ │ │ └── TagStudiosPanel.tsx
│ │ │ ├── TagList.tsx
│ │ │ ├── TagListTable.tsx
│ │ │ ├── TagMergeDialog.tsx
│ │ │ ├── TagPopover.tsx
│ │ │ ├── TagRecommendationRow.tsx
│ │ │ ├── TagSelect.tsx
│ │ │ ├── Tags.tsx
│ │ │ └── styles.scss
│ │ ├── TroubleshootingMode/
│ │ │ ├── TroubleshootingModeButton.tsx
│ │ │ ├── TroubleshootingModeOverlay.tsx
│ │ │ └── useTroubleshootingMode.ts
│ │ └── Wall/
│ │ ├── WallItem.tsx
│ │ ├── WallPanel.tsx
│ │ └── styles.scss
│ ├── core/
│ │ ├── StashService.ts
│ │ ├── config.ts
│ │ ├── createClient.ts
│ │ ├── enums.ts
│ │ ├── files.ts
│ │ ├── galleries.ts
│ │ ├── groups.ts
│ │ ├── markers.ts
│ │ ├── performers.ts
│ │ ├── recommendations.ts
│ │ ├── studios.ts
│ │ └── tags.ts
│ ├── docs/
│ │ └── en/
│ │ ├── Changelog/
│ │ │ ├── v010.md
│ │ │ ├── v0100.md
│ │ │ ├── v011.md
│ │ │ ├── v0110.md
│ │ │ ├── v0120.md
│ │ │ ├── v0130.md
│ │ │ ├── v0131.md
│ │ │ ├── v0140.md
│ │ │ ├── v0150.md
│ │ │ ├── v0160.md
│ │ │ ├── v0161.md
│ │ │ ├── v0170.md
│ │ │ ├── v0180.md
│ │ │ ├── v0190.md
│ │ │ ├── v020.md
│ │ │ ├── v0200.md
│ │ │ ├── v021.md
│ │ │ ├── v0210.md
│ │ │ ├── v0220.md
│ │ │ ├── v0230.md
│ │ │ ├── v0240.md
│ │ │ ├── v0250.md
│ │ │ ├── v0260.md
│ │ │ ├── v0270.md
│ │ │ ├── v0280.md
│ │ │ ├── v0290.md
│ │ │ ├── v030.md
│ │ │ ├── v0300.md
│ │ │ ├── v0310.md
│ │ │ ├── v040.md
│ │ │ ├── v050.md
│ │ │ ├── v060.md
│ │ │ ├── v070.md
│ │ │ ├── v080.md
│ │ │ └── v090.md
│ │ ├── Manual/
│ │ │ ├── AutoTagging.md
│ │ │ ├── Browsing.md
│ │ │ ├── Captions.md
│ │ │ ├── Configuration.md
│ │ │ ├── Contributing.md
│ │ │ ├── Deduplication.md
│ │ │ ├── EmbeddedPlugins.md
│ │ │ ├── ExternalPlugins.md
│ │ │ ├── Help.md
│ │ │ ├── Identify.md
│ │ │ ├── Images.md
│ │ │ ├── Interactive.md
│ │ │ ├── Interface.md
│ │ │ ├── Introduction.md
│ │ │ ├── JSONSpec.md
│ │ │ ├── KeyboardShortcuts.md
│ │ │ ├── Plugins.md
│ │ │ ├── SceneFilenameParser.md
│ │ │ ├── ScraperDevelopment.md
│ │ │ ├── Scraping.md
│ │ │ ├── Tagger.md
│ │ │ ├── Tasks.md
│ │ │ ├── TroubleshootingMode.md
│ │ │ └── UIPluginApi.md
│ │ ├── MigrationNotes/
│ │ │ ├── 32.md
│ │ │ ├── 39.md
│ │ │ ├── 48.md
│ │ │ ├── 58.md
│ │ │ ├── 60.md
│ │ │ └── index.ts
│ │ └── ReleaseNotes/
│ │ ├── index.ts
│ │ ├── v0170.md
│ │ ├── v0200.md
│ │ ├── v0240.md
│ │ ├── v0250.md
│ │ ├── v0260.md
│ │ ├── v0270.md
│ │ └── v0290.md
│ ├── globals.d.ts
│ ├── hooks/
│ │ ├── Config.tsx
│ │ ├── Interactive/
│ │ │ ├── context.tsx
│ │ │ ├── interactive.scss
│ │ │ ├── interactive.ts
│ │ │ ├── status.tsx
│ │ │ └── utils.ts
│ │ ├── Interval.ts
│ │ ├── Lightbox/
│ │ │ ├── Lightbox.tsx
│ │ │ ├── LightboxImage.tsx
│ │ │ ├── LightboxLink.tsx
│ │ │ ├── context.tsx
│ │ │ ├── hooks.ts
│ │ │ ├── lightbox.scss
│ │ │ └── types.ts
│ │ ├── LocalForage.ts
│ │ ├── OutsideClick.tsx
│ │ ├── PageVisibility.ts
│ │ ├── Toast.tsx
│ │ ├── data.ts
│ │ ├── debounce.ts
│ │ ├── detailsPanel.ts
│ │ ├── event.ts
│ │ ├── keybinds.ts
│ │ ├── modal.ts
│ │ ├── scrollToTop.ts
│ │ ├── sprite.ts
│ │ ├── state.ts
│ │ ├── tagsEdit.tsx
│ │ ├── throttle.ts
│ │ ├── title.ts
│ │ ├── useScript.tsx
│ │ └── useTableColumns.ts
│ ├── index.scss
│ ├── index.tsx
│ ├── locales/
│ │ ├── README.md
│ │ ├── af-ZA.json
│ │ ├── ar.json
│ │ ├── bg-BG.json
│ │ ├── bn-BD.json
│ │ ├── ca-ES.json
│ │ ├── countryNames/
│ │ │ └── zh-TW.json
│ │ ├── cs-CZ.json
│ │ ├── da-DK.json
│ │ ├── de-DE.json
│ │ ├── en-GB.json
│ │ ├── en-US.json
│ │ ├── es-ES.json
│ │ ├── et-EE.json
│ │ ├── fa-IR.json
│ │ ├── fi-FI.json
│ │ ├── fr-FR.json
│ │ ├── hi-IN.json
│ │ ├── hr-HR.json
│ │ ├── hu-HU.json
│ │ ├── id-ID.json
│ │ ├── index.ts
│ │ ├── it-IT.json
│ │ ├── ja-JP.json
│ │ ├── ko-KR.json
│ │ ├── lt-LT.json
│ │ ├── lv-LV.json
│ │ ├── nb-NO.json
│ │ ├── ne-NP.json
│ │ ├── nl-NL.json
│ │ ├── nn-NO.json
│ │ ├── pl-PL.json
│ │ ├── pt-BR.json
│ │ ├── ro-RO.json
│ │ ├── ru-RU.json
│ │ ├── sk-SK.json
│ │ ├── sv-SE.json
│ │ ├── th-TH.json
│ │ ├── tr-TR.json
│ │ ├── uk-UA.json
│ │ ├── ur-PK.json
│ │ ├── vi-VN.json
│ │ ├── zh-CN.json
│ │ └── zh-TW.json
│ ├── models/
│ │ ├── list-filter/
│ │ │ ├── criteria/
│ │ │ │ ├── captions.ts
│ │ │ │ ├── circumcised.ts
│ │ │ │ ├── country.ts
│ │ │ │ ├── criterion.ts
│ │ │ │ ├── custom-fields.ts
│ │ │ │ ├── favorite.ts
│ │ │ │ ├── folder.ts
│ │ │ │ ├── galleries.ts
│ │ │ │ ├── gender.ts
│ │ │ │ ├── groups.ts
│ │ │ │ ├── has-chapters.ts
│ │ │ │ ├── has-markers.ts
│ │ │ │ ├── interactive.ts
│ │ │ │ ├── is-missing.ts
│ │ │ │ ├── organized.ts
│ │ │ │ ├── orientation.ts
│ │ │ │ ├── path.ts
│ │ │ │ ├── performers.ts
│ │ │ │ ├── phash.ts
│ │ │ │ ├── rating.ts
│ │ │ │ ├── resolution.ts
│ │ │ │ ├── scenes.ts
│ │ │ │ ├── stash-ids.ts
│ │ │ │ ├── studios.ts
│ │ │ │ └── tags.ts
│ │ │ ├── factory.ts
│ │ │ ├── filter-options.ts
│ │ │ ├── filter.ts
│ │ │ ├── galleries.ts
│ │ │ ├── groups.ts
│ │ │ ├── images.ts
│ │ │ ├── performers.ts
│ │ │ ├── scene-markers.ts
│ │ │ ├── scenes.ts
│ │ │ ├── studios.ts
│ │ │ ├── tags.ts
│ │ │ ├── types.ts
│ │ │ └── utils.ts
│ │ └── sceneQueue.ts
│ ├── patch.tsx
│ ├── pluginApi.d.ts
│ ├── pluginApi.tsx
│ ├── plugins.tsx
│ ├── polyfills.ts
│ ├── serviceWorker.ts
│ ├── sfw-mode.scss
│ ├── styles/
│ │ ├── _range.scss
│ │ ├── _scrollbars.scss
│ │ └── _theme.scss
│ └── utils/
│ ├── apple.ts
│ ├── bulkUpdate.ts
│ ├── caption.ts
│ ├── circumcised.ts
│ ├── country.ts
│ ├── data.ts
│ ├── dlnaVideoSort.ts
│ ├── download.ts
│ ├── errors.ts
│ ├── field.tsx
│ ├── flattenMessages.ts
│ ├── focus.ts
│ ├── form.tsx
│ ├── gender.ts
│ ├── hamming.ts
│ ├── history.ts
│ ├── image.tsx
│ ├── imageWall.ts
│ ├── index.ts
│ ├── job.ts
│ ├── keyboard.ts
│ ├── lazyComponent.ts
│ ├── navigation.ts
│ ├── orientation.ts
│ ├── percent.ts
│ ├── query.ts
│ ├── rating.ts
│ ├── resolution.ts
│ ├── screen.ts
│ ├── session.ts
│ ├── stashIds.ts
│ ├── stashbox.ts
│ ├── text.ts
│ ├── units.ts
│ ├── visualFile.ts
│ └── yup.ts
├── tsconfig.json
└── vite.config.js
Showing preview only (1,157K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (12481 symbols across 1220 files)
FILE: cmd/phasher/main.go
function customUsage (line 17) | func customUsage() {
function printPhash (line 23) | func printPhash(ff *ffmpeg.FFMpeg, ffp *ffmpeg.FFProbe, inputfile string...
function printVideoPhash (line 40) | func printVideoPhash(ff *ffmpeg.FFMpeg, ffp *ffmpeg.FFProbe, inputfile s...
function printImagePhash (line 68) | func printImagePhash(ff *ffmpeg.FFMpeg, inputfile string, quiet *bool) e...
function getPaths (line 86) | func getPaths() (string, string) {
function main (line 93) | func main() {
FILE: cmd/stash/main.go
function main (line 31) | func main() {
function initLogTemp (line 115) | func initLogTemp() *log.Logger {
function initLog (line 123) | func initLog(cfg *config.Config) *log.Logger {
function initProfiling (line 131) | func initProfiling(path string) error {
function recoverPanic (line 146) | func recoverPanic() {
function exitError (line 156) | func exitError(err error) {
function handleSignals (line 167) | func handleSignals(exit chan<- int) {
FILE: cmd/stash/main_test.go
function TestStub (line 5) | func TestStub(t *testing.T) {
FILE: internal/api/authentication.go
constant tripwireActivatedErrMsg (line 18) | tripwireActivatedErrMsg = "Stash is exposed to the public internet witho...
constant externalAccessErrMsg (line 21) | externalAccessErrMsg = "You have attempted to access Stash over the inte...
function allowUnauthenticated (line 27) | func allowUnauthenticated(r *http.Request) bool {
function authenticateHandler (line 32) | func authenticateHandler() func(http.Handler) http.Handler {
FILE: internal/api/bool_map.go
function MarshalBoolMap (line 11) | func MarshalBoolMap(val map[string]bool) graphql.Marshaler {
function UnmarshalBoolMap (line 20) | func UnmarshalBoolMap(v interface{}) (map[string]bool, error) {
FILE: internal/api/changeset_translator.go
constant updateInputField (line 15) | updateInputField = "input"
function getArgumentMap (line 17) | func getArgumentMap(ctx context.Context) map[string]interface{} {
function getUpdateInputMap (line 23) | func getUpdateInputMap(ctx context.Context) map[string]interface{} {
function getNamedUpdateInputMap (line 27) | func getNamedUpdateInputMap(ctx context.Context, field string) map[strin...
function getUpdateInputMaps (line 55) | func getUpdateInputMaps(ctx context.Context) []map[string]interface{} {
type changesetTranslator (line 74) | type changesetTranslator struct
method hasField (line 78) | func (t changesetTranslator) hasField(field string) bool {
method getFields (line 87) | func (t changesetTranslator) getFields() []string {
method string (line 96) | func (t changesetTranslator) string(value *string) string {
method optionalString (line 104) | func (t changesetTranslator) optionalString(value *string, field strin...
method optionalDate (line 117) | func (t changesetTranslator) optionalDate(value *string, field string)...
method datePtr (line 137) | func (t changesetTranslator) datePtr(value *string) (*models.Date, err...
method intPtrFromString (line 149) | func (t changesetTranslator) intPtrFromString(value *string) (*int, er...
method optionalInt (line 161) | func (t changesetTranslator) optionalInt(value *int, field string) mod...
method optionalIntFromString (line 169) | func (t changesetTranslator) optionalIntFromString(value *string, fiel...
method bool (line 188) | func (t changesetTranslator) bool(value *bool) bool {
method optionalBool (line 196) | func (t changesetTranslator) optionalBool(value *bool, field string) m...
method optionalFloat64 (line 204) | func (t changesetTranslator) optionalFloat64(value *float64, field str...
method fileIDPtrFromString (line 212) | func (t changesetTranslator) fileIDPtrFromString(value *string) (*mode...
method fileIDSliceFromStringSlice (line 226) | func (t changesetTranslator) fileIDSliceFromStringSlice(value []string...
method relatedIds (line 240) | func (t changesetTranslator) relatedIds(value []string) (models.Relate...
method updateIds (line 249) | func (t changesetTranslator) updateIds(value []string, field string) (...
method updateIdsBulk (line 265) | func (t changesetTranslator) updateIdsBulk(value *BulkUpdateIds, field...
method optionalURLs (line 281) | func (t changesetTranslator) optionalURLs(value []string, legacyValue ...
method optionalURLsBulk (line 301) | func (t changesetTranslator) optionalURLsBulk(value *BulkUpdateStrings...
method updateStrings (line 321) | func (t changesetTranslator) updateStrings(value []string, field strin...
method updateStringsBulk (line 338) | func (t changesetTranslator) updateStringsBulk(value *BulkUpdateString...
method updateStashIDs (line 355) | func (t changesetTranslator) updateStashIDs(value models.StashIDInputs...
method relatedGroupsFromMovies (line 366) | func (t changesetTranslator) relatedGroupsFromMovies(value []models.Sc...
method relatedGroups (line 393) | func (t changesetTranslator) relatedGroups(value []models.SceneGroupIn...
method updateGroupIDsFromMovies (line 402) | func (t changesetTranslator) updateGroupIDsFromMovies(value []models.S...
method updateGroupIDs (line 418) | func (t changesetTranslator) updateGroupIDs(value []models.SceneGroupI...
method updateGroupIDsBulk (line 434) | func (t changesetTranslator) updateGroupIDsBulk(value *BulkUpdateIds, ...
method groupIDDescriptions (line 475) | func (t changesetTranslator) groupIDDescriptions(value []*GroupDescrip...
method updateGroupIDDescriptions (line 484) | func (t changesetTranslator) updateGroupIDDescriptions(value []*GroupD...
method updateGroupIDDescriptionsBulk (line 500) | func (t changesetTranslator) updateGroupIDDescriptionsBulk(value *Bulk...
function groupsScenesFromGroupInput (line 375) | func groupsScenesFromGroupInput(input []models.SceneGroupInput) ([]model...
function groupsDescriptionsFromGroupInput (line 455) | func groupsDescriptionsFromGroupInput(input []*GroupDescriptionInput) ([...
FILE: internal/api/check_version.go
constant apiReleases (line 23) | apiReleases string = "https://api.github.com/repos/stashapp/stash/releases"
constant apiTags (line 24) | apiTags string = "https://api.github.com/repos/stashapp/stash/tags"
constant apiAcceptHeader (line 25) | apiAcceptHeader string = "application/vnd.github.v3+json"
constant developmentTag (line 26) | developmentTag string = "latest_develop"
constant defaultSHLength (line 27) | defaultSHLength int = 8
function isMacOSBundle (line 42) | func isMacOSBundle() bool {
function getWantedRelease (line 48) | func getWantedRelease(platform string) string {
type githubReleasesResponse (line 59) | type githubReleasesResponse struct
type githubAuthor (line 80) | type githubAuthor struct
type githubAsset (line 101) | type githubAsset struct
type githubTagResponse (line 117) | type githubTagResponse struct
type LatestRelease (line 128) | type LatestRelease struct
function makeGithubRequest (line 136) | func makeGithubRequest(ctx context.Context, url string, output interface...
function GetLatestRelease (line 180) | func GetLatestRelease(ctx context.Context) (*LatestRelease, error) {
function getReleaseHash (line 252) | func getReleaseHash(ctx context.Context, tagName string) (string, error) {
function printLatestVersion (line 292) | func printLatestVersion(ctx context.Context) {
FILE: internal/api/context_keys.go
type key (line 5) | type key
constant galleryKey (line 8) | galleryKey key = 0
constant performerKey (line 9) | performerKey
constant sceneKey (line 10) | sceneKey
constant studioKey (line 11) | studioKey
constant groupKey (line 12) | groupKey
constant tagKey (line 13) | tagKey
constant downloadKey (line 14) | downloadKey
constant imageKey (line 15) | imageKey
constant pluginKey (line 16) | pluginKey
FILE: internal/api/custom_fields.go
function handleUpdateCustomFields (line 5) | func handleUpdateCustomFields(input models.CustomFieldsInput) models.Cus...
FILE: internal/api/dir_list.go
type dirLister (line 12) | type dirLister
method Len (line 14) | func (s dirLister) Len() int {
method Swap (line 18) | func (s dirLister) Swap(i, j int) {
method Bytes (line 22) | func (s dirLister) Bytes(i int) []byte {
function listDir (line 27) | func listDir(col *collate.Collator, path string) ([]string, error) {
FILE: internal/api/error.go
function gqlErrorHandler (line 13) | func gqlErrorHandler(ctx context.Context, e error) *gqlerror.Error {
FILE: internal/api/fields.go
type queryFields (line 9) | type queryFields
method Has (line 16) | func (f queryFields) Has(field string) bool {
function collectQueryFields (line 11) | func collectQueryFields(ctx context.Context) queryFields {
FILE: internal/api/images.go
type imageBox (line 17) | type imageBox struct
method GetRandomImageByName (line 60) | func (box *imageBox) GetRandomImageByName(name string) ([]byte, error) {
function newImageBox (line 32) | func newImageBox(box fs.FS) (*imageBox, error) {
function init (line 80) | func init() {
function initCustomPerformerImages (line 92) | func initCustomPerformerImages(customPath string) {
function getDefaultPerformerImage (line 105) | func getDefaultPerformerImage(name string, gender *models.GenderEnum, sf...
FILE: internal/api/input.go
function handleIDList (line 12) | func handleIDList(idList []string, field string) ([]int, error) {
function validateIDList (line 26) | func validateIDList(ids []string) error {
FILE: internal/api/json.go
function jsonNumberToNumber (line 11) | func jsonNumberToNumber(n json.Number) interface{} {
function anyJSONNumberToNumber (line 21) | func anyJSONNumberToNumber(v any) any {
function convertMapJSONNumbers (line 30) | func convertMapJSONNumbers(m map[string]interface{}) (ret map[string]int...
function convertCustomFieldCriterionValues (line 49) | func convertCustomFieldCriterionValues(c models.CustomFieldCriterionInpu...
function convertCustomFieldCriterionInputJSONNumbers (line 58) | func convertCustomFieldCriterionInputJSONNumbers(c []models.CustomFieldC...
FILE: internal/api/json_test.go
function TestConvertMapJSONNumbers (line 10) | func TestConvertMapJSONNumbers(t *testing.T) {
FILE: internal/api/loaders/customfieldsloader_gen.go
type CustomFieldsLoaderConfig (line 13) | type CustomFieldsLoaderConfig struct
function NewCustomFieldsLoader (line 25) | func NewCustomFieldsLoader(config CustomFieldsLoaderConfig) *CustomField...
type CustomFieldsLoader (line 34) | type CustomFieldsLoader struct
method Load (line 66) | func (l *CustomFieldsLoader) Load(key int) (models.CustomFieldMap, err...
method LoadThunk (line 73) | func (l *CustomFieldsLoader) LoadThunk(key int) func() (models.CustomF...
method LoadAll (line 116) | func (l *CustomFieldsLoader) LoadAll(keys []int) ([]models.CustomField...
method LoadAllThunk (line 134) | func (l *CustomFieldsLoader) LoadAllThunk(keys []int) func() ([]models...
method Prime (line 152) | func (l *CustomFieldsLoader) Prime(key int, value models.CustomFieldMa...
method Clear (line 163) | func (l *CustomFieldsLoader) Clear(key int) {
method unsafeSet (line 169) | func (l *CustomFieldsLoader) unsafeSet(key int, value models.CustomFie...
type customFieldsLoaderBatch (line 57) | type customFieldsLoaderBatch struct
method keyIndex (line 178) | func (b *customFieldsLoaderBatch) keyIndex(l *CustomFieldsLoader, key ...
method startTimer (line 202) | func (b *customFieldsLoaderBatch) startTimer(l *CustomFieldsLoader) {
method end (line 218) | func (b *customFieldsLoaderBatch) end(l *CustomFieldsLoader) {
FILE: internal/api/loaders/dataloaders.go
type contextKey (line 34) | type contextKey struct
constant wait (line 41) | wait = 1 * time.Millisecond
constant maxBatch (line 42) | maxBatch = 100
type Loaders (line 45) | type Loaders struct
type Middleware (line 81) | type Middleware struct
method Middleware (line 85) | func (m Middleware) Middleware(next http.Handler) http.Handler {
method fetchScenes (line 233) | func (m Middleware) fetchScenes(ctx context.Context) func(keys []int) ...
method fetchSceneCustomFields (line 244) | func (m Middleware) fetchSceneCustomFields(ctx context.Context) func(k...
method fetchImages (line 256) | func (m Middleware) fetchImages(ctx context.Context) func(keys []int) ...
method fetchImageCustomFields (line 268) | func (m Middleware) fetchImageCustomFields(ctx context.Context) func(k...
method fetchGalleries (line 280) | func (m Middleware) fetchGalleries(ctx context.Context) func(keys []in...
method fetchPerformers (line 292) | func (m Middleware) fetchPerformers(ctx context.Context) func(keys []i...
method fetchPerformerCustomFields (line 304) | func (m Middleware) fetchPerformerCustomFields(ctx context.Context) fu...
method fetchStudios (line 316) | func (m Middleware) fetchStudios(ctx context.Context) func(keys []int)...
method fetchStudioCustomFields (line 327) | func (m Middleware) fetchStudioCustomFields(ctx context.Context) func(...
method fetchTags (line 339) | func (m Middleware) fetchTags(ctx context.Context) func(keys []int) ([...
method fetchTagCustomFields (line 350) | func (m Middleware) fetchTagCustomFields(ctx context.Context) func(key...
method fetchGroupCustomFields (line 362) | func (m Middleware) fetchGroupCustomFields(ctx context.Context) func(k...
method fetchGalleryCustomFields (line 374) | func (m Middleware) fetchGalleryCustomFields(ctx context.Context) func...
method fetchGroups (line 386) | func (m Middleware) fetchGroups(ctx context.Context) func(keys []int) ...
method fetchFiles (line 397) | func (m Middleware) fetchFiles(ctx context.Context) func(keys []models...
method fetchFolders (line 408) | func (m Middleware) fetchFolders(ctx context.Context) func(keys []mode...
method fetchFoldersParentFolderIDs (line 419) | func (m Middleware) fetchFoldersParentFolderIDs(ctx context.Context) f...
method fetchScenesFileIDs (line 430) | func (m Middleware) fetchScenesFileIDs(ctx context.Context) func(keys ...
method fetchImagesFileIDs (line 441) | func (m Middleware) fetchImagesFileIDs(ctx context.Context) func(keys ...
method fetchGalleriesFileIDs (line 452) | func (m Middleware) fetchGalleriesFileIDs(ctx context.Context) func(ke...
method fetchScenesOCount (line 463) | func (m Middleware) fetchScenesOCount(ctx context.Context) func(keys [...
method fetchScenesPlayCount (line 474) | func (m Middleware) fetchScenesPlayCount(ctx context.Context) func(key...
method fetchScenesOHistory (line 485) | func (m Middleware) fetchScenesOHistory(ctx context.Context) func(keys...
method fetchScenesPlayHistory (line 496) | func (m Middleware) fetchScenesPlayHistory(ctx context.Context) func(k...
method fetchScenesLastPlayed (line 507) | func (m Middleware) fetchScenesLastPlayed(ctx context.Context) func(ke...
function From (line 221) | func From(ctx context.Context) Loaders {
function toErrorSlice (line 225) | func toErrorSlice(err error) []error {
FILE: internal/api/loaders/fileloader_gen.go
type FileLoaderConfig (line 13) | type FileLoaderConfig struct
function NewFileLoader (line 25) | func NewFileLoader(config FileLoaderConfig) *FileLoader {
type FileLoader (line 34) | type FileLoader struct
method Load (line 66) | func (l *FileLoader) Load(key models.FileID) (models.File, error) {
method LoadThunk (line 73) | func (l *FileLoader) LoadThunk(key models.FileID) func() (models.File,...
method LoadAll (line 116) | func (l *FileLoader) LoadAll(keys []models.FileID) ([]models.File, []e...
method LoadAllThunk (line 134) | func (l *FileLoader) LoadAllThunk(keys []models.FileID) func() ([]mode...
method Prime (line 152) | func (l *FileLoader) Prime(key models.FileID, value models.File) bool {
method Clear (line 163) | func (l *FileLoader) Clear(key models.FileID) {
method unsafeSet (line 169) | func (l *FileLoader) unsafeSet(key models.FileID, value models.File) {
type fileLoaderBatch (line 57) | type fileLoaderBatch struct
method keyIndex (line 178) | func (b *fileLoaderBatch) keyIndex(l *FileLoader, key models.FileID) i...
method startTimer (line 202) | func (b *fileLoaderBatch) startTimer(l *FileLoader) {
method end (line 218) | func (b *fileLoaderBatch) end(l *FileLoader) {
FILE: internal/api/loaders/folderloader_gen.go
type FolderLoaderConfig (line 13) | type FolderLoaderConfig struct
function NewFolderLoader (line 25) | func NewFolderLoader(config FolderLoaderConfig) *FolderLoader {
type FolderLoader (line 34) | type FolderLoader struct
method Load (line 66) | func (l *FolderLoader) Load(key models.FolderID) (*models.Folder, erro...
method LoadThunk (line 73) | func (l *FolderLoader) LoadThunk(key models.FolderID) func() (*models....
method LoadAll (line 116) | func (l *FolderLoader) LoadAll(keys []models.FolderID) ([]*models.Fold...
method LoadAllThunk (line 134) | func (l *FolderLoader) LoadAllThunk(keys []models.FolderID) func() ([]...
method Prime (line 152) | func (l *FolderLoader) Prime(key models.FolderID, value *models.Folder...
method Clear (line 166) | func (l *FolderLoader) Clear(key models.FolderID) {
method unsafeSet (line 172) | func (l *FolderLoader) unsafeSet(key models.FolderID, value *models.Fo...
type folderLoaderBatch (line 57) | type folderLoaderBatch struct
method keyIndex (line 181) | func (b *folderLoaderBatch) keyIndex(l *FolderLoader, key models.Folde...
method startTimer (line 205) | func (b *folderLoaderBatch) startTimer(l *FolderLoader) {
method end (line 221) | func (b *folderLoaderBatch) end(l *FolderLoader) {
FILE: internal/api/loaders/folderparentfolderidsloader_gen.go
type FolderParentFolderIDsLoaderConfig (line 13) | type FolderParentFolderIDsLoaderConfig struct
function NewFolderParentFolderIDsLoader (line 25) | func NewFolderParentFolderIDsLoader(config FolderParentFolderIDsLoaderCo...
type FolderParentFolderIDsLoader (line 34) | type FolderParentFolderIDsLoader struct
method Load (line 66) | func (l *FolderParentFolderIDsLoader) Load(key models.FolderID) ([]mod...
method LoadThunk (line 73) | func (l *FolderParentFolderIDsLoader) LoadThunk(key models.FolderID) f...
method LoadAll (line 116) | func (l *FolderParentFolderIDsLoader) LoadAll(keys []models.FolderID) ...
method LoadAllThunk (line 134) | func (l *FolderParentFolderIDsLoader) LoadAllThunk(keys []models.Folde...
method Prime (line 152) | func (l *FolderParentFolderIDsLoader) Prime(key models.FolderID, value...
method Clear (line 167) | func (l *FolderParentFolderIDsLoader) Clear(key models.FolderID) {
method unsafeSet (line 173) | func (l *FolderParentFolderIDsLoader) unsafeSet(key models.FolderID, v...
type folderParentFolderIDsLoaderBatch (line 57) | type folderParentFolderIDsLoaderBatch struct
method keyIndex (line 182) | func (b *folderParentFolderIDsLoaderBatch) keyIndex(l *FolderParentFol...
method startTimer (line 206) | func (b *folderParentFolderIDsLoaderBatch) startTimer(l *FolderParentF...
method end (line 222) | func (b *folderParentFolderIDsLoaderBatch) end(l *FolderParentFolderID...
FILE: internal/api/loaders/galleryfileidsloader_gen.go
type GalleryFileIDsLoaderConfig (line 13) | type GalleryFileIDsLoaderConfig struct
function NewGalleryFileIDsLoader (line 25) | func NewGalleryFileIDsLoader(config GalleryFileIDsLoaderConfig) *Gallery...
type GalleryFileIDsLoader (line 34) | type GalleryFileIDsLoader struct
method Load (line 66) | func (l *GalleryFileIDsLoader) Load(key int) ([]models.FileID, error) {
method LoadThunk (line 73) | func (l *GalleryFileIDsLoader) LoadThunk(key int) func() ([]models.Fil...
method LoadAll (line 116) | func (l *GalleryFileIDsLoader) LoadAll(keys []int) ([][]models.FileID,...
method LoadAllThunk (line 134) | func (l *GalleryFileIDsLoader) LoadAllThunk(keys []int) func() ([][]mo...
method Prime (line 152) | func (l *GalleryFileIDsLoader) Prime(key int, value []models.FileID) b...
method Clear (line 167) | func (l *GalleryFileIDsLoader) Clear(key int) {
method unsafeSet (line 173) | func (l *GalleryFileIDsLoader) unsafeSet(key int, value []models.FileI...
type galleryFileIDsLoaderBatch (line 57) | type galleryFileIDsLoaderBatch struct
method keyIndex (line 182) | func (b *galleryFileIDsLoaderBatch) keyIndex(l *GalleryFileIDsLoader, ...
method startTimer (line 206) | func (b *galleryFileIDsLoaderBatch) startTimer(l *GalleryFileIDsLoader) {
method end (line 222) | func (b *galleryFileIDsLoaderBatch) end(l *GalleryFileIDsLoader) {
FILE: internal/api/loaders/galleryloader_gen.go
type GalleryLoaderConfig (line 13) | type GalleryLoaderConfig struct
function NewGalleryLoader (line 25) | func NewGalleryLoader(config GalleryLoaderConfig) *GalleryLoader {
type GalleryLoader (line 34) | type GalleryLoader struct
method Load (line 66) | func (l *GalleryLoader) Load(key int) (*models.Gallery, error) {
method LoadThunk (line 73) | func (l *GalleryLoader) LoadThunk(key int) func() (*models.Gallery, er...
method LoadAll (line 116) | func (l *GalleryLoader) LoadAll(keys []int) ([]*models.Gallery, []erro...
method LoadAllThunk (line 134) | func (l *GalleryLoader) LoadAllThunk(keys []int) func() ([]*models.Gal...
method Prime (line 152) | func (l *GalleryLoader) Prime(key int, value *models.Gallery) bool {
method Clear (line 166) | func (l *GalleryLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *GalleryLoader) unsafeSet(key int, value *models.Gallery) {
type galleryLoaderBatch (line 57) | type galleryLoaderBatch struct
method keyIndex (line 181) | func (b *galleryLoaderBatch) keyIndex(l *GalleryLoader, key int) int {
method startTimer (line 205) | func (b *galleryLoaderBatch) startTimer(l *GalleryLoader) {
method end (line 221) | func (b *galleryLoaderBatch) end(l *GalleryLoader) {
FILE: internal/api/loaders/grouploader_gen.go
type GroupLoaderConfig (line 13) | type GroupLoaderConfig struct
function NewGroupLoader (line 25) | func NewGroupLoader(config GroupLoaderConfig) *GroupLoader {
type GroupLoader (line 34) | type GroupLoader struct
method Load (line 66) | func (l *GroupLoader) Load(key int) (*models.Group, error) {
method LoadThunk (line 73) | func (l *GroupLoader) LoadThunk(key int) func() (*models.Group, error) {
method LoadAll (line 116) | func (l *GroupLoader) LoadAll(keys []int) ([]*models.Group, []error) {
method LoadAllThunk (line 134) | func (l *GroupLoader) LoadAllThunk(keys []int) func() ([]*models.Group...
method Prime (line 152) | func (l *GroupLoader) Prime(key int, value *models.Group) bool {
method Clear (line 166) | func (l *GroupLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *GroupLoader) unsafeSet(key int, value *models.Group) {
type groupLoaderBatch (line 57) | type groupLoaderBatch struct
method keyIndex (line 181) | func (b *groupLoaderBatch) keyIndex(l *GroupLoader, key int) int {
method startTimer (line 205) | func (b *groupLoaderBatch) startTimer(l *GroupLoader) {
method end (line 221) | func (b *groupLoaderBatch) end(l *GroupLoader) {
FILE: internal/api/loaders/imagefileidsloader_gen.go
type ImageFileIDsLoaderConfig (line 13) | type ImageFileIDsLoaderConfig struct
function NewImageFileIDsLoader (line 25) | func NewImageFileIDsLoader(config ImageFileIDsLoaderConfig) *ImageFileID...
type ImageFileIDsLoader (line 34) | type ImageFileIDsLoader struct
method Load (line 66) | func (l *ImageFileIDsLoader) Load(key int) ([]models.FileID, error) {
method LoadThunk (line 73) | func (l *ImageFileIDsLoader) LoadThunk(key int) func() ([]models.FileI...
method LoadAll (line 116) | func (l *ImageFileIDsLoader) LoadAll(keys []int) ([][]models.FileID, [...
method LoadAllThunk (line 134) | func (l *ImageFileIDsLoader) LoadAllThunk(keys []int) func() ([][]mode...
method Prime (line 152) | func (l *ImageFileIDsLoader) Prime(key int, value []models.FileID) bool {
method Clear (line 167) | func (l *ImageFileIDsLoader) Clear(key int) {
method unsafeSet (line 173) | func (l *ImageFileIDsLoader) unsafeSet(key int, value []models.FileID) {
type imageFileIDsLoaderBatch (line 57) | type imageFileIDsLoaderBatch struct
method keyIndex (line 182) | func (b *imageFileIDsLoaderBatch) keyIndex(l *ImageFileIDsLoader, key ...
method startTimer (line 206) | func (b *imageFileIDsLoaderBatch) startTimer(l *ImageFileIDsLoader) {
method end (line 222) | func (b *imageFileIDsLoaderBatch) end(l *ImageFileIDsLoader) {
FILE: internal/api/loaders/imageloader_gen.go
type ImageLoaderConfig (line 13) | type ImageLoaderConfig struct
function NewImageLoader (line 25) | func NewImageLoader(config ImageLoaderConfig) *ImageLoader {
type ImageLoader (line 34) | type ImageLoader struct
method Load (line 66) | func (l *ImageLoader) Load(key int) (*models.Image, error) {
method LoadThunk (line 73) | func (l *ImageLoader) LoadThunk(key int) func() (*models.Image, error) {
method LoadAll (line 116) | func (l *ImageLoader) LoadAll(keys []int) ([]*models.Image, []error) {
method LoadAllThunk (line 134) | func (l *ImageLoader) LoadAllThunk(keys []int) func() ([]*models.Image...
method Prime (line 152) | func (l *ImageLoader) Prime(key int, value *models.Image) bool {
method Clear (line 166) | func (l *ImageLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *ImageLoader) unsafeSet(key int, value *models.Image) {
type imageLoaderBatch (line 57) | type imageLoaderBatch struct
method keyIndex (line 181) | func (b *imageLoaderBatch) keyIndex(l *ImageLoader, key int) int {
method startTimer (line 205) | func (b *imageLoaderBatch) startTimer(l *ImageLoader) {
method end (line 221) | func (b *imageLoaderBatch) end(l *ImageLoader) {
FILE: internal/api/loaders/performerloader_gen.go
type PerformerLoaderConfig (line 13) | type PerformerLoaderConfig struct
function NewPerformerLoader (line 25) | func NewPerformerLoader(config PerformerLoaderConfig) *PerformerLoader {
type PerformerLoader (line 34) | type PerformerLoader struct
method Load (line 66) | func (l *PerformerLoader) Load(key int) (*models.Performer, error) {
method LoadThunk (line 73) | func (l *PerformerLoader) LoadThunk(key int) func() (*models.Performer...
method LoadAll (line 116) | func (l *PerformerLoader) LoadAll(keys []int) ([]*models.Performer, []...
method LoadAllThunk (line 134) | func (l *PerformerLoader) LoadAllThunk(keys []int) func() ([]*models.P...
method Prime (line 152) | func (l *PerformerLoader) Prime(key int, value *models.Performer) bool {
method Clear (line 166) | func (l *PerformerLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *PerformerLoader) unsafeSet(key int, value *models.Performer) {
type performerLoaderBatch (line 57) | type performerLoaderBatch struct
method keyIndex (line 181) | func (b *performerLoaderBatch) keyIndex(l *PerformerLoader, key int) i...
method startTimer (line 205) | func (b *performerLoaderBatch) startTimer(l *PerformerLoader) {
method end (line 221) | func (b *performerLoaderBatch) end(l *PerformerLoader) {
FILE: internal/api/loaders/scenefileidsloader_gen.go
type SceneFileIDsLoaderConfig (line 13) | type SceneFileIDsLoaderConfig struct
function NewSceneFileIDsLoader (line 25) | func NewSceneFileIDsLoader(config SceneFileIDsLoaderConfig) *SceneFileID...
type SceneFileIDsLoader (line 34) | type SceneFileIDsLoader struct
method Load (line 66) | func (l *SceneFileIDsLoader) Load(key int) ([]models.FileID, error) {
method LoadThunk (line 73) | func (l *SceneFileIDsLoader) LoadThunk(key int) func() ([]models.FileI...
method LoadAll (line 116) | func (l *SceneFileIDsLoader) LoadAll(keys []int) ([][]models.FileID, [...
method LoadAllThunk (line 134) | func (l *SceneFileIDsLoader) LoadAllThunk(keys []int) func() ([][]mode...
method Prime (line 152) | func (l *SceneFileIDsLoader) Prime(key int, value []models.FileID) bool {
method Clear (line 167) | func (l *SceneFileIDsLoader) Clear(key int) {
method unsafeSet (line 173) | func (l *SceneFileIDsLoader) unsafeSet(key int, value []models.FileID) {
type sceneFileIDsLoaderBatch (line 57) | type sceneFileIDsLoaderBatch struct
method keyIndex (line 182) | func (b *sceneFileIDsLoaderBatch) keyIndex(l *SceneFileIDsLoader, key ...
method startTimer (line 206) | func (b *sceneFileIDsLoaderBatch) startTimer(l *SceneFileIDsLoader) {
method end (line 222) | func (b *sceneFileIDsLoaderBatch) end(l *SceneFileIDsLoader) {
FILE: internal/api/loaders/scenelastplayedloader_gen.go
type SceneLastPlayedLoaderConfig (line 11) | type SceneLastPlayedLoaderConfig struct
function NewSceneLastPlayedLoader (line 23) | func NewSceneLastPlayedLoader(config SceneLastPlayedLoaderConfig) *Scene...
type SceneLastPlayedLoader (line 32) | type SceneLastPlayedLoader struct
method Load (line 64) | func (l *SceneLastPlayedLoader) Load(key int) (*time.Time, error) {
method LoadThunk (line 71) | func (l *SceneLastPlayedLoader) LoadThunk(key int) func() (*time.Time,...
method LoadAll (line 114) | func (l *SceneLastPlayedLoader) LoadAll(keys []int) ([]*time.Time, []e...
method LoadAllThunk (line 132) | func (l *SceneLastPlayedLoader) LoadAllThunk(keys []int) func() ([]*ti...
method Prime (line 150) | func (l *SceneLastPlayedLoader) Prime(key int, value *time.Time) bool {
method Clear (line 164) | func (l *SceneLastPlayedLoader) Clear(key int) {
method unsafeSet (line 170) | func (l *SceneLastPlayedLoader) unsafeSet(key int, value *time.Time) {
type sceneLastPlayedLoaderBatch (line 55) | type sceneLastPlayedLoaderBatch struct
method keyIndex (line 179) | func (b *sceneLastPlayedLoaderBatch) keyIndex(l *SceneLastPlayedLoader...
method startTimer (line 203) | func (b *sceneLastPlayedLoaderBatch) startTimer(l *SceneLastPlayedLoad...
method end (line 219) | func (b *sceneLastPlayedLoaderBatch) end(l *SceneLastPlayedLoader) {
FILE: internal/api/loaders/sceneloader_gen.go
type SceneLoaderConfig (line 13) | type SceneLoaderConfig struct
function NewSceneLoader (line 25) | func NewSceneLoader(config SceneLoaderConfig) *SceneLoader {
type SceneLoader (line 34) | type SceneLoader struct
method Load (line 66) | func (l *SceneLoader) Load(key int) (*models.Scene, error) {
method LoadThunk (line 73) | func (l *SceneLoader) LoadThunk(key int) func() (*models.Scene, error) {
method LoadAll (line 116) | func (l *SceneLoader) LoadAll(keys []int) ([]*models.Scene, []error) {
method LoadAllThunk (line 134) | func (l *SceneLoader) LoadAllThunk(keys []int) func() ([]*models.Scene...
method Prime (line 152) | func (l *SceneLoader) Prime(key int, value *models.Scene) bool {
method Clear (line 166) | func (l *SceneLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *SceneLoader) unsafeSet(key int, value *models.Scene) {
type sceneLoaderBatch (line 57) | type sceneLoaderBatch struct
method keyIndex (line 181) | func (b *sceneLoaderBatch) keyIndex(l *SceneLoader, key int) int {
method startTimer (line 205) | func (b *sceneLoaderBatch) startTimer(l *SceneLoader) {
method end (line 221) | func (b *sceneLoaderBatch) end(l *SceneLoader) {
FILE: internal/api/loaders/sceneocountloader_gen.go
type SceneOCountLoaderConfig (line 11) | type SceneOCountLoaderConfig struct
function NewSceneOCountLoader (line 23) | func NewSceneOCountLoader(config SceneOCountLoaderConfig) *SceneOCountLo...
type SceneOCountLoader (line 32) | type SceneOCountLoader struct
method Load (line 64) | func (l *SceneOCountLoader) Load(key int) (int, error) {
method LoadThunk (line 71) | func (l *SceneOCountLoader) LoadThunk(key int) func() (int, error) {
method LoadAll (line 114) | func (l *SceneOCountLoader) LoadAll(keys []int) ([]int, []error) {
method LoadAllThunk (line 132) | func (l *SceneOCountLoader) LoadAllThunk(keys []int) func() ([]int, []...
method Prime (line 150) | func (l *SceneOCountLoader) Prime(key int, value int) bool {
method Clear (line 161) | func (l *SceneOCountLoader) Clear(key int) {
method unsafeSet (line 167) | func (l *SceneOCountLoader) unsafeSet(key int, value int) {
type sceneOCountLoaderBatch (line 55) | type sceneOCountLoaderBatch struct
method keyIndex (line 176) | func (b *sceneOCountLoaderBatch) keyIndex(l *SceneOCountLoader, key in...
method startTimer (line 200) | func (b *sceneOCountLoaderBatch) startTimer(l *SceneOCountLoader) {
method end (line 216) | func (b *sceneOCountLoaderBatch) end(l *SceneOCountLoader) {
FILE: internal/api/loaders/sceneohistoryloader_gen.go
type SceneOHistoryLoaderConfig (line 11) | type SceneOHistoryLoaderConfig struct
function NewSceneOHistoryLoader (line 23) | func NewSceneOHistoryLoader(config SceneOHistoryLoaderConfig) *SceneOHis...
type SceneOHistoryLoader (line 32) | type SceneOHistoryLoader struct
method Load (line 64) | func (l *SceneOHistoryLoader) Load(key int) ([]time.Time, error) {
method LoadThunk (line 71) | func (l *SceneOHistoryLoader) LoadThunk(key int) func() ([]time.Time, ...
method LoadAll (line 114) | func (l *SceneOHistoryLoader) LoadAll(keys []int) ([][]time.Time, []er...
method LoadAllThunk (line 132) | func (l *SceneOHistoryLoader) LoadAllThunk(keys []int) func() ([][]tim...
method Prime (line 150) | func (l *SceneOHistoryLoader) Prime(key int, value []time.Time) bool {
method Clear (line 165) | func (l *SceneOHistoryLoader) Clear(key int) {
method unsafeSet (line 171) | func (l *SceneOHistoryLoader) unsafeSet(key int, value []time.Time) {
type sceneOHistoryLoaderBatch (line 55) | type sceneOHistoryLoaderBatch struct
method keyIndex (line 180) | func (b *sceneOHistoryLoaderBatch) keyIndex(l *SceneOHistoryLoader, ke...
method startTimer (line 204) | func (b *sceneOHistoryLoaderBatch) startTimer(l *SceneOHistoryLoader) {
method end (line 220) | func (b *sceneOHistoryLoaderBatch) end(l *SceneOHistoryLoader) {
FILE: internal/api/loaders/sceneplaycountloader_gen.go
type ScenePlayCountLoaderConfig (line 11) | type ScenePlayCountLoaderConfig struct
function NewScenePlayCountLoader (line 23) | func NewScenePlayCountLoader(config ScenePlayCountLoaderConfig) *ScenePl...
type ScenePlayCountLoader (line 32) | type ScenePlayCountLoader struct
method Load (line 64) | func (l *ScenePlayCountLoader) Load(key int) (int, error) {
method LoadThunk (line 71) | func (l *ScenePlayCountLoader) LoadThunk(key int) func() (int, error) {
method LoadAll (line 114) | func (l *ScenePlayCountLoader) LoadAll(keys []int) ([]int, []error) {
method LoadAllThunk (line 132) | func (l *ScenePlayCountLoader) LoadAllThunk(keys []int) func() ([]int,...
method Prime (line 150) | func (l *ScenePlayCountLoader) Prime(key int, value int) bool {
method Clear (line 161) | func (l *ScenePlayCountLoader) Clear(key int) {
method unsafeSet (line 167) | func (l *ScenePlayCountLoader) unsafeSet(key int, value int) {
type scenePlayCountLoaderBatch (line 55) | type scenePlayCountLoaderBatch struct
method keyIndex (line 176) | func (b *scenePlayCountLoaderBatch) keyIndex(l *ScenePlayCountLoader, ...
method startTimer (line 200) | func (b *scenePlayCountLoaderBatch) startTimer(l *ScenePlayCountLoader) {
method end (line 216) | func (b *scenePlayCountLoaderBatch) end(l *ScenePlayCountLoader) {
FILE: internal/api/loaders/sceneplayhistoryloader_gen.go
type ScenePlayHistoryLoaderConfig (line 11) | type ScenePlayHistoryLoaderConfig struct
function NewScenePlayHistoryLoader (line 23) | func NewScenePlayHistoryLoader(config ScenePlayHistoryLoaderConfig) *Sce...
type ScenePlayHistoryLoader (line 32) | type ScenePlayHistoryLoader struct
method Load (line 64) | func (l *ScenePlayHistoryLoader) Load(key int) ([]time.Time, error) {
method LoadThunk (line 71) | func (l *ScenePlayHistoryLoader) LoadThunk(key int) func() ([]time.Tim...
method LoadAll (line 114) | func (l *ScenePlayHistoryLoader) LoadAll(keys []int) ([][]time.Time, [...
method LoadAllThunk (line 132) | func (l *ScenePlayHistoryLoader) LoadAllThunk(keys []int) func() ([][]...
method Prime (line 150) | func (l *ScenePlayHistoryLoader) Prime(key int, value []time.Time) bool {
method Clear (line 165) | func (l *ScenePlayHistoryLoader) Clear(key int) {
method unsafeSet (line 171) | func (l *ScenePlayHistoryLoader) unsafeSet(key int, value []time.Time) {
type scenePlayHistoryLoaderBatch (line 55) | type scenePlayHistoryLoaderBatch struct
method keyIndex (line 180) | func (b *scenePlayHistoryLoaderBatch) keyIndex(l *ScenePlayHistoryLoad...
method startTimer (line 204) | func (b *scenePlayHistoryLoaderBatch) startTimer(l *ScenePlayHistoryLo...
method end (line 220) | func (b *scenePlayHistoryLoaderBatch) end(l *ScenePlayHistoryLoader) {
FILE: internal/api/loaders/studioloader_gen.go
type StudioLoaderConfig (line 13) | type StudioLoaderConfig struct
function NewStudioLoader (line 25) | func NewStudioLoader(config StudioLoaderConfig) *StudioLoader {
type StudioLoader (line 34) | type StudioLoader struct
method Load (line 66) | func (l *StudioLoader) Load(key int) (*models.Studio, error) {
method LoadThunk (line 73) | func (l *StudioLoader) LoadThunk(key int) func() (*models.Studio, erro...
method LoadAll (line 116) | func (l *StudioLoader) LoadAll(keys []int) ([]*models.Studio, []error) {
method LoadAllThunk (line 134) | func (l *StudioLoader) LoadAllThunk(keys []int) func() ([]*models.Stud...
method Prime (line 152) | func (l *StudioLoader) Prime(key int, value *models.Studio) bool {
method Clear (line 166) | func (l *StudioLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *StudioLoader) unsafeSet(key int, value *models.Studio) {
type studioLoaderBatch (line 57) | type studioLoaderBatch struct
method keyIndex (line 181) | func (b *studioLoaderBatch) keyIndex(l *StudioLoader, key int) int {
method startTimer (line 205) | func (b *studioLoaderBatch) startTimer(l *StudioLoader) {
method end (line 221) | func (b *studioLoaderBatch) end(l *StudioLoader) {
FILE: internal/api/loaders/tagloader_gen.go
type TagLoaderConfig (line 13) | type TagLoaderConfig struct
function NewTagLoader (line 25) | func NewTagLoader(config TagLoaderConfig) *TagLoader {
type TagLoader (line 34) | type TagLoader struct
method Load (line 66) | func (l *TagLoader) Load(key int) (*models.Tag, error) {
method LoadThunk (line 73) | func (l *TagLoader) LoadThunk(key int) func() (*models.Tag, error) {
method LoadAll (line 116) | func (l *TagLoader) LoadAll(keys []int) ([]*models.Tag, []error) {
method LoadAllThunk (line 134) | func (l *TagLoader) LoadAllThunk(keys []int) func() ([]*models.Tag, []...
method Prime (line 152) | func (l *TagLoader) Prime(key int, value *models.Tag) bool {
method Clear (line 166) | func (l *TagLoader) Clear(key int) {
method unsafeSet (line 172) | func (l *TagLoader) unsafeSet(key int, value *models.Tag) {
type tagLoaderBatch (line 57) | type tagLoaderBatch struct
method keyIndex (line 181) | func (b *tagLoaderBatch) keyIndex(l *TagLoader, key int) int {
method startTimer (line 205) | func (b *tagLoaderBatch) startTimer(l *TagLoader) {
method end (line 221) | func (b *tagLoaderBatch) end(l *TagLoader) {
FILE: internal/api/locale.go
function newCollator (line 43) | func newCollator(locale *string, opts ...collate.Option) *collate.Collat...
FILE: internal/api/models.go
type BaseFile (line 10) | type BaseFile interface
type VisualFile (line 14) | type VisualFile interface
function convertVisualFile (line 18) | func convertVisualFile(f models.File) (VisualFile, error) {
function convertBaseFile (line 31) | func convertBaseFile(f models.File) BaseFile {
function convertBaseFiles (line 50) | func convertBaseFiles(files []models.File) []BaseFile {
type GalleryFile (line 54) | type GalleryFile struct
method IsBaseFile (line 58) | func (GalleryFile) IsBaseFile() {}
method IsVisualFile (line 60) | func (GalleryFile) IsVisualFile() {}
method Fingerprints (line 62) | func (f *GalleryFile) Fingerprints() []models.Fingerprint {
type VideoFile (line 66) | type VideoFile struct
method IsBaseFile (line 70) | func (VideoFile) IsBaseFile() {}
method IsVisualFile (line 72) | func (VideoFile) IsVisualFile() {}
method Fingerprints (line 74) | func (f *VideoFile) Fingerprints() []models.Fingerprint {
type ImageFile (line 78) | type ImageFile struct
method IsBaseFile (line 82) | func (ImageFile) IsBaseFile() {}
method IsVisualFile (line 84) | func (ImageFile) IsVisualFile() {}
method Fingerprints (line 86) | func (f *ImageFile) Fingerprints() []models.Fingerprint {
type BasicFile (line 90) | type BasicFile struct
method IsBaseFile (line 94) | func (BasicFile) IsBaseFile() {}
method IsVisualFile (line 96) | func (BasicFile) IsVisualFile() {}
method Fingerprints (line 98) | func (f *BasicFile) Fingerprints() []models.Fingerprint {
FILE: internal/api/plugin_map.go
function MarshalPluginConfigMap (line 11) | func MarshalPluginConfigMap(val map[string]map[string]interface{}) graph...
function UnmarshalPluginConfigMap (line 20) | func UnmarshalPluginConfigMap(v interface{}) (map[string]map[string]inte...
FILE: internal/api/resolver.go
type hookExecutor (line 30) | type hookExecutor interface
type Resolver (line 34) | type Resolver struct
method scraperCache (line 44) | func (r *Resolver) scraperCache() *scraper.Cache {
method Gallery (line 48) | func (r *Resolver) Gallery() GalleryResolver {
method GalleryChapter (line 51) | func (r *Resolver) GalleryChapter() GalleryChapterResolver {
method Mutation (line 54) | func (r *Resolver) Mutation() MutationResolver {
method Performer (line 57) | func (r *Resolver) Performer() PerformerResolver {
method Query (line 60) | func (r *Resolver) Query() QueryResolver {
method Scene (line 63) | func (r *Resolver) Scene() SceneResolver {
method Image (line 66) | func (r *Resolver) Image() ImageResolver {
method SceneMarker (line 69) | func (r *Resolver) SceneMarker() SceneMarkerResolver {
method Studio (line 72) | func (r *Resolver) Studio() StudioResolver {
method Group (line 76) | func (r *Resolver) Group() GroupResolver {
method Movie (line 79) | func (r *Resolver) Movie() MovieResolver {
method Subscription (line 83) | func (r *Resolver) Subscription() SubscriptionResolver {
method Tag (line 86) | func (r *Resolver) Tag() TagResolver {
method GalleryFile (line 89) | func (r *Resolver) GalleryFile() GalleryFileResolver {
method VideoFile (line 92) | func (r *Resolver) VideoFile() VideoFileResolver {
method ImageFile (line 95) | func (r *Resolver) ImageFile() ImageFileResolver {
method BasicFile (line 98) | func (r *Resolver) BasicFile() BasicFileResolver {
method Folder (line 101) | func (r *Resolver) Folder() FolderResolver {
method SavedFilter (line 104) | func (r *Resolver) SavedFilter() SavedFilterResolver {
method Plugin (line 107) | func (r *Resolver) Plugin() PluginResolver {
method ConfigResult (line 110) | func (r *Resolver) ConfigResult() ConfigResultResolver {
method withTxn (line 140) | func (r *Resolver) withTxn(ctx context.Context, fn func(ctx context.Co...
method withReadTxn (line 144) | func (r *Resolver) withReadTxn(ctx context.Context, fn func(ctx contex...
type mutationResolver (line 114) | type mutationResolver struct
method ExecSQL (line 323) | func (r *mutationResolver) ExecSQL(ctx context.Context, sql string, ar...
method QuerySQL (line 342) | func (r *mutationResolver) QuerySQL(ctx context.Context, sql string, a...
type queryResolver (line 115) | type queryResolver struct
method MarkerWall (line 148) | func (r *queryResolver) MarkerWall(ctx context.Context, q *string) (re...
method SceneWall (line 158) | func (r *queryResolver) SceneWall(ctx context.Context, q *string) (ret...
method MarkerStrings (line 169) | func (r *queryResolver) MarkerStrings(ctx context.Context, q *string, ...
method Stats (line 180) | func (r *queryResolver) Stats(ctx context.Context) (*StatsResultType, ...
method Version (line 295) | func (r *queryResolver) Version(ctx context.Context) (*Version, error) {
method Latestversion (line 305) | func (r *queryResolver) Latestversion(ctx context.Context) (*LatestVer...
method SceneMarkerTags (line 362) | func (r *queryResolver) SceneMarkerTags(ctx context.Context, scene_id ...
type subscriptionResolver (line 116) | type subscriptionResolver struct
type galleryResolver (line 118) | type galleryResolver struct
type galleryChapterResolver (line 119) | type galleryChapterResolver struct
type performerResolver (line 120) | type performerResolver struct
type sceneResolver (line 121) | type sceneResolver struct
type sceneMarkerResolver (line 122) | type sceneMarkerResolver struct
type imageResolver (line 123) | type imageResolver struct
type studioResolver (line 124) | type studioResolver struct
type groupResolver (line 127) | type groupResolver struct
type movieResolver (line 128) | type movieResolver struct
type tagResolver (line 130) | type tagResolver struct
type galleryFileResolver (line 131) | type galleryFileResolver struct
type videoFileResolver (line 132) | type videoFileResolver struct
type imageFileResolver (line 133) | type imageFileResolver struct
type basicFileResolver (line 134) | type basicFileResolver struct
type folderResolver (line 135) | type folderResolver struct
type savedFilterResolver (line 136) | type savedFilterResolver struct
type pluginResolver (line 137) | type pluginResolver struct
type configResultResolver (line 138) | type configResultResolver struct
function firstError (line 417) | func firstError(errs []error) error {
FILE: internal/api/resolver_model_config.go
method Plugins (line 9) | func (r *configResultResolver) Plugins(ctx context.Context, obj *ConfigR...
FILE: internal/api/resolver_model_file.go
function fingerprintResolver (line 10) | func fingerprintResolver(fp models.Fingerprints, type_ string) (*string,...
method Fingerprint (line 19) | func (r *galleryFileResolver) Fingerprint(ctx context.Context, obj *Gall...
method Fingerprint (line 23) | func (r *imageFileResolver) Fingerprint(ctx context.Context, obj *ImageF...
method Fingerprint (line 27) | func (r *videoFileResolver) Fingerprint(ctx context.Context, obj *VideoF...
method Fingerprint (line 31) | func (r *basicFileResolver) Fingerprint(ctx context.Context, obj *BasicF...
method ParentFolder (line 35) | func (r *galleryFileResolver) ParentFolder(ctx context.Context, obj *Gal...
method ParentFolder (line 39) | func (r *imageFileResolver) ParentFolder(ctx context.Context, obj *Image...
method ParentFolder (line 43) | func (r *videoFileResolver) ParentFolder(ctx context.Context, obj *Video...
method ParentFolder (line 47) | func (r *basicFileResolver) ParentFolder(ctx context.Context, obj *Basic...
function zipFileResolver (line 51) | func zipFileResolver(ctx context.Context, zipFileID *models.FileID) (*Ba...
method ZipFile (line 66) | func (r *galleryFileResolver) ZipFile(ctx context.Context, obj *GalleryF...
method ZipFile (line 70) | func (r *imageFileResolver) ZipFile(ctx context.Context, obj *ImageFile)...
method ZipFile (line 74) | func (r *videoFileResolver) ZipFile(ctx context.Context, obj *VideoFile)...
method ZipFile (line 78) | func (r *basicFileResolver) ZipFile(ctx context.Context, obj *BasicFile)...
FILE: internal/api/resolver_model_folder.go
method Basename (line 11) | func (r *folderResolver) Basename(ctx context.Context, obj *models.Folde...
method ParentFolder (line 15) | func (r *folderResolver) ParentFolder(ctx context.Context, obj *models.F...
method ParentFolders (line 23) | func (r *folderResolver) ParentFolders(ctx context.Context, obj *models....
method ZipFile (line 34) | func (r *folderResolver) ZipFile(ctx context.Context, obj *models.Folder...
FILE: internal/api/resolver_model_gallery.go
method getFiles (line 15) | func (r *galleryResolver) getFiles(ctx context.Context, obj *models.Gall...
method Files (line 25) | func (r *galleryResolver) Files(ctx context.Context, obj *models.Gallery...
method Folder (line 42) | func (r *galleryResolver) Folder(ctx context.Context, obj *models.Galler...
method Cover (line 69) | func (r *galleryResolver) Cover(ctx context.Context, obj *models.Gallery...
method Date (line 81) | func (r *galleryResolver) Date(ctx context.Context, obj *models.Gallery)...
method Rating100 (line 89) | func (r *galleryResolver) Rating100(ctx context.Context, obj *models.Gal...
method Scenes (line 93) | func (r *galleryResolver) Scenes(ctx context.Context, obj *models.Galler...
method Studio (line 107) | func (r *galleryResolver) Studio(ctx context.Context, obj *models.Galler...
method Tags (line 115) | func (r *galleryResolver) Tags(ctx context.Context, obj *models.Gallery)...
method Performers (line 129) | func (r *galleryResolver) Performers(ctx context.Context, obj *models.Ga...
method ImageCount (line 143) | func (r *galleryResolver) ImageCount(ctx context.Context, obj *models.Ga...
method Chapters (line 155) | func (r *galleryResolver) Chapters(ctx context.Context, obj *models.Gall...
method URL (line 166) | func (r *galleryResolver) URL(ctx context.Context, obj *models.Gallery) ...
method Urls (line 183) | func (r *galleryResolver) Urls(ctx context.Context, obj *models.Gallery)...
method Paths (line 195) | func (r *galleryResolver) Paths(ctx context.Context, obj *models.Gallery...
method Image (line 205) | func (r *galleryResolver) Image(ctx context.Context, obj *models.Gallery...
method CustomFields (line 220) | func (r *galleryResolver) CustomFields(ctx context.Context, obj *models....
FILE: internal/api/resolver_model_gallery_chapter.go
method Gallery (line 9) | func (r *galleryChapterResolver) Gallery(ctx context.Context, obj *model...
FILE: internal/api/resolver_model_image.go
method getFiles (line 11) | func (r *imageResolver) getFiles(ctx context.Context, obj *models.Image)...
method VisualFiles (line 21) | func (r *imageResolver) VisualFiles(ctx context.Context, obj *models.Ima...
method Date (line 38) | func (r *imageResolver) Date(ctx context.Context, obj *models.Image) (*s...
method Files (line 46) | func (r *imageResolver) Files(ctx context.Context, obj *models.Image) ([...
method Paths (line 69) | func (r *imageResolver) Paths(ctx context.Context, obj *models.Image) (*...
method Galleries (line 82) | func (r *imageResolver) Galleries(ctx context.Context, obj *models.Image...
method Rating100 (line 96) | func (r *imageResolver) Rating100(ctx context.Context, obj *models.Image...
method Studio (line 100) | func (r *imageResolver) Studio(ctx context.Context, obj *models.Image) (...
method Tags (line 108) | func (r *imageResolver) Tags(ctx context.Context, obj *models.Image) (re...
method Performers (line 122) | func (r *imageResolver) Performers(ctx context.Context, obj *models.Imag...
method URL (line 136) | func (r *imageResolver) URL(ctx context.Context, obj *models.Image) (*st...
method Urls (line 153) | func (r *imageResolver) Urls(ctx context.Context, obj *models.Image) ([]...
method CustomFields (line 165) | func (r *imageResolver) CustomFields(ctx context.Context, obj *models.Im...
FILE: internal/api/resolver_model_movie.go
method Date (line 14) | func (r *groupResolver) Date(ctx context.Context, obj *models.Group) (*s...
method Rating100 (line 22) | func (r *groupResolver) Rating100(ctx context.Context, obj *models.Group...
method URL (line 26) | func (r *groupResolver) URL(ctx context.Context, obj *models.Group) (*st...
method Urls (line 43) | func (r *groupResolver) Urls(ctx context.Context, obj *models.Group) ([]...
method Studio (line 55) | func (r *groupResolver) Studio(ctx context.Context, obj *models.Group) (...
method Tags (line 63) | func (r groupResolver) Tags(ctx context.Context, obj *models.Group) (ret...
method relatedGroups (line 77) | func (r groupResolver) relatedGroups(ctx context.Context, rgd models.Rel...
method ContainingGroups (line 104) | func (r groupResolver) ContainingGroups(ctx context.Context, obj *models...
method SubGroups (line 116) | func (r groupResolver) SubGroups(ctx context.Context, obj *models.Group)...
method SubGroupCount (line 128) | func (r *groupResolver) SubGroupCount(ctx context.Context, obj *models.G...
method FrontImagePath (line 139) | func (r *groupResolver) FrontImagePath(ctx context.Context, obj *models....
method BackImagePath (line 154) | func (r *groupResolver) BackImagePath(ctx context.Context, obj *models.G...
method SceneCount (line 174) | func (r *groupResolver) SceneCount(ctx context.Context, obj *models.Grou...
method PerformerCount (line 185) | func (r *groupResolver) PerformerCount(ctx context.Context, obj *models....
method Scenes (line 196) | func (r *groupResolver) Scenes(ctx context.Context, obj *models.Group) (...
method OCounter (line 208) | func (r *groupResolver) OCounter(ctx context.Context, obj *models.Group)...
method CustomFields (line 219) | func (r *groupResolver) CustomFields(ctx context.Context, obj *models.Gr...
FILE: internal/api/resolver_model_performer.go
method AliasList (line 15) | func (r *performerResolver) AliasList(ctx context.Context, obj *models.P...
method URL (line 27) | func (r *performerResolver) URL(ctx context.Context, obj *models.Perform...
method Twitter (line 44) | func (r *performerResolver) Twitter(ctx context.Context, obj *models.Per...
method Instagram (line 66) | func (r *performerResolver) Instagram(ctx context.Context, obj *models.P...
method Urls (line 88) | func (r *performerResolver) Urls(ctx context.Context, obj *models.Perfor...
method Height (line 100) | func (r *performerResolver) Height(ctx context.Context, obj *models.Perf...
method HeightCm (line 108) | func (r *performerResolver) HeightCm(ctx context.Context, obj *models.Pe...
method CareerStart (line 112) | func (r *performerResolver) CareerStart(ctx context.Context, obj *models...
method CareerEnd (line 120) | func (r *performerResolver) CareerEnd(ctx context.Context, obj *models.P...
method CareerLength (line 128) | func (r *performerResolver) CareerLength(ctx context.Context, obj *model...
method Birthdate (line 137) | func (r *performerResolver) Birthdate(ctx context.Context, obj *models.P...
method ImagePath (line 145) | func (r *performerResolver) ImagePath(ctx context.Context, obj *models.P...
method Tags (line 160) | func (r *performerResolver) Tags(ctx context.Context, obj *models.Perfor...
method SceneCount (line 174) | func (r *performerResolver) SceneCount(ctx context.Context, obj *models....
method ImageCount (line 185) | func (r *performerResolver) ImageCount(ctx context.Context, obj *models....
method GalleryCount (line 196) | func (r *performerResolver) GalleryCount(ctx context.Context, obj *model...
method GroupCount (line 207) | func (r *performerResolver) GroupCount(ctx context.Context, obj *models....
method MovieCount (line 219) | func (r *performerResolver) MovieCount(ctx context.Context, obj *models....
method PerformerCount (line 223) | func (r *performerResolver) PerformerCount(ctx context.Context, obj *mod...
method OCounter (line 234) | func (r *performerResolver) OCounter(ctx context.Context, obj *models.Pe...
method Scenes (line 252) | func (r *performerResolver) Scenes(ctx context.Context, obj *models.Perf...
method StashIds (line 263) | func (r *performerResolver) StashIds(ctx context.Context, obj *models.Pe...
method Rating100 (line 273) | func (r *performerResolver) Rating100(ctx context.Context, obj *models.P...
method DeathDate (line 277) | func (r *performerResolver) DeathDate(ctx context.Context, obj *models.P...
method Groups (line 285) | func (r *performerResolver) Groups(ctx context.Context, obj *models.Perf...
method CustomFields (line 296) | func (r *performerResolver) CustomFields(ctx context.Context, obj *model...
method Movies (line 310) | func (r *performerResolver) Movies(ctx context.Context, obj *models.Perf...
FILE: internal/api/resolver_model_plugin.go
type pluginURLBuilder (line 9) | type pluginURLBuilder struct
method javascript (line 14) | func (b pluginURLBuilder) javascript() []string {
method css (line 28) | func (b pluginURLBuilder) css() []string {
method paths (line 41) | func (b *pluginURLBuilder) paths() *PluginPaths {
method Paths (line 48) | func (r *pluginResolver) Paths(ctx context.Context, obj *plugin.Plugin) ...
method Requires (line 59) | func (r *pluginResolver) Requires(ctx context.Context, obj *plugin.Plugi...
FILE: internal/api/resolver_model_saved_filter.go
method Filter (line 9) | func (r *savedFilterResolver) Filter(ctx context.Context, obj *models.Sa...
FILE: internal/api/resolver_model_scene.go
function convertVideoFile (line 14) | func convertVideoFile(f models.File) (*models.VideoFile, error) {
method getPrimaryFile (line 22) | func (r *sceneResolver) getPrimaryFile(ctx context.Context, obj *models....
method getFiles (line 44) | func (r *sceneResolver) getFiles(ctx context.Context, obj *models.Scene)...
method Date (line 69) | func (r *sceneResolver) Date(ctx context.Context, obj *models.Scene) (*s...
method Files (line 77) | func (r *sceneResolver) Files(ctx context.Context, obj *models.Scene) ([...
method Rating (line 94) | func (r *sceneResolver) Rating(ctx context.Context, obj *models.Scene) (...
method Rating100 (line 102) | func (r *sceneResolver) Rating100(ctx context.Context, obj *models.Scene...
method Paths (line 106) | func (r *sceneResolver) Paths(ctx context.Context, obj *models.Scene) (*...
method SceneMarkers (line 134) | func (r *sceneResolver) SceneMarkers(ctx context.Context, obj *models.Sc...
method Captions (line 145) | func (r *sceneResolver) Captions(ctx context.Context, obj *models.Scene)...
method Galleries (line 164) | func (r *sceneResolver) Galleries(ctx context.Context, obj *models.Scene...
method Studio (line 178) | func (r *sceneResolver) Studio(ctx context.Context, obj *models.Scene) (...
method Movies (line 186) | func (r *sceneResolver) Movies(ctx context.Context, obj *models.Scene) (...
method Groups (line 217) | func (r *sceneResolver) Groups(ctx context.Context, obj *models.Scene) (...
method Tags (line 248) | func (r *sceneResolver) Tags(ctx context.Context, obj *models.Scene) (re...
method Performers (line 262) | func (r *sceneResolver) Performers(ctx context.Context, obj *models.Scen...
method StashIds (line 276) | func (r *sceneResolver) StashIds(ctx context.Context, obj *models.Scene)...
method SceneStreams (line 286) | func (r *sceneResolver) SceneStreams(ctx context.Context, obj *models.Sc...
method Interactive (line 302) | func (r *sceneResolver) Interactive(ctx context.Context, obj *models.Sce...
method InteractiveSpeed (line 314) | func (r *sceneResolver) InteractiveSpeed(ctx context.Context, obj *model...
method URL (line 326) | func (r *sceneResolver) URL(ctx context.Context, obj *models.Scene) (*st...
method Urls (line 343) | func (r *sceneResolver) Urls(ctx context.Context, obj *models.Scene) ([]...
method OCounter (line 355) | func (r *sceneResolver) OCounter(ctx context.Context, obj *models.Scene)...
method LastPlayedAt (line 364) | func (r *sceneResolver) LastPlayedAt(ctx context.Context, obj *models.Sc...
method PlayCount (line 373) | func (r *sceneResolver) PlayCount(ctx context.Context, obj *models.Scene...
method PlayHistory (line 382) | func (r *sceneResolver) PlayHistory(ctx context.Context, obj *models.Sce...
method OHistory (line 398) | func (r *sceneResolver) OHistory(ctx context.Context, obj *models.Scene)...
method CustomFields (line 414) | func (r *sceneResolver) CustomFields(ctx context.Context, obj *models.Sc...
FILE: internal/api/resolver_model_scene_marker.go
method Scene (line 10) | func (r *sceneMarkerResolver) Scene(ctx context.Context, obj *models.Sce...
method PrimaryTag (line 21) | func (r *sceneMarkerResolver) PrimaryTag(ctx context.Context, obj *model...
method Tags (line 32) | func (r *sceneMarkerResolver) Tags(ctx context.Context, obj *models.Scen...
method Stream (line 43) | func (r *sceneMarkerResolver) Stream(ctx context.Context, obj *models.Sc...
method Preview (line 48) | func (r *sceneMarkerResolver) Preview(ctx context.Context, obj *models.S...
method Screenshot (line 53) | func (r *sceneMarkerResolver) Screenshot(ctx context.Context, obj *model...
FILE: internal/api/resolver_model_studio.go
method ImagePath (line 16) | func (r *studioResolver) ImagePath(ctx context.Context, obj *models.Stud...
method Aliases (line 31) | func (r *studioResolver) Aliases(ctx context.Context, obj *models.Studio...
method URL (line 43) | func (r *studioResolver) URL(ctx context.Context, obj *models.Studio) (*...
method Urls (line 60) | func (r *studioResolver) Urls(ctx context.Context, obj *models.Studio) (...
method Tags (line 72) | func (r *studioResolver) Tags(ctx context.Context, obj *models.Studio) (...
method SceneCount (line 86) | func (r *studioResolver) SceneCount(ctx context.Context, obj *models.Stu...
method ImageCount (line 97) | func (r *studioResolver) ImageCount(ctx context.Context, obj *models.Stu...
method GalleryCount (line 108) | func (r *studioResolver) GalleryCount(ctx context.Context, obj *models.S...
method PerformerCount (line 119) | func (r *studioResolver) PerformerCount(ctx context.Context, obj *models...
method GroupCount (line 130) | func (r *studioResolver) GroupCount(ctx context.Context, obj *models.Stu...
method MovieCount (line 142) | func (r *studioResolver) MovieCount(ctx context.Context, obj *models.Stu...
method OCounter (line 146) | func (r *studioResolver) OCounter(ctx context.Context, obj *models.Studi...
method ParentStudio (line 164) | func (r *studioResolver) ParentStudio(ctx context.Context, obj *models.S...
method ChildStudios (line 172) | func (r *studioResolver) ChildStudios(ctx context.Context, obj *models.S...
method StashIds (line 183) | func (r *studioResolver) StashIds(ctx context.Context, obj *models.Studi...
method Rating100 (line 195) | func (r *studioResolver) Rating100(ctx context.Context, obj *models.Stud...
method Groups (line 199) | func (r *studioResolver) Groups(ctx context.Context, obj *models.Studio)...
method CustomFields (line 210) | func (r *studioResolver) CustomFields(ctx context.Context, obj *models.S...
method Movies (line 224) | func (r *studioResolver) Movies(ctx context.Context, obj *models.Studio)...
FILE: internal/api/resolver_model_tag.go
method Parents (line 17) | func (r *tagResolver) Parents(ctx context.Context, obj *models.Tag) (ret...
method Children (line 31) | func (r *tagResolver) Children(ctx context.Context, obj *models.Tag) (re...
method Aliases (line 45) | func (r *tagResolver) Aliases(ctx context.Context, obj *models.Tag) (ret...
method StashIds (line 57) | func (r *tagResolver) StashIds(ctx context.Context, obj *models.Tag) ([]...
method SceneCount (line 67) | func (r *tagResolver) SceneCount(ctx context.Context, obj *models.Tag, d...
method SceneMarkerCount (line 78) | func (r *tagResolver) SceneMarkerCount(ctx context.Context, obj *models....
method ImageCount (line 89) | func (r *tagResolver) ImageCount(ctx context.Context, obj *models.Tag, d...
method GalleryCount (line 100) | func (r *tagResolver) GalleryCount(ctx context.Context, obj *models.Tag,...
method PerformerCount (line 111) | func (r *tagResolver) PerformerCount(ctx context.Context, obj *models.Ta...
method StudioCount (line 122) | func (r *tagResolver) StudioCount(ctx context.Context, obj *models.Tag, ...
method GroupCount (line 133) | func (r *tagResolver) GroupCount(ctx context.Context, obj *models.Tag, d...
method MovieCount (line 144) | func (r *tagResolver) MovieCount(ctx context.Context, obj *models.Tag, d...
method ImagePath (line 148) | func (r *tagResolver) ImagePath(ctx context.Context, obj *models.Tag) (*...
method ParentCount (line 163) | func (r *tagResolver) ParentCount(ctx context.Context, obj *models.Tag) ...
method ChildCount (line 174) | func (r *tagResolver) ChildCount(ctx context.Context, obj *models.Tag) (...
method CustomFields (line 185) | func (r *tagResolver) CustomFields(ctx context.Context, obj *models.Tag)...
FILE: internal/api/resolver_mutation_configure.go
method Setup (line 25) | func (r *mutationResolver) Setup(ctx context.Context, input manager.Setu...
method DownloadFFMpeg (line 30) | func (r *mutationResolver) DownloadFFMpeg(ctx context.Context) (string, ...
method setConfigString (line 58) | func (r *mutationResolver) setConfigString(key string, value *string) {
method setConfigBool (line 65) | func (r *mutationResolver) setConfigBool(key string, value *bool) {
method setConfigInt (line 72) | func (r *mutationResolver) setConfigInt(key string, value *int) {
method setConfigFloat (line 79) | func (r *mutationResolver) setConfigFloat(key string, value *float64) {
method ConfigureGeneral (line 86) | func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input C...
method ConfigureInterface (line 470) | func (r *mutationResolver) ConfigureInterface(ctx context.Context, input...
method ConfigureDlna (line 552) | func (r *mutationResolver) ConfigureDlna(ctx context.Context, input Conf...
method ConfigureScraping (line 585) | func (r *mutationResolver) ConfigureScraping(ctx context.Context, input ...
method ConfigureDefaults (line 621) | func (r *mutationResolver) ConfigureDefaults(ctx context.Context, input ...
method GenerateAPIKey (line 652) | func (r *mutationResolver) GenerateAPIKey(ctx context.Context, input Gen...
method ConfigureUI (line 675) | func (r *mutationResolver) ConfigureUI(ctx context.Context, input map[st...
method ConfigureUISetting (line 700) | func (r *mutationResolver) ConfigureUISetting(ctx context.Context, key s...
method ConfigurePlugin (line 717) | func (r *mutationResolver) ConfigurePlugin(ctx context.Context, pluginID...
FILE: internal/api/resolver_mutation_dlna.go
method EnableDlna (line 10) | func (r *mutationResolver) EnableDlna(ctx context.Context, input EnableD...
method DisableDlna (line 18) | func (r *mutationResolver) DisableDlna(ctx context.Context, input Disabl...
method AddTempDlnaip (line 23) | func (r *mutationResolver) AddTempDlnaip(ctx context.Context, input AddT...
method RemoveTempDlnaip (line 28) | func (r *mutationResolver) RemoveTempDlnaip(ctx context.Context, input R...
function parseMinutes (line 33) | func parseMinutes(minutes *int) *time.Duration {
FILE: internal/api/resolver_mutation_file.go
method MoveFiles (line 19) | func (r *mutationResolver) MoveFiles(ctx context.Context, input MoveFile...
method validateFolderPath (line 117) | func (r *mutationResolver) validateFolderPath(paths config.StashConfigs,...
method validateFileExtension (line 125) | func (r *mutationResolver) validateFileExtension(oldBasename, newBasenam...
method validateFileExtensionList (line 142) | func (r *mutationResolver) validateFileExtensionList(exts []string, oldB...
method DeleteFiles (line 150) | func (r *mutationResolver) DeleteFiles(ctx context.Context, ids []string...
method DestroyFiles (line 217) | func (r *mutationResolver) DestroyFiles(ctx context.Context, ids []strin...
method FileSetFingerprints (line 269) | func (r *mutationResolver) FileSetFingerprints(ctx context.Context, inpu...
method RevealFileInFileManager (line 334) | func (r *mutationResolver) RevealFileInFileManager(ctx context.Context, ...
method RevealFolderInFileManager (line 368) | func (r *mutationResolver) RevealFolderInFileManager(ctx context.Context...
FILE: internal/api/resolver_mutation_gallery.go
method getGallery (line 23) | func (r *mutationResolver) getGallery(ctx context.Context, id int) (ret ...
method GalleryCreate (line 34) | func (r *mutationResolver) GalleryCreate(ctx context.Context, input Gall...
method GalleryUpdate (line 105) | func (r *mutationResolver) GalleryUpdate(ctx context.Context, input mode...
method GalleriesUpdate (line 123) | func (r *mutationResolver) GalleriesUpdate(ctx context.Context, input []...
method galleryUpdate (line 166) | func (r *mutationResolver) galleryUpdate(ctx context.Context, input mode...
method BulkGalleryUpdate (line 263) | func (r *mutationResolver) BulkGalleryUpdate(ctx context.Context, input ...
method GalleryDestroy (line 345) | func (r *mutationResolver) GalleryDestroy(ctx context.Context, input mod...
function isStashPath (line 428) | func isStashPath(path string) bool {
method AddGalleryImages (line 439) | func (r *mutationResolver) AddGalleryImages(ctx context.Context, input G...
method RemoveGalleryImages (line 469) | func (r *mutationResolver) RemoveGalleryImages(ctx context.Context, inpu...
method SetGalleryCover (line 499) | func (r *mutationResolver) SetGalleryCover(ctx context.Context, input Ga...
method ResetGalleryCover (line 529) | func (r *mutationResolver) ResetGalleryCover(ctx context.Context, input ...
method getGalleryChapter (line 554) | func (r *mutationResolver) getGalleryChapter(ctx context.Context, id int...
method GalleryChapterCreate (line 565) | func (r *mutationResolver) GalleryChapterCreate(ctx context.Context, inp...
method GalleryChapterUpdate (line 599) | func (r *mutationResolver) GalleryChapterUpdate(ctx context.Context, inp...
method GalleryChapterDestroy (line 665) | func (r *mutationResolver) GalleryChapterDestroy(ctx context.Context, id...
FILE: internal/api/resolver_mutation_group.go
function groupFromGroupCreateInput (line 17) | func groupFromGroupCreateInput(ctx context.Context, input GroupCreateInp...
method GroupCreate (line 93) | func (r *mutationResolver) GroupCreate(ctx context.Context, input GroupC...
function groupPartialFromGroupUpdateInput (line 116) | func groupPartialFromGroupUpdateInput(translator changesetTranslator, in...
method GroupUpdate (line 167) | func (r *mutationResolver) GroupUpdate(ctx context.Context, input GroupU...
function groupPartialFromBulkGroupUpdateInput (line 227) | func groupPartialFromBulkGroupUpdateInput(translator changesetTranslator...
method BulkGroupUpdate (line 275) | func (r *mutationResolver) BulkGroupUpdate(ctx context.Context, input Bu...
method GroupDestroy (line 325) | func (r *mutationResolver) GroupDestroy(ctx context.Context, input Group...
method GroupsDestroy (line 344) | func (r *mutationResolver) GroupsDestroy(ctx context.Context, groupIDs [...
method AddGroupSubGroups (line 372) | func (r *mutationResolver) AddGroupSubGroups(ctx context.Context, input ...
method RemoveGroupSubGroups (line 392) | func (r *mutationResolver) RemoveGroupSubGroups(ctx context.Context, inp...
method ReorderSubGroups (line 412) | func (r *mutationResolver) ReorderSubGroups(ctx context.Context, input R...
FILE: internal/api/resolver_mutation_image.go
method getImage (line 20) | func (r *mutationResolver) getImage(ctx context.Context, id int) (ret *m...
method ImageUpdate (line 31) | func (r *mutationResolver) ImageUpdate(ctx context.Context, input models...
method ImagesUpdate (line 49) | func (r *mutationResolver) ImagesUpdate(ctx context.Context, input []*mo...
method imageUpdate (line 92) | func (r *mutationResolver) imageUpdate(ctx context.Context, input models...
method BulkImageUpdate (line 203) | func (r *mutationResolver) BulkImageUpdate(ctx context.Context, input Bu...
method ImageDestroy (line 319) | func (r *mutationResolver) ImageDestroy(ctx context.Context, input model...
method ImagesDestroy (line 361) | func (r *mutationResolver) ImagesDestroy(ctx context.Context, input mode...
method ImageIncrementO (line 415) | func (r *mutationResolver) ImageIncrementO(ctx context.Context, id strin...
method ImageDecrementO (line 433) | func (r *mutationResolver) ImageDecrementO(ctx context.Context, id strin...
method ImageResetO (line 451) | func (r *mutationResolver) ImageResetO(ctx context.Context, id string) (...
FILE: internal/api/resolver_mutation_job.go
method StopJob (line 11) | func (r *mutationResolver) StopJob(ctx context.Context, jobID string) (b...
method StopAllJobs (line 21) | func (r *mutationResolver) StopAllJobs(ctx context.Context) (bool, error) {
FILE: internal/api/resolver_mutation_metadata.go
method MetadataScan (line 17) | func (r *mutationResolver) MetadataScan(ctx context.Context, input manag...
method MetadataImport (line 27) | func (r *mutationResolver) MetadataImport(ctx context.Context) (string, ...
method ImportObjects (line 36) | func (r *mutationResolver) ImportObjects(ctx context.Context, input mana...
method MetadataExport (line 47) | func (r *mutationResolver) MetadataExport(ctx context.Context) (string, ...
method ExportObjects (line 56) | func (r *mutationResolver) ExportObjects(ctx context.Context, input mana...
method MetadataGenerate (line 75) | func (r *mutationResolver) MetadataGenerate(ctx context.Context, input m...
method MetadataAutoTag (line 85) | func (r *mutationResolver) MetadataAutoTag(ctx context.Context, input ma...
method MetadataIdentify (line 90) | func (r *mutationResolver) MetadataIdentify(ctx context.Context, input i...
method MetadataClean (line 97) | func (r *mutationResolver) MetadataClean(ctx context.Context, input mana...
method MetadataCleanGenerated (line 102) | func (r *mutationResolver) MetadataCleanGenerated(ctx context.Context, i...
method MigrateHashNaming (line 117) | func (r *mutationResolver) MigrateHashNaming(ctx context.Context) (strin...
method BackupDatabase (line 122) | func (r *mutationResolver) BackupDatabase(ctx context.Context, input Bac...
method AnonymiseDatabase (line 152) | func (r *mutationResolver) AnonymiseDatabase(ctx context.Context, input ...
method OptimiseDatabase (line 181) | func (r *mutationResolver) OptimiseDatabase(ctx context.Context) (string...
FILE: internal/api/resolver_mutation_migrate.go
method MigrateSceneScreenshots (line 13) | func (r *mutationResolver) MigrateSceneScreenshots(ctx context.Context, ...
method MigrateBlobs (line 29) | func (r *mutationResolver) MigrateBlobs(ctx context.Context, input Migra...
method Migrate (line 42) | func (r *mutationResolver) Migrate(ctx context.Context, input manager.Mi...
FILE: internal/api/resolver_mutation_movie.go
method getGroup (line 17) | func (r *mutationResolver) getGroup(ctx context.Context, id int) (ret *m...
method MovieCreate (line 28) | func (r *mutationResolver) MovieCreate(ctx context.Context, input MovieC...
method MovieUpdate (line 122) | func (r *mutationResolver) MovieUpdate(ctx context.Context, input MovieU...
method BulkMovieUpdate (line 209) | func (r *mutationResolver) BulkMovieUpdate(ctx context.Context, input Bu...
method MovieDestroy (line 273) | func (r *mutationResolver) MovieDestroy(ctx context.Context, input Movie...
method MoviesDestroy (line 292) | func (r *mutationResolver) MoviesDestroy(ctx context.Context, groupIDs [...
FILE: internal/api/resolver_mutation_package.go
function refreshPackageType (line 12) | func refreshPackageType(typeArg PackageType) {
method InstallPackages (line 22) | func (r *mutationResolver) InstallPackages(ctx context.Context, typeArg ...
method UpdatePackages (line 41) | func (r *mutationResolver) UpdatePackages(ctx context.Context, typeArg P...
method UninstallPackages (line 60) | func (r *mutationResolver) UninstallPackages(ctx context.Context, typeAr...
FILE: internal/api/resolver_mutation_performer.go
constant twitterURL (line 20) | twitterURL = "https://twitter.com"
constant instagramURL (line 21) | instagramURL = "https://instagram.com"
method getPerformer (line 25) | func (r *mutationResolver) getPerformer(ctx context.Context, id int) (re...
method PerformerCreate (line 36) | func (r *mutationResolver) PerformerCreate(ctx context.Context, input mo...
function validateNoLegacyURLs (line 160) | func validateNoLegacyURLs(translator changesetTranslator) error {
method handleLegacyURLs (line 175) | func (r *mutationResolver) handleLegacyURLs(ctx context.Context, perform...
type legacyPerformerURLs (line 250) | type legacyPerformerURLs struct
method AnySet (line 256) | func (u *legacyPerformerURLs) AnySet() bool {
function legacyPerformerURLsFromInput (line 260) | func legacyPerformerURLsFromInput(input models.PerformerUpdateInput, tra...
function performerPartialFromInput (line 268) | func performerPartialFromInput(input models.PerformerUpdateInput, transl...
method PerformerUpdate (line 355) | func (r *mutationResolver) PerformerUpdate(ctx context.Context, input mo...
method BulkPerformerUpdate (line 437) | func (r *mutationResolver) BulkPerformerUpdate(ctx context.Context, inpu...
method PerformerDestroy (line 581) | func (r *mutationResolver) PerformerDestroy(ctx context.Context, input P...
method PerformersDestroy (line 598) | func (r *mutationResolver) PerformersDestroy(ctx context.Context, perfor...
method PerformerMerge (line 624) | func (r *mutationResolver) PerformerMerge(ctx context.Context, input Per...
FILE: internal/api/resolver_mutation_plugin.go
function toPluginArgs (line 13) | func toPluginArgs(args []*plugin.PluginArgInput) plugin.OperationInput {
function toPluginArgValue (line 22) | func toPluginArgValue(arg *plugin.PluginValueInput) interface{} {
method RunPluginTask (line 49) | func (r *mutationResolver) RunPluginTask(
method RunPluginOperation (line 68) | func (r *mutationResolver) RunPluginOperation(
method ReloadPlugins (line 81) | func (r *mutationResolver) ReloadPlugins(ctx context.Context) (bool, err...
method SetPluginsEnabled (line 86) | func (r *mutationResolver) SetPluginsEnabled(ctx context.Context, enable...
FILE: internal/api/resolver_mutation_saved_filter.go
method SaveFilter (line 16) | func (r *mutationResolver) SaveFilter(ctx context.Context, input SaveFil...
method DestroySavedFilter (line 57) | func (r *mutationResolver) DestroySavedFilter(ctx context.Context, input...
method SetDefaultFilter (line 72) | func (r *mutationResolver) SetDefaultFilter(ctx context.Context, input S...
FILE: internal/api/resolver_mutation_scene.go
method getScene (line 24) | func (r *mutationResolver) getScene(ctx context.Context, id int) (ret *m...
method SceneCreate (line 35) | func (r *mutationResolver) SceneCreate(ctx context.Context, input models...
method SceneUpdate (line 123) | func (r *mutationResolver) SceneUpdate(ctx context.Context, input models...
method ScenesUpdate (line 140) | func (r *mutationResolver) ScenesUpdate(ctx context.Context, input []*mo...
function scenePartialFromInput (line 183) | func scenePartialFromInput(input models.SceneUpdateInput, translator cha...
method sceneUpdate (line 250) | func (r *mutationResolver) sceneUpdate(ctx context.Context, input models...
method sceneUpdateCoverImage (line 345) | func (r *mutationResolver) sceneUpdateCoverImage(ctx context.Context, s ...
method BulkSceneUpdate (line 356) | func (r *mutationResolver) BulkSceneUpdate(ctx context.Context, input Bu...
method SceneDestroy (line 460) | func (r *mutationResolver) SceneDestroy(ctx context.Context, input model...
method ScenesDestroy (line 515) | func (r *mutationResolver) ScenesDestroy(ctx context.Context, input mode...
method SceneAssignFile (line 579) | func (r *mutationResolver) SceneAssignFile(ctx context.Context, input As...
method SceneMerge (line 599) | func (r *mutationResolver) SceneMerge(ctx context.Context, input SceneMe...
method getSceneMarker (line 688) | func (r *mutationResolver) getSceneMarker(ctx context.Context, id int) (...
method SceneMarkerCreate (line 699) | func (r *mutationResolver) SceneMarkerCreate(ctx context.Context, input ...
function validateSceneMarkerEndSeconds (line 750) | func validateSceneMarkerEndSeconds(seconds, endSeconds float64) error {
function float64OrZero (line 757) | func float64OrZero(f *float64) float64 {
method SceneMarkerUpdate (line 764) | func (r *mutationResolver) SceneMarkerUpdate(ctx context.Context, input ...
method BulkSceneMarkerUpdate (line 884) | func (r *mutationResolver) BulkSceneMarkerUpdate(ctx context.Context, in...
function adjustMarkerPartialForTagExclusion (line 952) | func adjustMarkerPartialForTagExclusion(ctx context.Context, r models.Sc...
method SceneMarkerDestroy (line 1001) | func (r *mutationResolver) SceneMarkerDestroy(ctx context.Context, id st...
method SceneMarkersDestroy (line 1005) | func (r *mutationResolver) SceneMarkersDestroy(ctx context.Context, mark...
method SceneSaveActivity (line 1068) | func (r *mutationResolver) SceneSaveActivity(ctx context.Context, id str...
method SceneResetActivity (line 1086) | func (r *mutationResolver) SceneResetActivity(ctx context.Context, id st...
method SceneIncrementPlayCount (line 1105) | func (r *mutationResolver) SceneIncrementPlayCount(ctx context.Context, ...
method SceneAddPlay (line 1125) | func (r *mutationResolver) SceneAddPlay(ctx context.Context, id string, ...
method SceneDeletePlay (line 1155) | func (r *mutationResolver) SceneDeletePlay(ctx context.Context, id strin...
method SceneResetPlayCount (line 1184) | func (r *mutationResolver) SceneResetPlayCount(ctx context.Context, id s...
method SceneIncrementO (line 1203) | func (r *mutationResolver) SceneIncrementO(ctx context.Context, id strin...
method SceneDecrementO (line 1224) | func (r *mutationResolver) SceneDecrementO(ctx context.Context, id strin...
method SceneResetO (line 1244) | func (r *mutationResolver) SceneResetO(ctx context.Context, id string) (...
method SceneAddO (line 1262) | func (r *mutationResolver) SceneAddO(ctx context.Context, id string, t [...
method SceneDeleteO (line 1292) | func (r *mutationResolver) SceneDeleteO(ctx context.Context, id string, ...
method SceneGenerateScreenshot (line 1321) | func (r *mutationResolver) SceneGenerateScreenshot(ctx context.Context, ...
FILE: internal/api/resolver_mutation_scraper.go
method ReloadScrapers (line 9) | func (r *mutationResolver) ReloadScrapers(ctx context.Context) (bool, er...
FILE: internal/api/resolver_mutation_stash_box.go
method SubmitStashBoxFingerprints (line 16) | func (r *mutationResolver) SubmitStashBoxFingerprints(ctx context.Contex...
method StashBoxBatchPerformerTag (line 41) | func (r *mutationResolver) StashBoxBatchPerformerTag(ctx context.Context...
method StashBoxBatchStudioTag (line 51) | func (r *mutationResolver) StashBoxBatchStudioTag(ctx context.Context, i...
method StashBoxBatchTagTag (line 61) | func (r *mutationResolver) StashBoxBatchTagTag(ctx context.Context, inpu...
method SubmitStashBoxSceneDraft (line 71) | func (r *mutationResolver) SubmitStashBoxSceneDraft(ctx context.Context,...
method makeSceneDraft (line 113) | func (r *mutationResolver) makeSceneDraft(ctx context.Context, s *models...
method SubmitStashBoxPerformerDraft (line 179) | func (r *mutationResolver) SubmitStashBoxPerformerDraft(ctx context.Cont...
FILE: internal/api/resolver_mutation_studio.go
method getStudio (line 17) | func (r *mutationResolver) getStudio(ctx context.Context, id int) (ret *...
method StudioCreate (line 28) | func (r *mutationResolver) StudioCreate(ctx context.Context, input model...
method StudioUpdate (line 105) | func (r *mutationResolver) StudioUpdate(ctx context.Context, input model...
method BulkStudioUpdate (line 224) | func (r *mutationResolver) BulkStudioUpdate(ctx context.Context, input B...
method StudioDestroy (line 315) | func (r *mutationResolver) StudioDestroy(ctx context.Context, input Stud...
method StudiosDestroy (line 332) | func (r *mutationResolver) StudiosDestroy(ctx context.Context, studioIDs...
FILE: internal/api/resolver_mutation_tag.go
method getTag (line 16) | func (r *mutationResolver) getTag(ctx context.Context, id int) (ret *mod...
method TagCreate (line 27) | func (r *mutationResolver) TagCreate(ctx context.Context, input TagCreat...
function tagPartialFromInput (line 105) | func tagPartialFromInput(input TagUpdateInput, translator changesetTrans...
method TagUpdate (line 145) | func (r *mutationResolver) TagUpdate(ctx context.Context, input TagUpdat...
method BulkTagUpdate (line 222) | func (r *mutationResolver) BulkTagUpdate(ctx context.Context, input Bulk...
method TagDestroy (line 291) | func (r *mutationResolver) TagDestroy(ctx context.Context, input TagDest...
method TagsDestroy (line 308) | func (r *mutationResolver) TagsDestroy(ctx context.Context, tagIDs []str...
method TagsMerge (line 334) | func (r *mutationResolver) TagsMerge(ctx context.Context, input TagsMerg...
FILE: internal/api/resolver_mutation_tag_test.go
function newResolver (line 17) | func newResolver(db *mocks.Database) *Resolver {
constant tagName (line 25) | tagName = "tagName"
constant errTagName (line 26) | errTagName = "errTagName"
constant existingTagID (line 28) | existingTagID = 1
constant existingTagName (line 29) | existingTagName = "existingTagName"
constant newTagID (line 31) | newTagID = 2
type mockHookExecutor (line 36) | type mockHookExecutor struct
method ExecutePostHooks (line 38) | func (*mockHookExecutor) ExecutePostHooks(ctx context.Context, id int,...
function TestTagCreate (line 41) | func TestTagCreate(t *testing.T) {
FILE: internal/api/resolver_query_configuration.go
method Configuration (line 15) | func (r *queryResolver) Configuration(ctx context.Context) (*ConfigResul...
method Directory (line 19) | func (r *queryResolver) Directory(ctx context.Context, path, locale *str...
function getDir (line 43) | func getDir(path string) string {
function getParent (line 51) | func getParent(path string) *string {
function makeConfigResult (line 61) | func makeConfigResult() *ConfigResult {
function makeConfigGeneralResult (line 72) | func makeConfigGeneralResult() *ConfigGeneralResult {
function makeConfigInterfaceResult (line 144) | func makeConfigInterfaceResult() *ConfigInterfaceResult {
function makeConfigDLNAResult (line 205) | func makeConfigDLNAResult() *ConfigDLNAResult {
function makeConfigScrapingResult (line 218) | func makeConfigScrapingResult() *ConfigScrapingResult {
function makeConfigDefaultsResult (line 232) | func makeConfigDefaultsResult() *ConfigDefaultSettingsResult {
function makeConfigUIResult (line 247) | func makeConfigUIResult() map[string]interface{} {
method ValidateStashBoxCredentials (line 251) | func (r *queryResolver) ValidateStashBoxCredentials(ctx context.Context,...
FILE: internal/api/resolver_query_dlna.go
method DlnaStatus (line 10) | func (r *queryResolver) DlnaStatus(ctx context.Context) (*dlna.Status, e...
FILE: internal/api/resolver_query_find_file.go
method FindFile (line 12) | func (r *queryResolver) FindFile(ctx context.Context, id *string, path *...
method FindFiles (line 48) | func (r *queryResolver) FindFiles(
FILE: internal/api/resolver_query_find_folder.go
method FindFolder (line 11) | func (r *queryResolver) FindFolder(ctx context.Context, id *string, path...
method FindFolders (line 43) | func (r *queryResolver) FindFolders(
FILE: internal/api/resolver_query_find_gallery.go
method FindGallery (line 10) | func (r *queryResolver) FindGallery(ctx context.Context, id string) (ret...
method FindGalleries (line 26) | func (r *queryResolver) FindGalleries(ctx context.Context, galleryFilter...
method AllGalleries (line 60) | func (r *queryResolver) AllGalleries(ctx context.Context) (ret []*models...
FILE: internal/api/resolver_query_find_group.go
method FindGroup (line 10) | func (r *queryResolver) FindGroup(ctx context.Context, id string) (ret *...
method FindGroups (line 26) | func (r *queryResolver) FindGroups(ctx context.Context, groupFilter *mod...
FILE: internal/api/resolver_query_find_image.go
method FindImage (line 12) | func (r *queryResolver) FindImage(ctx context.Context, id *string, check...
method FindImages (line 49) | func (r *queryResolver) FindImages(
method AllImages (line 127) | func (r *queryResolver) AllImages(ctx context.Context) (ret []*models.Im...
FILE: internal/api/resolver_query_find_movie.go
method FindMovie (line 10) | func (r *queryResolver) FindMovie(ctx context.Context, id string) (ret *...
method FindMovies (line 26) | func (r *queryResolver) FindMovies(ctx context.Context, movieFilter *mod...
method AllMovies (line 60) | func (r *queryResolver) AllMovies(ctx context.Context) (ret []*models.Gr...
FILE: internal/api/resolver_query_find_performer.go
method FindPerformer (line 10) | func (r *queryResolver) FindPerformer(ctx context.Context, id string) (r...
method FindPerformers (line 26) | func (r *queryResolver) FindPerformers(ctx context.Context, performerFil...
method AllPerformers (line 68) | func (r *queryResolver) AllPerformers(ctx context.Context) (ret []*model...
FILE: internal/api/resolver_query_find_saved_filter.go
method FindSavedFilter (line 14) | func (r *queryResolver) FindSavedFilter(ctx context.Context, id string) ...
method FindSavedFilters (line 29) | func (r *queryResolver) FindSavedFilters(ctx context.Context, mode *mode...
method FindDefaultFilter (line 43) | func (r *queryResolver) FindDefaultFilter(ctx context.Context, mode mode...
FILE: internal/api/resolver_query_find_scene.go
method FindScene (line 14) | func (r *queryResolver) FindScene(ctx context.Context, id *string, check...
method FindSceneByHash (line 44) | func (r *queryResolver) FindSceneByHash(ctx context.Context, input Scene...
method FindScenes (line 77) | func (r *queryResolver) FindScenes(
method FindScenesByPathRegex (line 151) | func (r *queryResolver) FindScenesByPathRegex(ctx context.Context, filte...
method ParseSceneFilenames (line 206) | func (r *queryResolver) ParseSceneFilenames(ctx context.Context, filter ...
method FindDuplicateScenes (line 230) | func (r *queryResolver) FindDuplicateScenes(ctx context.Context, distanc...
method AllScenes (line 249) | func (r *queryResolver) AllScenes(ctx context.Context) (ret []*models.Sc...
FILE: internal/api/resolver_query_find_scene_marker.go
method FindSceneMarkers (line 9) | func (r *queryResolver) FindSceneMarkers(ctx context.Context, sceneMarke...
method AllSceneMarkers (line 44) | func (r *queryResolver) AllSceneMarkers(ctx context.Context) (ret []*mod...
FILE: internal/api/resolver_query_find_studio.go
method FindStudio (line 10) | func (r *queryResolver) FindStudio(ctx context.Context, id string) (ret ...
method FindStudios (line 27) | func (r *queryResolver) FindStudios(ctx context.Context, studioFilter *m...
method AllStudios (line 61) | func (r *queryResolver) AllStudios(ctx context.Context) (ret []*models.S...
FILE: internal/api/resolver_query_find_tag.go
method FindTag (line 10) | func (r *queryResolver) FindTag(ctx context.Context, id string) (ret *mo...
method FindTags (line 26) | func (r *queryResolver) FindTags(ctx context.Context, tagFilter *models....
method AllTags (line 61) | func (r *queryResolver) AllTags(ctx context.Context) (ret []*models.Tag,...
FILE: internal/api/resolver_query_job.go
method JobQueue (line 11) | func (r *queryResolver) JobQueue(ctx context.Context) ([]*Job, error) {
method FindJob (line 22) | func (r *queryResolver) FindJob(ctx context.Context, input FindJobInput)...
function jobToJobModel (line 35) | func jobToJobModel(j job.Job) *Job {
FILE: internal/api/resolver_query_logs.go
method Logs (line 9) | func (r *queryResolver) Logs(ctx context.Context) ([]*LogEntry, error) {
FILE: internal/api/resolver_query_metadata.go
method SystemStatus (line 9) | func (r *queryResolver) SystemStatus(ctx context.Context) (*manager.Syst...
FILE: internal/api/resolver_query_package.go
function getPackageManager (line 19) | func getPackageManager(typeArg PackageType) (*pkg.Manager, error) {
function manifestToPackage (line 37) | func manifestToPackage(p pkg.Manifest) *Package {
function remotePackageToPackage (line 59) | func remotePackageToPackage(p pkg.RemotePackage, index pkg.RemotePackage...
function sortedPackageSpecKeys (line 98) | func sortedPackageSpecKeys[V any](m map[models.PackageSpecInput]V) []mod...
method getInstalledPackagesWithUpgrades (line 129) | func (r *queryResolver) getInstalledPackagesWithUpgrades(ctx context.Con...
method InstalledPackages (line 161) | func (r *queryResolver) InstalledPackages(ctx context.Context, typeArg P...
method AvailablePackages (line 191) | func (r *queryResolver) AvailablePackages(ctx context.Context, typeArg P...
FILE: internal/api/resolver_query_plugin.go
method Plugins (line 10) | func (r *queryResolver) Plugins(ctx context.Context) ([]*plugin.Plugin, ...
method PluginTasks (line 14) | func (r *queryResolver) PluginTasks(ctx context.Context) ([]*plugin.Plug...
FILE: internal/api/resolver_query_scene.go
method SceneStreams (line 13) | func (r *queryResolver) SceneStreams(ctx context.Context, id *string) ([...
FILE: internal/api/resolver_query_scraper.go
method ScrapeURL (line 17) | func (r *queryResolver) ScrapeURL(ctx context.Context, url string, ty sc...
method ListScrapers (line 21) | func (r *queryResolver) ListScrapers(ctx context.Context, types []scrape...
method ScrapePerformerURL (line 25) | func (r *queryResolver) ScrapePerformerURL(ctx context.Context, url stri...
method ScrapeSceneQuery (line 34) | func (r *queryResolver) ScrapeSceneQuery(ctx context.Context, scraperID ...
method ScrapeSceneURL (line 52) | func (r *queryResolver) ScrapeSceneURL(ctx context.Context, url string) ...
method ScrapeGalleryURL (line 66) | func (r *queryResolver) ScrapeGalleryURL(ctx context.Context, url string...
method ScrapeImageURL (line 80) | func (r *queryResolver) ScrapeImageURL(ctx context.Context, url string) ...
method ScrapeMovieURL (line 89) | func (r *queryResolver) ScrapeMovieURL(ctx context.Context, url string) ...
method ScrapeGroupURL (line 103) | func (r *queryResolver) ScrapeGroupURL(ctx context.Context, url string) ...
method ScrapeSingleScene (line 134) | func (r *queryResolver) ScrapeSingleScene(ctx context.Context, source sc...
method ScrapeMultiScenes (line 218) | func (r *queryResolver) ScrapeMultiScenes(ctx context.Context, source sc...
method getScenesFingerprints (line 258) | func (r *queryResolver) getScenesFingerprints(ctx context.Context, ids [...
method matchScenesRelationships (line 296) | func (r *queryResolver) matchScenesRelationships(ctx context.Context, ss...
method ScrapeSingleStudio (line 317) | func (r *queryResolver) ScrapeSingleStudio(ctx context.Context, source s...
method ScrapeSingleTag (line 356) | func (r *queryResolver) ScrapeSingleTag(ctx context.Context, source scra...
method ScrapeSinglePerformer (line 395) | func (r *queryResolver) ScrapeSinglePerformer(ctx context.Context, sourc...
method ScrapeMultiPerformers (line 461) | func (r *queryResolver) ScrapeMultiPerformers(ctx context.Context, sourc...
method findPerformerNames (line 483) | func (r *queryResolver) findPerformerNames(ctx context.Context, performe...
method ScrapeSingleGallery (line 509) | func (r *queryResolver) ScrapeSingleGallery(ctx context.Context, source ...
method ScrapeSingleImage (line 552) | func (r *queryResolver) ScrapeSingleImage(ctx context.Context, source sc...
method ScrapeSingleMovie (line 585) | func (r *queryResolver) ScrapeSingleMovie(ctx context.Context, source sc...
method ScrapeSingleGroup (line 589) | func (r *queryResolver) ScrapeSingleGroup(ctx context.Context, source sc...
FILE: internal/api/resolver_subscription_job.go
function makeJobStatusUpdate (line 10) | func makeJobStatusUpdate(t JobStatusUpdateType, j job.Job) *JobStatusUpd...
method JobsSubscribe (line 17) | func (r *subscriptionResolver) JobsSubscribe(ctx context.Context) (<-cha...
method ScanCompleteSubscribe (line 41) | func (r *subscriptionResolver) ScanCompleteSubscribe(ctx context.Context...
FILE: internal/api/resolver_subscription_logging.go
function getLogLevel (line 10) | func getLogLevel(logType string) LogLevel {
function logEntriesFromLogItems (line 29) | func logEntriesFromLogItems(logItems []log.LogItem) []*LogEntry {
method LoggingSubscribe (line 43) | func (r *subscriptionResolver) LoggingSubscribe(ctx context.Context) (<-...
FILE: internal/api/routes.go
type routes (line 9) | type routes struct
method withReadTxn (line 13) | func (rs routes) withReadTxn(r *http.Request, fn txn.TxnFunc) error {
FILE: internal/api/routes_custom.go
type customRoutes (line 11) | type customRoutes struct
method Routes (line 19) | func (rs customRoutes) Routes() chi.Router {
function getCustomRoutes (line 15) | func getCustomRoutes(servedFolders utils.URLMap) chi.Router {
FILE: internal/api/routes_downloads.go
type downloadsRoutes (line 12) | type downloadsRoutes struct
method Routes (line 14) | func (rs downloadsRoutes) Routes() chi.Router {
method file (line 25) | func (rs downloadsRoutes) file(w http.ResponseWriter, r *http.Request) {
function downloadCtx (line 35) | func downloadCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_gallery.go
type GalleryFinder (line 19) | type GalleryFinder interface
type GalleryImageFinder (line 24) | type GalleryImageFinder interface
type galleryRoutes (line 30) | type galleryRoutes struct
method Routes (line 38) | func (rs galleryRoutes) Routes() chi.Router {
method Cover (line 51) | func (rs galleryRoutes) Cover(w http.ResponseWriter, r *http.Request) {
method Preview (line 84) | func (rs galleryRoutes) Preview(w http.ResponseWriter, r *http.Request) {
method GalleryCtx (line 122) | func (rs galleryRoutes) GalleryCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_group.go
type GroupFinder (line 17) | type GroupFinder interface
type groupRoutes (line 23) | type groupRoutes struct
method Routes (line 28) | func (rs groupRoutes) Routes() chi.Router {
method FrontImage (line 40) | func (rs groupRoutes) FrontImage(w http.ResponseWriter, r *http.Reques...
method BackImage (line 66) | func (rs groupRoutes) BackImage(w http.ResponseWriter, r *http.Request) {
method GroupCtx (line 92) | func (rs groupRoutes) GroupCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_image.go
type ImageFinder (line 24) | type ImageFinder interface
type imageRoutes (line 29) | type imageRoutes struct
method Routes (line 35) | func (rs imageRoutes) Routes() chi.Router {
method Thumbnail (line 49) | func (rs imageRoutes) Thumbnail(w http.ResponseWriter, r *http.Request) {
method serveThumbnail (line 54) | func (rs imageRoutes) serveThumbnail(w http.ResponseWriter, r *http.Re...
method Preview (line 118) | func (rs imageRoutes) Preview(w http.ResponseWriter, r *http.Request) {
method Image (line 126) | func (rs imageRoutes) Image(w http.ResponseWriter, r *http.Request) {
method serveImage (line 133) | func (rs imageRoutes) serveImage(w http.ResponseWriter, r *http.Reques...
method ImageCtx (line 159) | func (rs imageRoutes) ImageCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_performer.go
type PerformerFinder (line 16) | type PerformerFinder interface
type sfwConfig (line 21) | type sfwConfig interface
type performerRoutes (line 25) | type performerRoutes struct
method Routes (line 31) | func (rs performerRoutes) Routes() chi.Router {
method Image (line 42) | func (rs performerRoutes) Image(w http.ResponseWriter, r *http.Request) {
method PerformerCtx (line 68) | func (rs performerRoutes) PerformerCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_plugin.go
type pluginRoutes (line 14) | type pluginRoutes struct
method Routes (line 18) | func (rs pluginRoutes) Routes() chi.Router {
method Assets (line 32) | func (rs pluginRoutes) Assets(w http.ResponseWriter, r *http.Request) {
method Javascript (line 68) | func (rs pluginRoutes) Javascript(w http.ResponseWriter, r *http.Reque...
method CSS (line 80) | func (rs pluginRoutes) CSS(w http.ResponseWriter, r *http.Request) {
method PluginCtx (line 92) | func (rs pluginRoutes) PluginCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_scene.go
type SceneFinder (line 24) | type SceneFinder interface
type SceneMarkerFinder (line 32) | type SceneMarkerFinder interface
type SceneMarkerTagFinder (line 37) | type SceneMarkerTagFinder interface
type CaptionFinder (line 42) | type CaptionFinder interface
type sceneRoutes (line 46) | type sceneRoutes struct
method Routes (line 55) | func (rs sceneRoutes) Routes() chi.Router {
method StreamDirect (line 93) | func (rs sceneRoutes) StreamDirect(w http.ResponseWriter, r *http.Requ...
method StreamMp4 (line 102) | func (rs sceneRoutes) StreamMp4(w http.ResponseWriter, r *http.Request) {
method StreamWebM (line 106) | func (rs sceneRoutes) StreamWebM(w http.ResponseWriter, r *http.Reques...
method StreamMKV (line 110) | func (rs sceneRoutes) StreamMKV(w http.ResponseWriter, r *http.Request) {
method streamTranscode (line 135) | func (rs sceneRoutes) streamTranscode(w http.ResponseWriter, r *http.R...
method StreamHLS (line 168) | func (rs sceneRoutes) StreamHLS(w http.ResponseWriter, r *http.Request) {
method StreamDASH (line 172) | func (rs sceneRoutes) StreamDASH(w http.ResponseWriter, r *http.Reques...
method streamManifest (line 176) | func (rs sceneRoutes) streamManifest(w http.ResponseWriter, r *http.Re...
method StreamHLSSegment (line 200) | func (rs sceneRoutes) StreamHLSSegment(w http.ResponseWriter, r *http....
method StreamDASHVideoSegment (line 204) | func (rs sceneRoutes) StreamDASHVideoSegment(w http.ResponseWriter, r ...
method StreamDASHAudioSegment (line 208) | func (rs sceneRoutes) StreamDASHAudioSegment(w http.ResponseWriter, r ...
method streamSegment (line 212) | func (rs sceneRoutes) streamSegment(w http.ResponseWriter, r *http.Req...
method Screenshot (line 246) | func (rs sceneRoutes) Screenshot(w http.ResponseWriter, r *http.Reques...
method Preview (line 262) | func (rs sceneRoutes) Preview(w http.ResponseWriter, r *http.Request) {
method Webp (line 270) | func (rs sceneRoutes) Webp(w http.ResponseWriter, r *http.Request) {
method getChapterVttTitle (line 278) | func (rs sceneRoutes) getChapterVttTitle(r *http.Request, marker *mode...
method VttChapter (line 310) | func (rs sceneRoutes) VttChapter(w http.ResponseWriter, r *http.Reques...
method VttThumbs (line 352) | func (rs sceneRoutes) VttThumbs(w http.ResponseWriter, r *http.Request) {
method VttSprite (line 366) | func (rs sceneRoutes) VttSprite(w http.ResponseWriter, r *http.Request) {
method Funscript (line 379) | func (rs sceneRoutes) Funscript(w http.ResponseWriter, r *http.Request) {
method InteractiveCSV (line 386) | func (rs sceneRoutes) InteractiveCSV(w http.ResponseWriter, r *http.Re...
method InteractiveHeatmap (line 400) | func (rs sceneRoutes) InteractiveHeatmap(w http.ResponseWriter, r *htt...
method Caption (line 408) | func (rs sceneRoutes) Caption(w http.ResponseWriter, r *http.Request, ...
method CaptionLang (line 458) | func (rs sceneRoutes) CaptionLang(w http.ResponseWriter, r *http.Reque...
method SceneMarkerStream (line 469) | func (rs sceneRoutes) SceneMarkerStream(w http.ResponseWriter, r *http...
method SceneMarkerPreview (line 497) | func (rs sceneRoutes) SceneMarkerPreview(w http.ResponseWriter, r *htt...
method SceneMarkerScreenshot (line 533) | func (rs sceneRoutes) SceneMarkerScreenshot(w http.ResponseWriter, r *...
method SceneCtx (line 569) | func (rs sceneRoutes) SceneCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_studio.go
type StudioFinder (line 17) | type StudioFinder interface
type studioRoutes (line 22) | type studioRoutes struct
method Routes (line 27) | func (rs studioRoutes) Routes() chi.Router {
method Image (line 38) | func (rs studioRoutes) Image(w http.ResponseWriter, r *http.Request) {
method StudioCtx (line 65) | func (rs studioRoutes) StudioCtx(next http.Handler) http.Handler {
FILE: internal/api/routes_tag.go
type TagFinder (line 17) | type TagFinder interface
type tagRoutes (line 22) | type tagRoutes struct
method Routes (line 27) | func (rs tagRoutes) Routes() chi.Router {
method Image (line 38) | func (rs tagRoutes) Image(w http.ResponseWriter, r *http.Request) {
method TagCtx (line 65) | func (rs tagRoutes) TagCtx(next http.Handler) http.Handler {
FILE: internal/api/scraped_content.go
function marshalScrapedScenes (line 12) | func marshalScrapedScenes(content []scraper.ScrapedContent) ([]*models.S...
function marshalScrapedPerformers (line 35) | func marshalScrapedPerformers(content []scraper.ScrapedContent) ([]*mode...
function marshalScrapedGalleries (line 58) | func marshalScrapedGalleries(content []scraper.ScrapedContent) ([]*model...
function marshalScrapedImages (line 79) | func marshalScrapedImages(content []scraper.ScrapedContent) ([]*models.S...
function marshalScrapedMovies (line 102) | func marshalScrapedMovies(content []scraper.ScrapedContent) ([]*models.S...
function marshalScrapedGroups (line 125) | func marshalScrapedGroups(content []scraper.ScrapedContent) ([]*models.S...
function marshalScrapedPerformer (line 154) | func marshalScrapedPerformer(content scraper.ScrapedContent) (*models.Sc...
function marshalScrapedScene (line 164) | func marshalScrapedScene(content scraper.ScrapedContent) (*models.Scrape...
function marshalScrapedGallery (line 174) | func marshalScrapedGallery(content scraper.ScrapedContent) (*models.Scra...
function marshalScrapedImage (line 184) | func marshalScrapedImage(content scraper.ScrapedContent) (*models.Scrape...
function marshalScrapedMovie (line 194) | func marshalScrapedMovie(content scraper.ScrapedContent) (*models.Scrape...
function marshalScrapedGroup (line 204) | func marshalScrapedGroup(content scraper.ScrapedContent) (*models.Scrape...
FILE: internal/api/server.go
constant loginEndpoint (line 45) | loginEndpoint = "/login"
constant loginLocaleEndpoint (line 46) | loginLocaleEndpoint = loginEndpoint + "/locale"
constant logoutEndpoint (line 47) | logoutEndpoint = "/logout"
constant gqlEndpoint (line 48) | gqlEndpoint = "/graphql"
constant playgroundEndpoint (line 49) | playgroundEndpoint = "/playground"
type Server (line 52) | type Server struct
method Start (line 330) | func (s *Server) Start() error {
method Shutdown (line 342) | func (s *Server) Shutdown() {
method getPerformerRoutes (line 349) | func (s *Server) getPerformerRoutes() chi.Router {
method getSceneRoutes (line 358) | func (s *Server) getSceneRoutes() chi.Router {
method getGalleryRoutes (line 370) | func (s *Server) getGalleryRoutes() chi.Router {
method getImageRoutes (line 380) | func (s *Server) getImageRoutes() chi.Router {
method getStudioRoutes (line 389) | func (s *Server) getStudioRoutes() chi.Router {
method getGroupRoutes (line 397) | func (s *Server) getGroupRoutes() chi.Router {
method getTagRoutes (line 405) | func (s *Server) getTagRoutes() chi.Router {
method getDownloadsRoutes (line 413) | func (s *Server) getDownloadsRoutes() chi.Router {
method getPluginRoutes (line 417) | func (s *Server) getPluginRoutes() chi.Router {
type osFS (line 61) | type osFS
method ReadDir (line 63) | func (dir osFS) ReadDir(name string) ([]os.DirEntry, error) {
method Open (line 77) | func (dir osFS) Open(name string) (fs.File, error) {
function Initialize (line 83) | func Initialize() (*Server, error) {
function handleFavicon (line 302) | func handleFavicon(staticUI *statigz.Server) func(w http.ResponseWriter,...
function copyFile (line 423) | func copyFile(w io.Writer, path string) error {
function serveFiles (line 435) | func serveFiles(w http.ResponseWriter, r *http.Request, paths []string) {
function cssHandler (line 449) | func cssHandler(c *config.Config) func(w http.ResponseWriter, r *http.Re...
function javascriptHandler (line 467) | func javascriptHandler(c *config.Config) func(w http.ResponseWriter, r *...
function customLocalesHandler (line 485) | func customLocalesHandler(c *config.Config) func(w http.ResponseWriter, ...
function makeTLSConfig (line 510) | func makeTLSConfig(c *config.Config) (*tls.Config, error) {
function isURL (line 550) | func isURL(s string) bool {
function setPageSecurityHeaders (line 554) | func setPageSecurityHeaders(w http.ResponseWriter, r *http.Request, plug...
function SecurityHeadersMiddleware (line 626) | func SecurityHeadersMiddleware(next http.Handler) http.Handler {
type contextKey (line 635) | type contextKey struct
function BaseURLMiddleware (line 643) | func BaseURLMiddleware(next http.Handler) http.Handler {
function getProxyPrefix (line 667) | func getProxyPrefix(r *http.Request) string {
FILE: internal/api/session.go
constant returnURLParam (line 21) | returnURLParam = "returnURL"
constant defaultLocale (line 23) | defaultLocale = "en-GB"
function getLoginPage (line 26) | func getLoginPage() []byte {
type loginTemplateData (line 34) | type loginTemplateData struct
function serveLoginPage (line 39) | func serveLoginPage(w http.ResponseWriter, r *http.Request, returnURL st...
function handleLoginLocale (line 65) | func handleLoginLocale(cfg *config.Config) http.HandlerFunc {
function getLoginLocale (line 98) | func getLoginLocale(lang string) ([]byte, error) {
function handleLogin (line 106) | func handleLogin() http.HandlerFunc {
function handleLoginPost (line 124) | func handleLoginPost() http.HandlerFunc {
function handleLogout (line 149) | func handleLogout() http.HandlerFunc {
FILE: internal/api/stash_box.go
method newStashBoxClient (line 13) | func (r *Resolver) newStashBoxClient(box models.StashBox) *stashbox.Clie...
function resolveStashBoxFn (line 17) | func resolveStashBoxFn(indexField, endpointField string) func(index *int...
FILE: internal/api/timestamp.go
function MarshalTimestamp (line 17) | func MarshalTimestamp(t time.Time) graphql.Marshaler {
function UnmarshalTimestamp (line 30) | func UnmarshalTimestamp(v interface{}) (time.Time, error) {
FILE: internal/api/timestamp_test.go
function TestTimestampSymmetry (line 10) | func TestTimestampSymmetry(t *testing.T) {
function TestTimestamp (line 29) | func TestTimestamp(t *testing.T) {
constant epsilon (line 63) | epsilon = 10 * time.Second
function TestTimestampRelative (line 65) | func TestTimestampRelative(t *testing.T) {
FILE: internal/api/types.go
function stashIDsSliceToPtrSlice (line 8) | func stashIDsSliceToPtrSlice(v []models.StashID) []*models.StashID {
FILE: internal/api/urlbuilders/gallery.go
type GalleryURLBuilder (line 9) | type GalleryURLBuilder struct
method GetPreviewURL (line 23) | func (b GalleryURLBuilder) GetPreviewURL() string {
method GetCoverURL (line 27) | func (b GalleryURLBuilder) GetCoverURL() string {
function NewGalleryURLBuilder (line 15) | func NewGalleryURLBuilder(baseURL string, gallery *models.Gallery) Galle...
FILE: internal/api/urlbuilders/group.go
type GroupURLBuilder (line 9) | type GroupURLBuilder struct
method GetGroupFrontImageURL (line 23) | func (b GroupURLBuilder) GetGroupFrontImageURL(hasImage bool) string {
method GetGroupBackImageURL (line 31) | func (b GroupURLBuilder) GetGroupBackImageURL() string {
function NewGroupURLBuilder (line 15) | func NewGroupURLBuilder(baseURL string, group *models.Group) GroupURLBui...
FILE: internal/api/urlbuilders/image.go
type ImageURLBuilder (line 11) | type ImageURLBuilder struct
method GetImageURL (line 27) | func (b ImageURLBuilder) GetImageURL() string {
method GetThumbnailURL (line 31) | func (b ImageURLBuilder) GetThumbnailURL() string {
method GetPreviewURL (line 35) | func (b ImageURLBuilder) GetPreviewURL() string {
function NewImageURLBuilder (line 18) | func NewImageURLBuilder(baseURL string, image *models.Image) ImageURLBui...
FILE: internal/api/urlbuilders/performer.go
type PerformerURLBuilder (line 9) | type PerformerURLBuilder struct
method GetPerformerImageURL (line 23) | func (b PerformerURLBuilder) GetPerformerImageURL(hasImage bool) string {
function NewPerformerURLBuilder (line 15) | func NewPerformerURLBuilder(baseURL string, performer *models.Performer)...
FILE: internal/api/urlbuilders/scene.go
type SceneURLBuilder (line 11) | type SceneURLBuilder struct
method GetStreamURL (line 25) | func (b SceneURLBuilder) GetStreamURL(apiKey string) *url.URL {
method GetStreamPreviewURL (line 40) | func (b SceneURLBuilder) GetStreamPreviewURL() string {
method GetStreamPreviewImageURL (line 44) | func (b SceneURLBuilder) GetStreamPreviewImageURL() string {
method GetSpriteVTTURL (line 48) | func (b SceneURLBuilder) GetSpriteVTTURL(checksum string) string {
method GetSpriteURL (line 52) | func (b SceneURLBuilder) GetSpriteURL(checksum string) string {
method GetScreenshotURL (line 56) | func (b SceneURLBuilder) GetScreenshotURL() string {
method GetFunscriptURL (line 60) | func (b SceneURLBuilder) GetFunscriptURL() string {
method GetCaptionURL (line 64) | func (b SceneURLBuilder) GetCaptionURL() string {
method GetInteractiveHeatmapURL (line 68) | func (b SceneURLBuilder) GetInteractiveHeatmapURL() string {
function NewSceneURLBuilder (line 17) | func NewSceneURLBuilder(baseURL string, scene *models.Scene) SceneURLBui...
FILE: internal/api/urlbuilders/scene_markers.go
type SceneMarkerURLBuilder (line 9) | type SceneMarkerURLBuilder struct
method GetStreamURL (line 23) | func (b SceneMarkerURLBuilder) GetStreamURL() string {
method GetPreviewURL (line 27) | func (b SceneMarkerURLBuilder) GetPreviewURL() string {
method GetScreenshotURL (line 31) | func (b SceneMarkerURLBuilder) GetScreenshotURL() string {
function NewSceneMarkerURLBuilder (line 15) | func NewSceneMarkerURLBuilder(baseURL string, sceneMarker *models.SceneM...
FILE: internal/api/urlbuilders/studio.go
type StudioURLBuilder (line 9) | type StudioURLBuilder struct
method GetStudioImageURL (line 23) | func (b StudioURLBuilder) GetStudioImageURL(hasImage bool) string {
function NewStudioURLBuilder (line 15) | func NewStudioURLBuilder(baseURL string, studio *models.Studio) StudioUR...
FILE: internal/api/urlbuilders/tag.go
type TagURLBuilder (line 8) | type TagURLBuilder struct
method GetTagImageURL (line 22) | func (b TagURLBuilder) GetTagImageURL(hasImage bool) string {
function NewTagURLBuilder (line 14) | func NewTagURLBuilder(baseURL string, tag *models.Tag) TagURLBuilder {
FILE: internal/autotag/gallery.go
type GalleryFinderUpdater (line 12) | type GalleryFinderUpdater interface
type GalleryPerformerUpdater (line 17) | type GalleryPerformerUpdater interface
type GalleryTagUpdater (line 22) | type GalleryTagUpdater interface
function getGalleryFileTagger (line 27) | func getGalleryFileTagger(s *models.Gallery, cache *match.Cache) tagger {
function GalleryPerformers (line 47) | func GalleryPerformers(ctx context.Context, s *models.Gallery, rw Galler...
function GalleryStudios (line 71) | func GalleryStudios(ctx context.Context, s *models.Gallery, rw GalleryFi...
function GalleryTags (line 85) | func GalleryTags(ctx context.Context, s *models.Gallery, rw GalleryTagUp...
FILE: internal/autotag/gallery_test.go
constant galleryExt (line 13) | galleryExt = "zip"
function galleryPartialsEqual (line 19) | func galleryPartialsEqual(got, expected models.GalleryPartial) bool {
function TestGalleryPerformers (line 30) | func TestGalleryPerformers(t *testing.T) {
function TestGalleryStudios (line 86) | func TestGalleryStudios(t *testing.T) {
function TestGalleryTags (line 158) | func TestGalleryTags(t *testing.T) {
FILE: internal/autotag/image.go
type ImageFinderUpdater (line 12) | type ImageFinderUpdater interface
type ImagePerformerUpdater (line 17) | type ImagePerformerUpdater interface
type ImageTagUpdater (line 22) | type ImageTagUpdater interface
function getImageFileTagger (line 27) | func getImageFileTagger(s *models.Image, cache *match.Cache) tagger {
function ImagePerformers (line 38) | func ImagePerformers(ctx context.Context, s *models.Image, rw ImagePerfo...
function ImageStudios (line 62) | func ImageStudios(ctx context.Context, s *models.Image, rw ImageFinderUp...
function ImageTags (line 76) | func ImageTags(ctx context.Context, s *models.Image, rw ImageTagUpdater,...
FILE: internal/autotag/image_test.go
constant imageExt (line 12) | imageExt = "jpg"
function imagePartialsEqual (line 16) | func imagePartialsEqual(got, expected models.ImagePartial) bool {
function TestImagePerformers (line 27) | func TestImagePerformers(t *testing.T) {
function TestImageStudios (line 83) | func TestImageStudios(t *testing.T) {
function TestImageTags (line 155) | func TestImageTags(t *testing.T) {
FILE: internal/autotag/integration_test.go
constant testName (line 25) | testName = "Foo's Bar"
constant existingStudioName (line 26) | existingStudioName = "ExistingStudio"
constant existingStudioSceneName (line 28) | existingStudioSceneName = testName + ".dontChangeStudio.mp4"
constant existingStudioImageName (line 29) | existingStudioImageName = testName + ".dontChangeStudio.png"
constant existingStudioGalleryName (line 30) | existingStudioGalleryName = testName + ".dontChangeStudio.zip"
constant expectedMatchTitle (line 34) | expectedMatchTitle = "expected match"
function testTeardown (line 39) | func testTeardown(databaseFile string) {
function runTests (line 52) | func runTests(m *testing.M) int {
function TestMain (line 80) | func TestMain(m *testing.M) {
function createPerformer (line 88) | func createPerformer(ctx context.Context, pqb models.PerformerWriter) er...
function createStudio (line 102) | func createStudio(ctx context.Context, qb models.StudioWriter, name stri...
function createTag (line 115) | func createTag(ctx context.Context, qb models.TagWriter) error {
function createScenes (line 129) | func createScenes(ctx context.Context, sqb models.SceneReaderWriter, fol...
function makeScene (line 190) | func makeScene(expectedResult bool) *models.Scene {
function createSceneFile (line 201) | func createSceneFile(ctx context.Context, name string, folderStore model...
function getOrCreateFolder (line 226) | func getOrCreateFolder(ctx context.Context, folderStore models.FolderFin...
function createScene (line 262) | func createScene(ctx context.Context, sqb models.SceneWriter, s *models....
function createImages (line 272) | func createImages(ctx context.Context, w models.ImageReaderWriter, folde...
function createImageFile (line 331) | func createImageFile(ctx context.Context, name string, folderStore model...
function makeImage (line 356) | func makeImage(expectedResult bool) *models.Image {
function createImage (line 367) | func createImage(ctx context.Context, w models.ImageWriter, o *models.Im...
function createGalleries (line 380) | func createGalleries(ctx context.Context, w models.GalleryReaderWriter, ...
function createGalleryFile (line 439) | func createGalleryFile(ctx context.Context, name string, folderStore mod...
function makeGallery (line 462) | func makeGallery(expectedResult bool) *models.Gallery {
function createGallery (line 473) | func createGallery(ctx context.Context, w models.GalleryWriter, o *model...
function withTxn (line 485) | func withTxn(f func(ctx context.Context) error) error {
function withDB (line 489) | func withDB(f func(ctx context.Context) error) error {
function populateDB (line 493) | func populateDB() error {
function TestParsePerformerScenes (line 541) | func TestParsePerformerScenes(t *testing.T) {
function TestParseStudioScenes (line 595) | func TestParseStudioScenes(t *testing.T) {
function TestParseTagScenes (line 655) | func TestParseTagScenes(t *testing.T) {
function TestParsePerformerImages (line 711) | func TestParsePerformerImages(t *testing.T) {
function TestParseStudioImages (line 766) | func TestParseStudioImages(t *testing.T) {
function TestParseTagImages (line 826) | func TestParseTagImages(t *testing.T) {
function TestParsePerformerGalleries (line 883) | func TestParsePerformerGalleries(t *testing.T) {
function TestParseStudioGalleries (line 938) | func TestParseStudioGalleries(t *testing.T) {
function TestParseTagGalleries (line 998) | func TestParseTagGalleries(t *testing.T) {
FILE: internal/autotag/performer.go
type SceneQueryPerformerUpdater (line 15) | type SceneQueryPerformerUpdater interface
type ImageQueryPerformerUpdater (line 21) | type ImageQueryPerformerUpdater interface
type GalleryQueryPerformerUpdater (line 27) | type GalleryQueryPerformerUpdater interface
function getPerformerTaggers (line 33) | func getPerformerTaggers(p *models.Performer, cache *match.Cache) []tagg...
method PerformerScenes (line 56) | func (tagger *Tagger) PerformerScenes(ctx context.Context, p *models.Per...
method PerformerImages (line 85) | func (tagger *Tagger) PerformerImages(ctx context.Context, p *models.Per...
method PerformerGalleries (line 114) | func (tagger *Tagger) PerformerGalleries(ctx context.Context, p *models....
FILE: internal/autotag/performer_test.go
function TestPerformerScenes (line 15) | func TestPerformerScenes(t *testing.T) {
function testPerformerScenes (line 47) | func testPerformerScenes(t *testing.T, performerName, expectedRegex stri...
function TestPerformerImages (line 118) | func TestPerformerImages(t *testing.T) {
function testPerformerImages (line 142) | func testPerformerImages(t *testing.T, performerName, expectedRegex stri...
function TestPerformerGalleries (line 213) | func TestPerformerGalleries(t *testing.T) {
function testPerformerGalleries (line 237) | func testPerformerGalleries(t *testing.T, performerName, expectedRegex s...
FILE: internal/autotag/scene.go
type SceneFinderUpdater (line 12) | type SceneFinderUpdater interface
type ScenePerformerUpdater (line 17) | type ScenePerformerUpdater interface
type SceneTagUpdater (line 22) | type SceneTagUpdater interface
function getSceneFileTagger (line 27) | func getSceneFileTagger(s *models.Scene, cache *match.Cache) tagger {
function ScenePerformers (line 38) | func ScenePerformers(ctx context.Context, s *models.Scene, rw ScenePerfo...
function SceneStudios (line 62) | func SceneStudios(ctx context.Context, s *models.Scene, rw SceneFinderUp...
function SceneTags (line 76) | func SceneTags(ctx context.Context, s *models.Scene, rw SceneTagUpdater,...
FILE: internal/autotag/scene_test.go
constant sceneExt (line 15) | sceneExt = "mp4"
function scenePartialsEqual (line 34) | func scenePartialsEqual(got, expected models.ScenePartial) bool {
function generateNamePatterns (line 45) | func generateNamePatterns(name, separator, ext string) []string {
function generateSplitNamePatterns (line 58) | func generateSplitNamePatterns(name, separator, ext string) []string {
function generateFalseNamePatterns (line 69) | func generateFalseNamePatterns(name string, separator, ext string) []str...
function generateTestPaths (line 81) | func generateTestPaths(testName, ext string) (scenePatterns []string, fa...
type pathTestTable (line 119) | type pathTestTable struct
function generateTestTable (line 124) | func generateTestTable(testName, ext string) []pathTestTable {
function TestScenePerformers (line 160) | func TestScenePerformers(t *testing.T) {
function TestSceneStudios (line 217) | func TestSceneStudios(t *testing.T) {
function TestSceneTags (line 291) | func TestSceneTags(t *testing.T) {
FILE: internal/autotag/studio.go
function addSceneStudio (line 14) | func addSceneStudio(ctx context.Context, sceneWriter models.SceneUpdater...
function addImageStudio (line 30) | func addImageStudio(ctx context.Context, imageWriter models.ImageUpdater...
function addGalleryStudio (line 46) | func addGalleryStudio(ctx context.Context, galleryWriter GalleryFinderUp...
function getStudioTagger (line 62) | func getStudioTagger(p *models.Studio, aliases []string, cache *match.Ca...
method StudioScenes (line 82) | func (tagger *Tagger) StudioScenes(ctx context.Context, p *models.Studio...
method StudioImages (line 112) | func (tagger *Tagger) StudioImages(ctx context.Context, p *models.Studio...
method StudioGalleries (line 142) | func (tagger *Tagger) StudioGalleries(ctx context.Context, p *models.Stu...
FILE: internal/autotag/studio_test.go
type testStudioCase (line 15) | type testStudioCase struct
function TestStudioScenes (line 66) | func TestStudioScenes(t *testing.T) {
function testStudioScenes (line 80) | func testStudioScenes(t *testing.T, tc testStudioCase) {
function TestStudioImages (line 177) | func TestStudioImages(t *testing.T) {
function testStudioImages (line 185) | func testStudioImages(t *testing.T, tc testStudioCase) {
function TestStudioGalleries (line 280) | func TestStudioGalleries(t *testing.T) {
function testStudioGalleries (line 288) | func testStudioGalleries(t *testing.T, tc testStudioCase) {
FILE: internal/autotag/tag.go
type SceneQueryTagUpdater (line 15) | type SceneQueryTagUpdater interface
type ImageQueryTagUpdater (line 21) | type ImageQueryTagUpdater interface
type GalleryQueryTagUpdater (line 27) | type GalleryQueryTagUpdater interface
function getTagTaggers (line 33) | func getTagTaggers(p *models.Tag, aliases []string, cache *match.Cache) ...
method TagScenes (line 54) | func (tagger *Tagger) TagScenes(ctx context.Context, p *models.Tag, path...
method TagImages (line 83) | func (tagger *Tagger) TagImages(ctx context.Context, p *models.Tag, path...
method TagGalleries (line 112) | func (tagger *Tagger) TagGalleries(ctx context.Context, p *models.Tag, p...
FILE: internal/autotag/tag_test.go
type testTagCase (line 15) | type testTagCase struct
function TestTagScenes (line 66) | func TestTagScenes(t *testing.T) {
function testTagScenes (line 80) | func testTagScenes(t *testing.T, tc testTagCase) {
function TestTagImages (line 180) | func TestTagImages(t *testing.T) {
function testTagImages (line 188) | func testTagImages(t *testing.T, tc testTagCase) {
function TestTagGalleries (line 287) | func TestTagGalleries(t *testing.T) {
function testTagGalleries (line 295) | func testTagGalleries(t *testing.T, tc testTagCase) {
FILE: internal/autotag/tagger.go
type Tagger (line 26) | type Tagger struct
type tagger (line 31) | type tagger struct
method addError (line 46) | func (t *tagger) addError(otherType, otherName string, err error) error {
method addLog (line 50) | func (t *tagger) addLog(otherType, otherName string) {
method tagPerformers (line 54) | func (t *tagger) tagPerformers(ctx context.Context, performerReader mo...
method tagStudios (line 75) | func (t *tagger) tagStudios(ctx context.Context, studioReader models.S...
method tagTags (line 96) | func (t *tagger) tagTags(ctx context.Context, tagReader models.TagAuto...
method tagScenes (line 117) | func (t *tagger) tagScenes(ctx context.Context, paths []string, sceneR...
method tagImages (line 133) | func (t *tagger) tagImages(ctx context.Context, paths []string, imageR...
method tagGalleries (line 149) | func (t *tagger) tagGalleries(ctx context.Context, paths []string, gal...
type addLinkFunc (line 41) | type addLinkFunc
type addImageLinkFunc (line 42) | type addImageLinkFunc
type addGalleryLinkFunc (line 43) | type addGalleryLinkFunc
type addSceneLinkFunc (line 44) | type addSceneLinkFunc
FILE: internal/build/version.go
function Version (line 13) | func Version() (string, string, string) {
function VersionString (line 17) | func VersionString() string {
function IsOfficial (line 42) | func IsOfficial() bool {
function IsDevelop (line 46) | func IsDevelop() bool {
FILE: internal/desktop/desktop.go
function InitIsDesktop (line 27) | func InitIsDesktop() {
type FaviconProvider (line 31) | type FaviconProvider interface
function Start (line 38) | func Start(exit chan int, faviconProvider FaviconProvider) {
function openURLInBrowser (line 52) | func openURLInBrowser(path string) {
function SendNotification (line 63) | func SendNotification(title string, text string) {
function IsDesktop (line 72) | func IsDesktop() bool {
function isDesktopCheck (line 78) | func isDesktopCheck() bool {
function IsServerDockerized (line 106) | func IsServerDockerized() bool {
function writeStashIcon (line 111) | func writeStashIcon(faviconProvider FaviconProvider) {
function IsAllowedAutoUpdate (line 124) | func IsAllowedAutoUpdate() bool {
function getIconPath (line 155) | func getIconPath() string {
function RevealInFileManager (line 159) | func RevealInFileManager(path string) error {
function getServerURL (line 172) | func getServerURL(path string) string {
FILE: internal/desktop/desktop_platform_darwin.go
function isService (line 15) | func isService() bool {
function isServerDockerized (line 20) | func isServerDockerized() bool {
function sendNotification (line 24) | func sendNotification(notificationTitle string, notificationText string) {
function revealInFileManager (line 37) | func revealInFileManager(path string, _ os.FileInfo) error {
function isDoubleClickLaunched (line 44) | func isDoubleClickLaunched() bool {
function hideConsole (line 48) | func hideConsole() {
FILE: internal/desktop/desktop_platform_nixes.go
function isService (line 17) | func isService() bool {
function isServerDockerized (line 21) | func isServerDockerized() bool {
function sendNotification (line 31) | func sendNotification(notificationTitle string, notificationText string) {
function revealInFileManager (line 38) | func revealInFileManager(path string, info os.FileInfo) error {
function isDoubleClickLaunched (line 49) | func isDoubleClickLaunched() bool {
function hideConsole (line 53) | func hideConsole() {
FILE: internal/desktop/desktop_platform_windows.go
function isService (line 22) | func isService() bool {
function isDoubleClickLaunched (line 37) | func isDoubleClickLaunched() bool {
function hideConsole (line 50) | func hideConsole() {
function getConsoleWindow (line 59) | func getConsoleWindow() uintptr {
function isServerDockerized (line 65) | func isServerDockerized() bool {
function sendNotification (line 69) | func sendNotification(notificationTitle string, notificationText string) {
function revealInFileManager (line 87) | func revealInFileManager(path string, _ os.FileInfo) error {
FILE: internal/desktop/dialog_nonwindows.go
function FatalError (line 6) | func FatalError(err error) int {
FILE: internal/desktop/dialog_windows.go
function FatalError (line 12) | func FatalError(err error) int {
function messageBox (line 22) | func messageBox(hwnd uintptr, caption, title string, flags uint) int {
FILE: internal/desktop/systray_nixes.go
function startSystray (line 5) | func startSystray(exit chan int, favicon FaviconProvider) {
FILE: internal/desktop/systray_nonlinux.go
function startSystray (line 19) | func startSystray(exit chan int, faviconProvider FaviconProvider) {
function systrayInitialize (line 59) | func systrayInitialize(exit chan<- int, faviconProvider FaviconProvider) {
FILE: internal/dlna/activity.go
constant DefaultSessionTimeout (line 18) | DefaultSessionTimeout = 5 * time.Minute
constant monitorInterval (line 21) | monitorInterval = 10 * time.Second
type ActivityConfig (line 25) | type ActivityConfig interface
type SceneActivityWriter (line 36) | type SceneActivityWriter interface
type streamSession (line 42) | type streamSession struct
method percentWatched (line 62) | func (s *streamSession) percentWatched() float64 {
method estimatedResumeTime (line 89) | func (s *streamSession) estimatedResumeTime() float64 {
function sessionKey (line 52) | func sessionKey(clientIP string, sceneID int) string {
type ActivityTracker (line 115) | type ActivityTracker struct
method Stop (line 155) | func (t *ActivityTracker) Stop() {
method RecordRequest (line 176) | func (t *ActivityTracker) RecordRequest(sceneID int, clientIP string, ...
method monitorSessions (line 203) | func (t *ActivityTracker) monitorSessions() {
method processExpiredSessions (line 220) | func (t *ActivityTracker) processExpiredSessions() {
method processCompletedSession (line 262) | func (t *ActivityTracker) processCompletedSession(session *streamSessi...
method isEnabled (line 320) | func (t *ActivityTracker) isEnabled() bool {
method getMinimumPlayPercent (line 328) | func (t *ActivityTracker) getMinimumPlayPercent() int {
function NewActivityTracker (line 130) | func NewActivityTracker(
FILE: internal/dlna/activity_test.go
type mockSceneWriter (line 13) | type mockSceneWriter struct
method SaveActivity (line 30) | func (m *mockSceneWriter) SaveActivity(_ context.Context, sceneID int,...
method AddViews (line 41) | func (m *mockSceneWriter) AddViews(_ context.Context, sceneID int, dat...
type saveActivityCall (line 19) | type saveActivityCall struct
type addViewsCall (line 25) | type addViewsCall struct
type mockConfig (line 52) | type mockConfig struct
method GetDLNAActivityTrackingEnabled (line 57) | func (c *mockConfig) GetDLNAActivityTrackingEnabled() bool {
method GetMinimumPlayPercent (line 61) | func (c *mockConfig) GetMinimumPlayPercent() int {
function TestStreamSession_PercentWatched (line 65) | func TestStreamSession_PercentWatched(t *testing.T) {
function TestStreamSession_EstimatedResumeTime (line 132) | func TestStreamSession_EstimatedResumeTime(t *testing.T) {
function TestSessionKey (line 206) | func TestSessionKey(t *testing.T) {
function TestActivityTracker_RecordRequest (line 211) | func TestActivityTracker_RecordRequest(t *testing.T) {
function TestActivityTracker_DisabledTracking (line 249) | func TestActivityTracker_DisabledTracking(t *testing.T) {
function TestActivityTracker_SessionExpiration (line 271) | func TestActivityTracker_SessionExpiration(t *testing.T) {
function TestActivityTracker_SessionExpiration_StoppedEarly (line 310) | func TestActivityTracker_SessionExpiration_StoppedEarly(t *testing.T) {
function TestActivityTracker_MinimumPlayPercentThreshold (line 343) | func TestActivityTracker_MinimumPlayPercentThreshold(t *testing.T) {
function TestActivityTracker_MultipleSessions (line 373) | func TestActivityTracker_MultipleSessions(t *testing.T) {
function TestActivityTracker_ShortSessionIgnored (line 397) | func TestActivityTracker_ShortSessionIgnored(t *testing.T) {
FILE: internal/dlna/cd-service-desc.go
constant contentDirectoryServiceDescription (line 29) | contentDirectoryServiceDescription = `<?xml version="1.0"?>
FILE: internal/dlna/cds.go
type browse (line 48) | type browse struct
type contentDirectoryService (line 56) | type contentDirectoryService struct
method updateIDString (line 75) | func (me *contentDirectoryService) updateIDString() string {
method objectFromID (line 149) | func (me *contentDirectoryService) objectFromID(id string) (o object, ...
method Handle (line 175) | func (me *contentDirectoryService) Handle(action string, argsXML []byt...
method handleBrowseDirectChildren (line 229) | func (me *contentDirectoryService) handleBrowseDirectChildren(obj obje...
method handleBrowseMetadata (line 340) | func (me *contentDirectoryService) handleBrowseMetadata(obj object, ho...
method getVideos (line 451) | func (me *contentDirectoryService) getVideos(sceneFilter *models.Scene...
method getPageVideos (line 497) | func (me *contentDirectoryService) getPageVideos(sceneFilter *models.S...
method getAllScenes (line 537) | func (me *contentDirectoryService) getAllScenes(host string) []interfa...
method getStudios (line 541) | func (me *contentDirectoryService) getStudios() []interface{} {
method getStudioScenes (line 563) | func (me *contentDirectoryService) getStudioScenes(paths []string, hos...
method getTags (line 581) | func (me *contentDirectoryService) getTags() []interface{} {
method getTagScenes (line 603) | func (me *contentDirectoryService) getTagScenes(paths []string, host s...
method getPerformers (line 621) | func (me *contentDirectoryService) getPerformers() []interface{} {
method getPerformerScenes (line 643) | func (me *contentDirectoryService) getPerformerScenes(paths []string, ...
method getGroups (line 661) | func (me *contentDirectoryService) getGroups() []interface{} {
method getGroupScenes (line 683) | func (me *contentDirectoryService) getGroupScenes(paths []string, host...
method getRating (line 701) | func (me *contentDirectoryService) getRating() []interface{} {
method getRatingScenes (line 712) | func (me *contentDirectoryService) getRatingScenes(paths []string, hos...
function formatDurationSexagesimal (line 61) | func formatDurationSexagesimal(d time.Duration) string {
function sceneToContainer (line 79) | func sceneToContainer(scene *models.Scene, parent string, host string) i...
function childPath (line 167) | func childPath(paths []string) []string {
function makeBrowseResult (line 393) | func makeBrowseResult(objs []interface{}, updateID string) (map[string]s...
function makeStorageFolder (line 407) | func makeStorageFolder(id, title, parentID string) upnpav.Container {
function getRootObject (line 421) | func getRootObject() []interface{} {
function getRootObjects (line 427) | func getRootObjects() []interface{} {
function getSortDirection (line 442) | func getSortDirection(sceneFilter *models.SceneFilterType, sort string) ...
function getPageFromID (line 523) | func getPageFromID(paths []string) *int {
type object (line 736) | type object struct
method FilePath (line 742) | func (o *object) FilePath() string {
method ID (line 747) | func (o object) ID() string {
method IsRoot (line 754) | func (o *object) IsRoot() bool {
method ParentID (line 760) | func (o object) ParentID() string {
FILE: internal/dlna/cds_test.go
function TestEscapeObjectID (line 37) | func TestEscapeObjectID(t *testing.T) {
function TestRootObjectID (line 47) | func TestRootObjectID(t *testing.T) {
function TestRootParentObjectID (line 53) | func TestRootParentObjectID(t *testing.T) {
function testHandleBrowse (line 59) | func testHandleBrowse(argsXML string) (map[string]string, error) {
function TestBrowseMetadataRoot (line 68) | func TestBrowseMetadataRoot(t *testing.T) {
function TestBrowseMetadataTags (line 75) | func TestBrowseMetadataTags(t *testing.T) {
FILE: internal/dlna/cm-service-desc.go
constant connectionManagerServiceDescription (line 24) | connectionManagerServiceDescription = `<?xml version="1.0" encoding="UTF...
FILE: internal/dlna/cms.go
constant defaultProtocolInfo (line 30) | defaultProtocolInfo = "http-get:*:video/mpeg:*,http-get:*:video/mp4:*,ht...
type connectionManagerService (line 32) | type connectionManagerService struct
method Handle (line 37) | func (cms *connectionManagerService) Handle(action string, argsXML []b...
FILE: internal/dlna/dms.go
type SceneFinder (line 54) | type SceneFinder interface
type StudioFinder (line 59) | type StudioFinder interface
type TagFinder (line 63) | type TagFinder interface
type PerformerFinder (line 67) | type PerformerFinder interface
type GroupFinder (line 71) | type GroupFinder interface
constant serverField (line 76) | serverField = "Linux/3.4 DLNADOC/1.50 UPnP/1.0 DMS/1.0"
constant rootDeviceType (line 77) | rootDeviceType = "urn:schemas-upnp-org:device:MediaServer:1"
constant rootDeviceModelName (line 78) | rootDeviceModelName = "dms 1.0xb"
constant resPath (line 79) | resPath = "/res"
constant iconPath (line 80) | iconPath = "/icon"
constant rootDescPath (line 81) | rootDescPath = "/rootDesc.xml"
constant contentDirectoryEventSubURL (line 82) | contentDirectoryEventSubURL = "/evt/ContentDirectory"
constant serviceControlURL (line 83) | serviceControlURL = "/ctl"
constant deviceIconPath (line 84) | deviceIconPath = "/deviceIcon"
function makeDeviceUuid (line 87) | func makeDeviceUuid(unique string) string {
type service (line 97) | type service struct
function init (line 131) | func init() {
function devices (line 138) | func devices() []string {
function serviceTypes (line 144) | func serviceTypes() (ret []string) {
constant ssdpInterfaceFlags (line 181) | ssdpInterfaceFlags = net.FlagUp | net.FlagMulticast
type Icon (line 252) | type Icon struct
type Server (line 258) | type Server struct
method httpPort (line 150) | func (me *Server) httpPort() int {
method serveHTTP (line 154) | func (me *Server) serveHTTP() error {
method doSSDP (line 183) | func (me *Server) doSSDP() {
method ssdpInterface (line 202) | func (me *Server) ssdpInterface(if_ net.Interface) {
method soapActionResponse (line 380) | func (me *Server) soapActionResponse(sa upnp.SoapAction, actionRequest...
method serviceControlHandler (line 397) | func (me *Server) serviceControlHandler(w http.ResponseWriter, r *http...
method serveIcon (line 441) | func (me *Server) serveIcon(w http.ResponseWriter, r *http.Request) {
method contentDirectoryInitialEvent (line 468) | func (me *Server) contentDirectoryInitialEvent(ctx context.Context, ur...
method contentDirectoryEventSubHandler (line 524) | func (me *Server) contentDirectoryEventSubHandler(w http.ResponseWrite...
method subscribe (line 573) | func (me *Server) subscribe(urls []*url.URL, timeout int) (sid string,...
method initMux (line 581) | func (me *Server) initMux(mux *http.ServeMux) {
method initServices (line 658) | func (me *Server) initServices() {
method Serve (line 672) | func (me *Server) Serve() (err error) {
method Close (line 741) | func (me *Server) Close() (err error) {
method location (line 758) | func (me *Server) location(ip net.IP) string {
type UPnPService (line 288) | type UPnPService interface
type Cache (line 294) | type Cache interface
function init (line 299) | func init() {
function xmlMarshalOrPanic (line 303) | func xmlMarshalOrPanic(value interface{}) []byte {
type mitmRespWriter (line 312) | type mitmRespWriter struct
method WriteHeader (line 318) | func (me *mitmRespWriter) WriteHeader(code int) {
method doLogHeader (line 323) | func (me *mitmRespWriter) doLogHeader(code int) {
method Write (line 334) | func (me *mitmRespWriter) Write(b []byte) (int, error) {
method CloseNotify (line 343) | func (me *mitmRespWriter) CloseNotify() <-chan bool {
function init (line 348) | func init() {
function handleSCPDs (line 356) | func handleSCPDs(mux *http.ServeMux) {
function marshalSOAPResponse (line 368) | func marshalSOAPResponse(sa upnp.SoapAction, args map[string]string) []b...
function didl_lite (line 748) | func didl_lite(chardata string) string {
FILE: internal/dlna/html.go
function init (line 37) | func init() {
FILE: internal/dlna/mrrs.go
type mediaReceiverRegistrarService (line 9) | type mediaReceiverRegistrarService struct
method Handle (line 14) | func (mrrs *mediaReceiverRegistrarService) Handle(action string, argsX...
FILE: internal/dlna/paging.go
type scenePager (line 13) | type scenePager struct
method getPageID (line 18) | func (p *scenePager) getPageID(page int) string {
method getPages (line 22) | func (p *scenePager) getPages(ctx context.Context, r models.SceneQuery...
method getPageVideos (line 62) | func (p *scenePager) getPageVideos(ctx context.Context, r SceneFinder,...
FILE: internal/dlna/service.go
type Repository (line 17) | type Repository struct
method WithReadTxn (line 40) | func (r *Repository) WithReadTxn(ctx context.Context, fn txn.TxnFunc) ...
function NewRepository (line 28) | func NewRepository(repo models.Repository) Repository {
type Status (line 44) | type Status struct
type Dlnaip (line 52) | type Dlnaip struct
type dmsConfig (line 58) | type dmsConfig struct
type sceneServer (line 69) | type sceneServer interface
type Config (line 74) | type Config interface
type activityConfig (line 84) | type activityConfig struct
method GetDLNAActivityTrackingEnabled (line 89) | func (c *activityConfig) GetDLNAActivityTrackingEnabled() bool {
method GetMinimumPlayPercent (line 93) | func (c *activityConfig) GetMinimumPlayPercent() int {
type Service (line 97) | type Service struct
method getInterfaces (line 114) | func (s *Service) getInterfaces() ([]net.Interface, error) {
method init (line 149) | func (s *Service) init() error {
method Start (line 259) | func (s *Service) Start(duration *time.Duration) error {
method Stop (line 305) | func (s *Service) Stop(duration *time.Duration) {
method IsRunning (line 349) | func (s *Service) IsRunning() bool {
method Status (line 355) | func (s *Service) Status() *Status {
method AddTempDLNAIP (line 378) | func (s *Service) AddTempDLNAIP(pattern string, duration *time.Duratio...
method RemoveTempDLNAIP (line 382) | func (s *Service) RemoveTempDLNAIP(pattern string) bool {
function NewService (line 237) | func NewService(repo Repository, cfg Config, sceneServer sceneServer, sc...
FILE: internal/dlna/whitelist.go
constant recentListLength (line 10) | recentListLength = 10
constant wildcard (line 12) | wildcard = "*"
type tempIPWhitelist (line 14) | type tempIPWhitelist struct
type ipWhitelistManager (line 19) | type ipWhitelistManager struct
method addRecent (line 28) | func (m *ipWhitelistManager) addRecent(addr string) bool {
method getRecent (line 53) | func (m *ipWhitelistManager) getRecent() []string {
method getTempAllowed (line 60) | func (m *ipWhitelistManager) getTempAllowed() []*Dlnaip {
method ipAllowed (line 87) | func (m *ipWhitelistManager) ipAllowed(addr string) bool {
method removeExpiredWhitelists (line 125) | func (m *ipWhitelistManager) removeExpiredWhitelists() {
method allowPattern (line 141) | func (m *ipWhitelistManager) allowPattern(pattern string, duration *ti...
method removePattern (line 179) | func (m *ipWhitelistManager) removePattern(pattern string) bool {
FILE: internal/dlna/xmsr-service-desc.go
constant xmsMediaReceiverServiceDescription (line 24) | xmsMediaReceiverServiceDescription = `<?xml version="1.0" ?>
FILE: internal/identify/identify.go
type MultipleMatchesFoundError (line 25) | type MultipleMatchesFoundError struct
method Error (line 29) | func (e *MultipleMatchesFoundError) Error() string {
type SceneScraper (line 33) | type SceneScraper interface
type SceneUpdatePostHookExecutor (line 37) | type SceneUpdatePostHookExecutor interface
type ScraperSource (line 41) | type ScraperSource struct
type SceneIdentifier (line 48) | type SceneIdentifier struct
method Identify (line 60) | func (t *SceneIdentifier) Identify(ctx context.Context, scene *models....
method scrapeScene (line 102) | func (t *SceneIdentifier) scrapeScene(ctx context.Context, scene *mode...
method getOptions (line 132) | func (t *SceneIdentifier) getOptions(source ScraperSource) MetadataOpt...
method getSceneUpdater (line 169) | func (t *SceneIdentifier) getSceneUpdater(ctx context.Context, s *mode...
method modifyScene (line 285) | func (t *SceneIdentifier) modifyScene(ctx context.Context, s *models.S...
method addTagToScene (line 340) | func (t *SceneIdentifier) addTagToScene(ctx context.Context, s *models...
type scrapeResult (line 97) | type scrapeResult struct
function getFieldOptions (line 375) | func getFieldOptions(options []MetadataOptions) map[string]*FieldOptions {
function getScenePartial (line 389) | func getScenePartial(scene *models.Scene, scraped *models.ScrapedScene, ...
function getFieldStrategy (line 451) | func getFieldStrategy(strategy *FieldOptions) FieldStrategy {
function shouldSetSingleValueField (line 462) | func shouldSetSingleValueField(strategy *FieldOptions, hasExistingValue ...
FILE: internal/identify/identify_test.go
type mockSceneScraper (line 19) | type mockSceneScraper struct
method ScrapeScenes (line 24) | func (s mockSceneScraper) ScrapeScenes(ctx context.Context, sceneID in...
type mockHookExecutor (line 31) | type mockHookExecutor struct
method ExecuteSceneUpdatePostHooks (line 34) | func (s mockHookExecutor) ExecuteSceneUpdatePostHooks(ctx context.Cont...
function TestSceneIdentifier_Identify (line 37) | func TestSceneIdentifier_Identify(t *testing.T) {
function TestSceneIdentifier_modifyScene (line 220) | func TestSceneIdentifier_modifyScene(t *testing.T) {
function Test_getFieldOptions (line 282) | func Test_getFieldOptions(t *testing.T) {
function Test_getScenePartial (line 352) | func Test_getScenePartial(t *testing.T) {
function Test_shouldSetSingleValueField (line 533) | func Test_shouldSetSingleValueField(t *testing.T) {
FILE: internal/identify/options.go
type Source (line 12) | type Source struct
type Options (line 18) | type Options struct
type MetadataOptions (line 29) | type MetadataOptions struct
type FieldOptions (line 50) | type FieldOptions struct
type FieldStrategy (line 57) | type FieldStrategy
method IsValid (line 77) | func (e FieldStrategy) IsValid() bool {
method String (line 85) | func (e FieldStrategy) String() string {
method UnmarshalGQL (line 89) | func (e *FieldStrategy) UnmarshalGQL(v interface{}) error {
method MarshalGQL (line 102) | func (e FieldStrategy) MarshalGQL(w io.Writer) {
constant FieldStrategyIgnore (line 61) | FieldStrategyIgnore FieldStrategy = "IGNORE"
constant FieldStrategyMerge (line 64) | FieldStrategyMerge FieldStrategy = "MERGE"
constant FieldStrategyOverwrite (line 68) | FieldStrategyOverwrite FieldStrategy = "OVERWRITE"
FILE: internal/identify/performer.go
type PerformerCreator (line 12) | type PerformerCreator interface
function getPerformerID (line 17) | func getPerformerID(ctx context.Context, endpoint string, w PerformerCre...
function createMissingPerformer (line 37) | func createMissingPerformer(ctx context.Context, endpoint string, w Perf...
FILE: internal/identify/performer_test.go
function Test_getPerformerID (line 14) | func Test_getPerformerID(t *testing.T) {
function Test_createMissingPerformer (line 147) | func Test_createMissingPerformer(t *testing.T) {
FILE: internal/identify/scene.go
type SceneCoverGetter (line 19) | type SceneCoverGetter interface
type SceneReaderUpdater (line 23) | type SceneReaderUpdater interface
type sceneRelationships (line 32) | type sceneRelationships struct
method studio (line 43) | func (g sceneRelationships) studio(ctx context.Context) (*int, error) {
method performers (line 73) | func (g sceneRelationships) performers(ctx context.Context, allowedGen...
method tags (line 136) | func (g sceneRelationships) tags(ctx context.Context) ([]int, error) {
method stashIDs (line 197) | func (g sceneRelationships) stashIDs(ctx context.Context, setUpdateTim...
method cover (line 257) | func (g sceneRelationships) cover(ctx context.Context) ([]byte, error) {
FILE: internal/identify/scene_test.go
function Test_sceneRelationships_studio (line 16) | func Test_sceneRelationships_studio(t *testing.T) {
function Test_sceneRelationships_performers (line 144) | func Test_sceneRelationships_performers(t *testing.T) {
function Test_sceneRelationships_tags (line 334) | func Test_sceneRelationships_tags(t *testing.T) {
function Test_sceneRelationships_stashIDs (line 526) | func Test_sceneRelationships_stashIDs(t *testing.T) {
function Test_sceneRelationships_cover (line 755) | func Test_sceneRelationships_cover(t *testing.T) {
FILE: internal/identify/studio.go
function createMissingStudio (line 12) | func createMissingStudio(ctx context.Context, endpoint string, w models....
FILE: internal/identify/studio_test.go
function Test_createMissingStudio (line 13) | func Test_createMissingStudio(t *testing.T) {
FILE: internal/log/hook.go
type fileLogHook (line 9) | type fileLogHook struct
method Fire (line 14) | func (hook *fileLogHook) Fire(entry *logrus.Entry) error {
method Levels (line 23) | func (hook *fileLogHook) Levels() []logrus.Level {
FILE: internal/log/logger.go
type LogItem (line 16) | type LogItem struct
type Logger (line 22) | type Logger struct
method Init (line 46) | func (log *Logger) Init(logFile string, logOut bool, logLevel string, ...
method SetLogLevel (line 102) | func (log *Logger) SetLogLevel(level string) {
method addToCache (line 123) | func (log *Logger) addToCache(l *LogItem) {
method addLogItem (line 135) | func (log *Logger) addLogItem(l *LogItem) {
method GetLogCache (line 143) | func (log *Logger) GetLogCache() []LogItem {
method SubscribeToLog (line 154) | func (log *Logger) SubscribeToLog(stop chan int) <-chan []LogItem {
method unsubscribeFromLog (line 169) | func (log *Logger) unsubscribeFromLog(toRemove chan []LogItem) {
method doBroadcastLogItems (line 180) | func (log *Logger) doBroadcastLogItems() {
method broadcastLogItem (line 196) | func (log *Logger) broadcastLogItem(l *LogItem) {
method Progressf (line 222) | func (log *Logger) Progressf(format string, args ...interface{}) {
method Trace (line 231) | func (log *Logger) Trace(args ...interface{}) {
method Tracef (line 240) | func (log *Logger) Tracef(format string, args ...interface{}) {
method TraceFunc (line 249) | func (log *Logger) TraceFunc(fn func() (string, []interface{})) {
method Debug (line 256) | func (log *Logger) Debug(args ...interface{}) {
method Debugf (line 265) | func (log *Logger) Debugf(format string, args ...interface{}) {
method logFunc (line 274) | func (log *Logger) logFunc(level logrus.Level, logFn func(format strin...
method DebugFunc (line 281) | func (log *Logger) DebugFunc(fn func() (string, []interface{})) {
method Info (line 285) | func (log *Logger) Info(args ...interface{}) {
method Infof (line 294) | func (log *Logger) Infof(format string, args ...interface{}) {
method InfoFunc (line 303) | func (log *Logger) InfoFunc(fn func() (string, []interface{})) {
method Warn (line 307) | func (log *Logger) Warn(args ...interface{}) {
method Warnf (line 316) | func (log *Logger) Warnf(format string, args ...interface{}) {
method WarnFunc (line 325) | func (log *Logger) WarnFunc(fn func() (string, []interface{})) {
method Error (line 329) | func (log *Logger) Error(args ...interface{}) {
method Errorf (line 338) | func (log *Logger) Errorf(format string, args ...interface{}) {
method ErrorFunc (line 347) | func (log *Logger) ErrorFunc(fn func() (string, []interface{})) {
method Fatal (line 351) | func (log *Logger) Fatal(args ...interface{}) {
method Fatalf (line 355) | func (log *Logger) Fatalf(format string, args ...interface{}) {
function NewLogger (line 33) | func NewLogger() *Logger {
function logLevelFromString (line 106) | func logLevelFromString(level string) logrus.Level {
FILE: internal/log/progress_formatter.go
type ProgressFormatter (line 7) | type ProgressFormatter struct
method Format (line 9) | func (f *ProgressFormatter) Format(entry *logrus.Entry) ([]byte, error) {
FILE: internal/manager/apikey.go
constant APIKeySubject (line 13) | APIKeySubject = "APIKey"
type APIKeyClaims (line 15) | type APIKeyClaims struct
function GenerateAPIKey (line 20) | func GenerateAPIKey(userID string) (string, error) {
function GetUserIDFromAPIKey (line 40) | func GetUserIDFromAPIKey(apiKey string) (string, error) {
FILE: internal/manager/backup.go
type databaseBackupZip (line 17) | type databaseBackupZip struct
method zipFileRename (line 21) | func (z *databaseBackupZip) zipFileRename(fn, outDir, outFn string) er...
method zipFile (line 44) | func (z *databaseBackupZip) zipFile(fn, outDir string) error {
method BackupDatabase (line 48) | func (s *Manager) BackupDatabase(download bool, includeBlobs bool) (stri...
method backupDatabaseOnly (line 146) | func (s *Manager) backupDatabaseOnly(download bool) (string, string, err...
FILE: internal/manager/checksum.go
type SceneMissingHashCounter (line 10) | type SceneMissingHashCounter interface
function ValidateVideoFileNamingAlgorithm (line 23) | func ValidateVideoFileNamingAlgorithm(ctx context.Context, qb SceneMissi...
FILE: internal/manager/config/config.go
constant Stash (line 34) | Stash = "stash"
constant Cache (line 35) | Cache = "cache"
constant BackupDirectoryPath (line 36) | BackupDirectoryPath = "backup_directory_path"
constant Generated (line 37) | Generated = "generated"
constant Metadata (line 38) | Metadata = "metadata"
constant BlobsPath (line 39) | BlobsPath = "blobs_path"
constant Downloads (line 40) | Downloads = "downloads"
constant ApiKey (line 41) | ApiKey = "api_key"
constant Username (line 42) | Username = "username"
constant Password (line 43) | Password = "password"
constant MaxSessionAge (line 44) | MaxSessionAge = "max_session_age"
constant SFWContentMode (line 47) | SFWContentMode = "sfw_content_mode"
constant FFMpegPath (line 49) | FFMpegPath = "ffmpeg_path"
constant FFProbePath (line 50) | FFProbePath = "ffprobe_path"
constant BlobsStorage (line 52) | BlobsStorage = "blobs_storage"
constant DefaultMaxSessionAge (line 54) | DefaultMaxSessionAge = 60 * 60 * 1
constant Database (line 56) | Database = "database"
constant Exclude (line 58) | Exclude = "exclude"
constant ImageExclude (line 59) | ImageExclude = "image_exclude"
constant VideoExtensions (line 61) | VideoExtensions = "video_extensions"
constant ImageExtensions (line 62) | ImageExtensions = "image_extensions"
constant GalleryExtensions (line 63) | GalleryExtensions = "gallery_extensions"
constant CreateGalleriesFromFolders (line 64) | CreateGalleriesFromFolders = "create_galleries_from_folders"
constant CalculateMD5 (line 68) | CalculateMD5 = "calculate_md5"
constant VideoFileNamingAlgorithm (line 72) | VideoFileNamingAlgorithm = "video_file_naming_algorithm"
constant MaxTranscodeSize (line 74) | MaxTranscodeSize = "max_transcode_size"
constant MaxStreamingTranscodeSize (line 75) | MaxStreamingTranscodeSize = "max_streaming_transcode_size"
constant TranscodeInputArgs (line 78) | TranscodeInputArgs = "ffmpeg.transcode.input_args"
constant TranscodeOutputArgs (line 79) | TranscodeOutputArgs = "ffmpeg.transcode.output_args"
constant LiveTranscodeInputArgs (line 80) | LiveTranscodeInputArgs = "ffmpeg.live_transcode.input_args"
constant LiveTranscodeOutputArgs (line 81) | LiveTranscodeOutputArgs = "ffmpeg.live_transcode.output_args"
constant ParallelTasks (line 83) | ParallelTasks = "parallel_tasks"
constant parallelTasksDefault (line 84) | parallelTasksDefault = 1
constant UseCustomSpriteInterval (line 86) | UseCustomSpriteInterval = "use_custom_sprite_interval"
constant UseCustomSpriteIntervalDefault (line 87) | UseCustomSpriteIntervalDefault = false
constant SpriteInterval (line 89) | SpriteInterval = "sprite_interval"
constant SpriteIntervalDefault (line 90) | SpriteIntervalDefault = 30
constant MinimumSprites (line 92) | MinimumSprites = "minimum_sprites"
constant MinimumSpritesDefault (line 93) | MinimumSpritesDefault = 10
constant MaximumSprites (line 95) | MaximumSprites = "maximum_sprites"
constant MaximumSpritesDefault (line 96) | MaximumSpritesDefault = 500
constant SpriteScreenshotSize (line 98) | SpriteScreenshotSize = "sprite_screenshot_width"
constant spriteScreenshotSizeDefault (line 99) | spriteScreenshotSizeDefault = 160
constant PreviewPreset (line 101) | PreviewPreset = "preview_preset"
constant TranscodeHardwareAcceleration (line 102) | TranscodeHardwareAcceleration = "ffmpeg.hardware_acceleration"
constant SequentialScanning (line 104) | SequentialScanning = "sequential_scanning"
constant SequentialScanningDefault (line 105) | SequentialScanningDefault = false
constant PreviewAudio (line 107) | PreviewAudio = "preview_audio"
constant previewAudioDefault (line 108) | previewAudioDefault = true
constant PreviewSegmentDuration (line 110) | PreviewSegmentDuration = "preview_segment_duration"
constant previewSegmentDurationDefault (line 111) | previewSegmentDurationDefault = 0.75
constant PreviewSegments (line 113) | PreviewSegments = "preview_segments"
constant previewSegmentsDefault (line 114) | previewSegmentsDefault = 12
constant PreviewExcludeStart (line 116) | PreviewExcludeStart = "preview_exclude_start"
constant previewExcludeStartDefault (line 117) | previewExcludeStartDefault = "0"
constant PreviewExcludeEnd (line 119) | PreviewExcludeEnd = "preview_exclude_end"
constant previewExcludeEndDefault (line 120) | previewExcludeEndDefault = "0"
constant WriteImageThumbnails (line 122) | WriteImageThumbnails = "write_image_thumbnails"
constant writeImageThumbnailsDefault (line 123) | writeImageThumbnailsDefault = true
constant CreateImageClipsFromVideos (line 125) | CreateImageClipsFromVideos = "create_image_clip_from_videos"
constant createImageClipsFromVideosDefault (line 126) | createImageClipsFromVideosDefault = false
constant Host (line 128) | Host = "host"
constant hostDefault (line 129) | hostDefault = "0.0.0.0"
constant Port (line 131) | Port = "port"
constant portDefault (line 132) | portDefault = 9999
constant ExternalHost (line 134) | ExternalHost = "external_host"
constant Proxy (line 137) | Proxy = "proxy"
constant NoProxy (line 140) | NoProxy = "no_proxy"
constant noProxyDefault (line 141) | noProxyDefault = "localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0...
constant JWTSignKey (line 144) | JWTSignKey = "jwt_secret_key"
constant SessionStoreKey (line 147) | SessionStoreKey = "session_store_key"
constant ScrapersPath (line 150) | ScrapersPath = "scrapers_path"
constant ScraperUserAgent (line 151) | ScraperUserAgent = "scraper_user_agent"
constant ScraperCertCheck (line 152) | ScraperCertCheck = "scraper_cert_check"
constant ScraperCDPPath (line 153) | ScraperCDPPath = "scraper_cdp_path"
constant ScraperExcludeTagPatterns (line 154) | ScraperExcludeTagPatterns = "scraper_exclude_tag_patterns"
constant StashBoxes (line 157) | StashBoxes = "stash_boxes"
constant PythonPath (line 159) | PythonPath = "python_path"
constant PluginsPath (line 162) | PluginsPath = "plugins_path"
constant PluginsSetting (line 163) | PluginsSetting = "plugins.settings"
constant PluginsSettingPrefix (line 164) | PluginsSettingPrefix = PluginsSetting + "."
constant DisabledPlugins (line 165) | DisabledPlugins = "plugins.disabled"
constant sourceDefaultPath (line 167) | sourceDefaultPath = "community"
constant sourceDefaultName (line 168) | sourceDefaultName = "Community (stable)"
constant PluginPackageSources (line 170) | PluginPackageSources = "plugins.package_sources"
constant pluginPackageSourcesDefault (line 171) | pluginPackageSourcesDefault = "https://stashapp.github.io/CommunityScrip...
constant ScraperPackageSources (line 173) | ScraperPackageSources = "scrapers.package_sources"
constant scraperPackageSourcesDefault (line 174) | scraperPackageSourcesDefault = "https://stashapp.github.io/CommunityScra...
constant Language (line 177) | Language = "language"
constant CustomServedFolders (line 181) | CustomServedFolders = "custom_served_folders"
constant UILocation (line 185) | UILocation = "ui_location"
constant LegacyCustomUILocation (line 188) | LegacyCustomUILocation = "custom_ui_location"
constant GalleryCoverRegex (line 191) | GalleryCoverRegex = "gallery_cover_regex"
constant galleryCoverRegexDefault (line 192) | galleryCoverRegexDefault = `(poster|cover|folder|board)\.[^\.]+$`
constant MenuItems (line 195) | MenuItems = "menu_items"
constant SoundOnPreview (line 197) | SoundOnPreview = "sound_on_preview"
constant WallShowTitle (line 199) | WallShowTitle = "wall_show_title"
constant defaultWallShowTitle (line 200) | defaultWallShowTitle = true
constant CustomPerformerImageLocation (line 202) | CustomPerformerImageLocation = "custom_performer_image_location"
constant MaximumLoopDuration (line 203) | MaximumLoopDuration = "maximum_loop_duration"
constant AutostartVideo (line 204) | AutostartVideo = "autostart_video"
constant AutostartVideoOnPlaySelected (line 205) | AutostartVideoOnPlaySelected = "autostart_video_on_play_selected"
constant autostartVideoOnPlaySelectedDefault (line 206) | autostartVideoOnPlaySelectedDefault = true
constant ContinuePlaylistDefault (line 207) | ContinuePlaylistDefault = "continue_playlist_default"
constant ShowStudioAsText (line 208) | ShowStudioAsText = "show_studio_as_text"
constant CSSEnabled (line 209) | CSSEnabled = "cssenabled"
constant JavascriptEnabled (line 210) | JavascriptEnabled = "javascriptenabled"
constant CustomLocalesEnabled (line 211) | CustomLocalesEnabled = "customlocalesenabled"
constant DisableCustomizations (line 212) | DisableCustomizations = "disable_customizations"
constant ShowScrubber (line 214) | ShowScrubber = "show_scrubber"
constant showScrubberDefault (line 215) | showScrubberDefault = true
constant WallPlayback (line 217) | WallPlayback = "wall_playback"
constant defaultWallPlayback (line 218) | defaultWallPlayback = "video"
constant legacyImageLightboxSlideshowDelay (line 221) | legacyImageLightboxSlideshowDelay = "slideshow_delay"
constant ImageLightboxSlideshowDelay (line 222) | ImageLightboxSlideshowDelay = "image_lightbox.slideshow_delay"
constant ImageLightboxDisplayModeKey (line 223) | ImageLightboxDisplayModeKey = "image_lightbox.display_mode"
constant ImageLightboxScaleUp (line 224) | ImageLightboxScaleUp = "image_lightbox.scale_up"
constant ImageLightboxResetZoomOnNav (line 225) | ImageLightboxResetZoomOnNav = "image_lightbox.reset_zoom_on_...
constant ImageLightboxScrollModeKey (line 226) | ImageLightboxScrollModeKey = "image_lightbox.scroll_mode"
constant ImageLightboxScrollAttemptsBeforeChange (line 227) | ImageLightboxScrollAttemptsBeforeChange = "image_lightbox.scroll_attempt...
constant ImageLightboxDisableAnimation (line 228) | ImageLightboxDisableAnimation = "image_lightbox.disable_animat...
constant UI (line 230) | UI = "ui"
constant defaultImageLightboxSlideshowDelay (line 232) | defaultImageLightboxSlideshowDelay = 5
constant DisableDropdownCreatePerformer (line 234) | DisableDropdownCreatePerformer = "disable_dropdown_create.performer"
constant DisableDropdownCreateStudio (line 235) | DisableDropdownCreateStudio = "disable_dropdown_create.studio"
constant DisableDropdownCreateTag (line 236) | DisableDropdownCreateTag = "disable_dropdown_create.tag"
constant DisableDropdownCreateMovie (line 237) | DisableDropdownCreateMovie = "disable_dropdown_create.movie"
constant DisableDropdownCreateGallery (line 238) | DisableDropdownCreateGallery = "disable_dropdown_create.gallery"
constant HandyKey (line 240) | HandyKey = "handy_key"
constant FunscriptOffset (line 241) | FunscriptOffset = "funscript_offset"
constant UseStashHostedFunscript (line 242) | UseStashHostedFunscript = "use_stash_hosted_funscript"
constant useStashHostedFunscriptDefault (line 243) | useStashHostedFunscriptDefault = false
constant DrawFunscriptHeatmapRange (line 245) | DrawFunscriptHeatmapRange = "draw_funscript_heatmap_range"
constant drawFunscriptHeatmapRangeDefault (line 246) | drawFunscriptHeatmapRangeDefault = true
constant ThemeColor (line 248) | ThemeColor = "theme_color"
constant DefaultThemeColor (line 249) | DefaultThemeColor = "#202b33"
constant dangerousAllowPublicWithoutAuth (line 252) | dangerousAllowPublicWithoutAuth = "dangerous_allow_pub...
constant dangerousAllowPublicWithoutAuthDefault (line 253) | dangerousAllowPublicWithoutAuthDefault = "false"
constant SecurityTripwireAccessedFromPublicInternet (line 254) | SecurityTripwireAccessedFromPublicInternet = "security_tripwire_a...
constant securityTripwireAccessedFromPublicInternetDefault (line 255) | securityTripwireAccessedFromPublicInternetDefault = ""
constant sslCertPath (line 257) | sslCertPath = "ssl_cert_path"
constant sslKeyPath (line 258) | sslKeyPath = "ssl_key_path"
constant DLNAServerName (line 261) | DLNAServerName = "dlna.server_name"
constant DLNADefaultEnabled (line 262) | DLNADefaultEnabled = "dlna.default_enabled"
constant DLNADefaultIPWhitelist (line 263) | DLNADefaultIPWhitelist = "dlna.default_whitelist"
constant DLNAInterfaces (line 264) | DLNAInterfaces = "dlna.interfaces"
constant DLNAVideoSortOrder (line 266) | DLNAVideoSortOrder = "dlna.video_sort_order"
constant dlnaVideoSortOrderDefault (line 267) | dlnaVideoSortOrderDefault = "title"
constant DLNAPort (line 269) | DLNAPort = "dlna.port"
constant DLNAPortDefault (line 270) | DLNAPortDefault = 1338
constant LogFile (line 273) | LogFile = "logfile"
constant LogOut (line 274) | LogOut = "logout"
constant defaultLogOut (line 275) | defaultLogOut = true
constant LogLevel (line 276) | LogLevel = "loglevel"
constant defaultLogLevel (line 277) | defaultLogLevel = "Info"
constant LogAccess (line 278) | LogAccess = "logaccess"
constant defaultLogAccess (line 279) | defaultLogAccess = true
constant LogFileMaxSize (line 280) | LogFileMaxSize = "logfile_max_size"
constant defaultLogFileMaxSize (line 281) | defaultLogFileMaxSize = 0
constant DefaultScanSettings (line 284) | DefaultScanSettings = "defaults.scan_task"
constant DefaultIdentifySettings (line 285) | DefaultIdentifySettings = "defaults.identify_task"
constant DefaultAutoTagSettings (line 286) | DefaultAutoTagSettings = "defaults.auto_tag_task"
constant DefaultGenerateSettings (line 287) | DefaultGenerateSettings = "defaults.generate_task"
constant DeleteFileDefault (line 289) | DeleteFileDefault = "defaults.delete_file"
constant DeleteGeneratedDefault (line 290) | DeleteGeneratedDefault = "defaults.delete_generated"
constant deleteGeneratedDefaultDefault (line 291) | deleteGeneratedDefaultDefault = true
constant DeleteTrashPath (line 294) | DeleteTrashPath = "delete_trash_path"
constant NoBrowser (line 297) | NoBrowser = "nobrowser"
constant NoBrowserDefault (line 298) | NoBrowserDefault = false
constant NotificationsEnabled (line 299) | NotificationsEnabled = "notifications_enabled"
constant NotificationsEnabledDefault (line 300) | NotificationsEnabledDefault = true
constant ShowOneTimeMovedNotification (line 301) | ShowOneTimeMovedNotification = "show_one_time_moved_notification"
constant ShowOneTimeMovedNotificationDefault (line 302) | ShowOneTimeMovedNotificationDefault = false
constant MaxUploadSize (line 305) | MaxUploadSize = "max_upload_size"
constant ExtraBlobsPaths (line 308) | ExtraBlobsPaths = "developer_options.extra_blob_paths"
type MissingConfigError (line 319) | type MissingConfigError struct
method Error (line 323) | func (e MissingConfigError) Error() string {
type StashBoxError (line 328) | type StashBoxError struct
method Error (line 332) | func (s *StashBoxError) Error() string {
type Config (line 337) | type Config struct
method load (line 363) | func (i *Config) load(f string) error {
method IsNewSystem (line 372) | func (i *Config) IsNewSystem() bool {
method SetConfigFile (line 376) | func (i *Config) SetConfigFile(fn string) {
method InitTLS (line 382) | func (i *Config) InitTLS() {
method GetTLSFiles (line 402) | func (i *Config) GetTLSFiles() (certFile, keyFile string) {
method HasTLSConfig (line 406) | func (i *Config) HasTLSConfig() bool {
method GetNoBrowser (line 411) | func (i *Config) GetNoBrowser() bool {
method GetNotificationsEnabled (line 415) | func (i *Config) GetNotificationsEnabled() bool {
method GetShowOneTimeMovedNotification (line 422) | func (i *Config) GetShowOneTimeMovedNotification() bool {
method SetBool (line 427) | func (i *Config) SetBool(key string, value bool) {
method SetString (line 431) | func (i *Config) SetString(key string, value string) {
method SetInt (line 435) | func (i *Config) SetInt(key string, value int) {
method SetFloat (line 439) | func (i *Config) SetFloat(key string, value float64) {
method SetInterface (line 443) | func (i *Config) SetInterface(key string, value interface{}) {
method set (line 450) | func (i *Config) set(key string, value interface{}) {
method SetDefault (line 470) | func (i *Config) SetDefault(key string, value interface{}) {
method setDefault (line 477) | func (i *Config) setDefault(key string, value interface{}) {
method SetPassword (line 483) | func (i *Config) SetPassword(value string) {
method Write (line 492) | func (i *Config) Write() error {
method Marshal (line 504) | func (i *Config) Marshal() ([]byte, error) {
method marshal (line 511) | func (i *Config) marshal() ([]byte, error) {
method GetConfigFile (line 522) | func (i *Config) GetConfigFile() string {
method GetConfigPath (line 530) | func (i *Config) GetConfigPath() string {
method GetConfigPathAbs (line 537) | func (i *Config) GetConfigPathAbs() string {
method GetDefaultDatabaseFilePath (line 550) | func (i *Config) GetDefaultDatabaseFilePath() string {
method forKey (line 557) | func (i *Config) forKey(key string) *koanf.Koanf {
method with (line 568) | func (i *Config) with(key string) *koanf.Koanf {
method HasOverride (line 578) | func (i *Config) HasOverride(key string) bool {
method unmarshalKey (line 588) | func (i *Config) unmarshalKey(key string, rawVal interface{}) error {
method getStringSlice (line 595) | func (i *Config) getStringSlice(key string) []string {
method getString (line 602) | func (i *Config) getString(key string) string {
method getBool (line 609) | func (i *Config) getBool(key string) bool {
method getBoolDefault (line 616) | func (i *Config) getBoolDefault(key string, def bool) bool {
method getInt (line 628) | func (i *Config) getInt(key string) int {
method getFloat64 (line 635) | func (i *Config) getFloat64(key string) float64 {
method getStringMapString (line 642) | func (i *Config) getStringMapString(key string) map[string]string {
method GetSFWContentMode (line 659) | func (i *Config) GetSFWContentMode() bool {
method GetStashPaths (line 668) | func (i *Config) GetStashPaths() StashConfigs {
method GetCachePath (line 694) | func (i *Config) GetCachePath() string {
method GetGeneratedPath (line 698) | func (i *Config) GetGeneratedPath() string {
method GetBlobsPath (line 702) | func (i *Config) GetBlobsPath() string {
method GetExtraBlobsPaths (line 708) | func (i *Config) GetExtraBlobsPaths() []string {
method GetBlobsStorage (line 712) | func (i *Config) GetBlobsStorage() BlobsStorageType {
method GetMetadataPath (line 724) | func (i *Config) GetMetadataPath() string {
method GetDatabasePath (line 728) | func (i *Config) GetDatabasePath() string {
method GetBackupDirectoryPath (line 732) | func (i *Config) GetBackupDirectoryPath() string {
method GetBackupDirectoryPathOrDefault (line 736) | func (i *Config) GetBackupDirectoryPathOrDefault() string {
method GetFFMpegPath (line 748) | func (i *Config) GetFFMpegPath() string {
method GetFFProbePath (line 754) | func (i *Config) GetFFProbePath() string {
method GetJWTSignKey (line 758) | func (i *Config) GetJWTSignKey() []byte {
method GetSessionStoreKey (line 762) | func (i *Config) GetSessionStoreKey() []byte {
method GetDefaultScrapersPath (line 766) | func (i *Config) GetDefaultScrapersPath() string {
method GetExcludes (line 773) | func (i *Config) GetExcludes() []string {
method GetImageExcludes (line 777) | func (i *Config) GetImageExcludes() []string {
method GetVideoExtensions (line 781) | func (i *Config) GetVideoExtensions() []string {
method GetImageExtensions (line 789) | func (i *Config) GetImageExtensions() []string {
method GetGalleryExtensions (line 797) | func (i *Config) GetGalleryExtensions() []string {
method GetCreateGalleriesFromFolders (line 805) | func (i *Config) GetCreateGalleriesFromFolders() bool {
method GetLanguage (line 809) | func (i *Config) GetLanguage() string {
method IsCalculateMD5 (line 822) | func (i *Config) IsCalculateMD5() bool {
method GetVideoFileNamingAlgorithm (line 828) | func (i *Config) GetVideoFileNamingAlgorithm() models.HashAlgorithm {
method GetSequentialScanning (line 839) | func (i *Config) GetSequentialScanning() bool {
method GetGalleryCoverRegex (line 843) | func (i *Config) GetGalleryCoverRegex() string {
method GetScrapersPath (line 855) | func (i *Config) GetScrapersPath() string {
method GetScraperUserAgent (line 859) | func (i *Config) GetScraperUserAgent() string {
method GetScraperCDPPath (line 865) | func (i *Config) GetScraperCDPPath() string {
method GetScraperCertCheck (line 871) | func (i *Config) GetScraperCertCheck() bool {
method GetScraperExcludeTagPatterns (line 875) | func (i *Config) GetScraperExcludeTagPatterns() []string {
method GetStashBoxes (line 879) | func (i *Config) GetStashBoxes() []*models.StashBox {
method GetDefaultPluginsPath (line 888) | func (i *Config) GetDefaultPluginsPath() string {
method GetPluginsPath (line 895) | func (i *Config) GetPluginsPath() string {
method GetAllPluginConfiguration (line 899) | func (i *Config) GetAllPluginConfiguration() map[string]map[string]int...
method GetPluginConfiguration (line 919) | func (i *Config) GetPluginConfiguration(pluginID string) map[string]in...
method SetPluginConfiguration (line 930) | func (i *Config) SetPluginConfiguration(pluginID string, v map[string]...
method GetDisabledPlugins (line 939) | func (i *Config) GetDisabledPlugins() []string {
method GetPythonPath (line 943) | func (i *Config) GetPythonPath() string {
method GetHost (line 947) | func (i *Config) GetHost() string {
method GetPort (line 956) | func (i *Config) GetPort() int {
method GetThemeColor (line 965) | func (i *Config) GetThemeColor() string {
method GetExternalHost (line 969) | func (i *Config) GetExternalHost() string {
method GetPreviewSegmentDuration (line 975) | func (i *Config) GetPreviewSegmentDuration() float64 {
method GetParallelTasks (line 981) | func (i *Config) GetParallelTasks() int {
method GetParallelTasksWithAutoDetection (line 985) | func (i *Config) GetParallelTasksWithAutoDetection() int {
method GetUseCustomSpriteInterval (line 995) | func (i *Config) GetUseCustomSpriteInterval() bool {
method GetSpriteInterval (line 1003) | func (i *Config) GetSpriteInterval() float64 {
method GetMinimumSprites (line 1010) | func (i *Config) GetMinimumSprites() int {
method GetMaximumSprites (line 1020) | func (i *Config) GetMaximumSprites() int {
method GetSpriteScreenshotSize (line 1029) | func (i *Config) GetSpriteScreenshotSize() int {
method GetPreviewAudio (line 1037) | func (i *Config) GetPreviewAudio() bool {
method GetPreviewSegments (line 1042) | func (i *Config) GetPreviewSegments() int {
method GetPreviewExcludeStart (line 1052) | func (i *Config) GetPreviewExcludeStart() string {
method GetPreviewExcludeEnd (line 1061) | func (i *Config) GetPreviewExcludeEnd() string {
method GetPreviewPreset (line 1067) | func (i *Config) GetPreviewPreset() models.PreviewPreset {
method GetTranscodeHardwareAcceleration (line 1078) | func (i *Config) GetTranscodeHardwareAcceleration() bool {
method GetMaxTranscodeSize (line 1082) | func (i *Config) GetMaxTranscodeSize() models.StreamingResolutionEnum {
method GetMaxStreamingTranscodeSize (line 1093) | func (i *Config) GetMaxStreamingTranscodeSize() models.StreamingResolu...
method GetTranscodeInputArgs (line 1104) | func (i *Config) GetTranscodeInputArgs() []string {
method GetTranscodeOutputArgs (line 1108) | func (i *Config) GetTranscodeOutputArgs() []string {
method GetLiveTranscodeInputArgs (line 1112) | func (i *Config) GetLiveTranscodeInputArgs() []string {
method GetLiveTranscodeOutputArgs (line 1116) | func (i *Config) GetLiveTranscodeOutputArgs() []string {
method GetDrawFunscriptHeatmapRange (line 1120) | func (i *Config) GetDrawFunscriptHeatmapRange() bool {
method IsWriteImageThumbnails (line 1126) | func (i *Config) IsWriteImageThumbnails() bool {
method IsCreateImageClipsFromVideos (line 1130) | func (i *Config) IsCreateImageClipsFromVideos() bool {
method GetAPIKey (line 1134) | func (i *Config) GetAPIKey() string {
method GetUsername (line 1138) | func (i *Config) GetUsername() string {
method GetPasswordHash (line 1142) | func (i *Config) GetPasswordHash() string {
method GetCredentials (line 1146) | func (i *Config) GetCredentials() (string, string) {
method HasCredentials (line 1154) | func (i *Config) HasCredentials() bool {
method ValidateCredentials (line 1167) | func (i *Config) ValidateCredentials(username string, password string)...
method ValidateStashBoxes (line 1192) | func (i *Config) ValidateStashBoxes(boxes []*StashBoxInput) error {
method GetMaxSessionAge (line 1219) | func (i *Config) GetMaxSessionAge() int {
method GetCustomServedFolders (line 1234) | func (i *Config) GetCustomServedFolders() utils.URLMap {
method GetUILocation (line 1238) | func (i *Config) GetUILocation() string {
method GetMenuItems (line 1247) | func (i *Config) GetMenuItems() []string {
method GetSoundOnPreview (line 1257) | func (i *Config) GetSoundOnPreview() bool {
method GetWallShowTitle (line 1261) | func (i *Config) GetWallShowTitle() bool {
method GetCustomPerformerImageLocation (line 1273) | func (i *Config) GetCustomPerformerImageLocation() string {
method GetWallPlayback (line 1277) | func (i *Config) GetWallPlayback() string {
method GetShowScrubber (line 1290) | func (i *Config) GetShowScrubber() bool {
method GetMaximumLoopDuration (line 1294) | func (i *Config) GetMaximumLoopDuration() int {
method GetAutostartVideo (line 1298) | func (i *Config) GetAutostartVideo() bool {
method GetAutostartVideoOnPlaySelected (line 1302) | func (i *Config) GetAutostartVideoOnPlaySelected() bool {
method GetContinuePlaylistDefault (line 1306) | func (i *Config) GetContinuePlaylistDefault() bool {
method GetShowStudioAsText (line 1310) | func (i *Config) GetShowStudioAsText() bool {
method getSlideshowDelay (line 1314) | func (i *Config) getSlideshowDelay() int {
method GetImageLightboxOptions (line 1332) | func (i *Config) GetImageLightboxOptions() ConfigImageLightboxResult {
method GetDisableDropdownCreate (line 1369) | func (i *Config) GetDisableDropdownCreate() *ConfigDisableDropdownCrea...
method GetUIConfiguration (line 1379) | func (i *Config) GetUIConfiguration() map[string]interface{} {
method GetMinimumPlayPercent (line 1388) | func (i *Config) GetMinimumPlayPercent() int {
method SetUIConfiguration (line 1406) | func (i *Config) SetUIConfiguration(v map[string]interface{}) {
method GetCSSPath (line 1413) | func (i *Config) GetCSSPath() string {
method GetCSS (line 1423) | func (i *Config) GetCSS() string {
method SetCSS (line 1440) | func (i *Config) SetCSS(css string) {
method GetCSSEnabled (line 1452) | func (i *Config) GetCSSEnabled() bool {
method GetJavascriptPath (line 1456) | func (i *Config) GetJavascriptPath() string {
method GetJavascript (line 1466) | func (i *Config) GetJavascript() string {
method SetJavascript (line 1483) | func (i *Config) SetJavascript(javascript string) {
method GetJavascriptEnabled (line 1495) | func (i *Config) GetJavascriptEnabled() bool {
method GetCustomLocalesPath (line 1499) | func (i *Config) GetCustomLocalesPath() string {
method GetCustomLocales (line 1509) | func (i *Config) GetCustomLocales() string {
method SetCustomLocales (line 1526) | func (i *Config) SetCustomLocales(customLocales string) {
method GetCustomLocalesEnabled (line 1538) | func (i *Config) GetCustomLocalesEnabled() bool {
method GetDisableCustomizations (line 1545) | func (i *Config) GetDisableCustomizations() bool {
method GetHandyKey (line 1549) | func (i *Config) GetHandyKey() string {
method GetFunscriptOffset (line 1553) | func (i *Config) GetFunscriptOffset() int {
method GetUseStashHostedFunscript (line 1557) | func (i *Config) GetUseStashHostedFunscript() bool {
method GetDeleteFileDefault (line 1561) | func (i *Config) GetDeleteFileDefault() bool {
method GetDeleteGeneratedDefault (line 1565) | func (i *Config) GetDeleteGeneratedDefault() bool {
method GetDeleteTrashPath (line 1569) | func (i *Config) GetDeleteTrashPath() string {
method SetDeleteTrashPath (line 1573) | func (i *Config) SetDeleteTrashPath(value string) {
method GetDefaultIdentifySettings (line 1580) | func (i *Config) GetDefaultIdentifySettings() *identify.Options {
method GetDefaultScanSettings (line 1600) | func (i *Config) GetDefaultScanSettings() *ScanMetadataOptions {
method GetDefaultAutoTagSettings (line 1619) | func (i *Config) GetDefaultAutoTagSettings() *AutoTagMetadataOptions {
method GetDefaultGenerateSettings (line 1638) | func (i *Config) GetDefaultGenerateSettings() *models.GenerateMetadata...
method GetDangerousAllowPublicWithoutAuth (line 1656) | func (i *Config) GetDangerousAllowPublicWithoutAuth() bool {
method GetSecurityTripwireAccessedFromPublicInternet (line 1663) | func (i *Config) GetSecurityTripwireAccessedFromPublicInternet() string {
method GetDLNAServerName (line 1669) | func (i *Config) GetDLNAServerName() string {
method GetDLNADefaultEnabled (line 1674) | func (i *Config) GetDLNADefaultEnabled() bool {
method GetDLNADefaultIPWhitelist (line 1680) | func (i *Config) GetDLNADefaultIPWhitelist() []string {
method GetDLNAInterfaces (line 1686) | func (i *Config) GetDLNAInterfaces() []string {
method GetDLNAPort (line 1692) | func (i *Config) GetDLNAPort() int {
method GetDLNAPortAsString (line 1701) | func (i *Config) GetDLNAPortAsString() string {
method GetDLNAActivityTrackingEnabled (line 1708) | func (i *Config) GetDLNAActivityTrackingEnabled() bool {
method GetVideoSortOrder (line 1723) | func (i *Config) GetVideoSortOrder() string {
method GetLogFile (line 1734) | func (i *Config) GetLogFile() string {
method GetLogOut (line 1741) | func (i *Config) GetLogOut() bool {
method GetLogLevel (line 1747) | func (i *Config) GetLogLevel() string {
method GetLogAccess (line 1758) | func (i *Config) GetLogAccess() bool {
method GetLogFileMaxSize (line 1763) | func (i *Config) GetLogFileMaxSize() int {
method GetMaxUploadSize (line 1773) | func (i *Config) GetMaxUploadSize() int64 {
method GetProxy (line 1786) | func (i *Config) GetProxy() string {
method GetNoProxy (line 1801) | func (i *Config) GetNoProxy() string {
method ActivatePublicAccessTripwire (line 1809) | func (i *Config) ActivatePublicAccessTripwire(requestIP string) error {
method getPackageSources (line 1814) | func (i *Config) getPackageSources(key string) []*models.PackageSource {
method GetPluginPackageSources (line 1823) | func (i *Config) GetPluginPackageSources() []*models.PackageSource {
method GetScraperPackageSources (line 1827) | func (i *Config) GetScraperPackageSources() []*models.PackageSource {
method GetPluginPackagePathGetter (line 1857) | func (i *Config) GetPluginPackagePathGetter() packagePathGetter {
method GetScraperPackagePathGetter (line 1863) | func (i *Config) GetScraperPackagePathGetter() packagePathGetter {
method Validate (line 1869) | func (i *Config) Validate() error {
method setDefaultValues (line 1900) | func (i *Config) setDefaultValues() {
method setExistingSystemDefaults (line 1972) | func (i *Config) setExistingSystemDefaults() {
method SetInitialConfig (line 1990) | func (i *Config) SetInitialConfig() error {
method FinalizeSetup (line 2015) | func (i *Config) FinalizeSetup() {
function GetInstance (line 356) | func GetInstance() *Config {
function FileEnvSet (line 517) | func FileEnvSet() bool {
function hashPassword (line 1161) | func hashPassword(password string) string {
function stashBoxValidate (line 1180) | func stashBoxValidate(str string) bool {
type StashBoxInput (line 1185) | type StashBoxInput struct
type packagePathGetter (line 1831) | type packagePathGetter struct
method GetAllSourcePaths (line 1835) | func (g packagePathGetter) GetAllSourcePaths() []string {
method GetSourcePath (line 1845) | func (g packagePathGetter) GetSourcePath(srcURL string) string {
FILE: internal/manager/config/config_concurrency_test.go
function TestConcurrentConfigAccess (line 10) | func TestConcurrentConfigAccess(t *testing.T) {
FILE: internal/manager/config/config_test.go
function TestConfig_GetAllPluginConfiguration (line 9) | func TestConfig_GetAllPluginConfiguration(t *testing.T) {
FILE: internal/manager/config/enums.go
type BlobsStorageType (line 9) | type BlobsStorageType
method IsValid (line 23) | func (e BlobsStorageType) IsValid() bool {
method String (line 31) | func (e BlobsStorageType) String() string {
method UnmarshalGQL (line 35) | func (e *BlobsStorageType) UnmarshalGQL(v interface{}) error {
method MarshalGQL (line 48) | func (e BlobsStorageType) MarshalGQL(w io.Writer) {
constant BlobStorageTypeDatabase (line 13) | BlobStorageTypeDatabase BlobsStorageType = "DATABASE"
constant BlobStorageTypeFilesystem (line 15) | BlobStorageTypeFilesystem BlobsStorageType = "FILESYSTEM"
FILE: internal/manager/config/init.go
type flagStruct (line 20) | type flagStruct struct
function init (line 51) | func init() {
function Initialize (line 60) | func Initialize() (*Config, error) {
function InitializeEmpty (line 104) | func InitializeEmpty() *Config {
method loadFromCommandLine (line 113) | func (i *Config) loadFromCommandLine() {
method loadFromEnv (line 128) | func (i *Config) loadFromEnv() {
method initOverrides (line 143) | func (i *Config) initOverrides() {
method initConfig (line 148) | func (i *Config) initConfig() error {
method loadFirstFromFiles (line 194) | func (i *Config) loadFirstFromFiles(f []string) error {
FILE: internal/manager/config/stash_config.go
type StashConfigInput (line 10) | type StashConfigInput struct
type StashConfig (line 16) | type StashConfig struct
type StashConfigs (line 22) | type StashConfigs
method GetStashFromPath (line 24) | func (s StashConfigs) GetStashFromPath(path string) *StashConfig {
method GetStashFromDirPath (line 33) | func (s StashConfigs) GetStashFromDirPath(dirPath string) *StashConfig {
method Paths (line 42) | func (s StashConfigs) Paths() []string {
FILE: internal/manager/config/tasks.go
type ScanMetadataOptions (line 3) | type ScanMetadataOptions struct
type AutoTagMetadataOptions (line 24) | type AutoTagMetadataOptions struct
FILE: internal/manager/config/ui.go
type ConfigImageLightboxResult (line 9) | type ConfigImageLightboxResult struct
type ImageLightboxDisplayMode (line 19) | type ImageLightboxDisplayMode
method IsValid (line 33) | func (e ImageLightboxDisplayMode) IsValid() bool {
method String (line 41) | func (e ImageLightboxDisplayMode) String() string {
method UnmarshalGQL (line 45) | func (e *ImageLightboxDisplayMode) UnmarshalGQL(v interface{}) error {
method MarshalGQL (line 58) | func (e ImageLightboxDisplayMode) MarshalGQL(w io.Writer) {
constant ImageLightboxDisplayModeOriginal (line 22) | ImageLightboxDisplayModeOriginal ImageLightboxDisplayMode = "ORIGINAL"
constant ImageLightboxDisplayModeFitXy (line 23) | ImageLightboxDisplayModeFitXy ImageLightboxDisplayMode = "FIT_XY"
constant ImageLightboxDisplayModeFitX (line 24) | ImageLightboxDisplayModeFitX ImageLightboxDisplayMode = "FIT_X"
type ImageLightboxScrollMode (line 62) | type ImageLightboxScrollMode
method IsValid (line 74) | func (e ImageLightboxScrollMode) IsValid() bool {
method String (line 82) | func (e ImageLightboxScrollMode) String() string {
method UnmarshalGQL (line 86) | func (e *ImageLightboxScrollMode) UnmarshalGQL(v interface{}) error {
method MarshalGQL (line 99) | func (e ImageLightboxScrollMode) MarshalGQL(w io.Writer) {
constant ImageLightboxScrollModeZoom (line 65) | ImageLightboxScrollModeZoom ImageLightboxScrollMode = "ZOOM"
constant ImageLightboxScrollModePanY (line 66) | ImageLightboxScrollModePanY ImageLightboxScrollMode = "PAN_Y"
type ConfigDisableDropdownCreate (line 103) | type ConfigDisableDropdownCreate struct
FILE: internal/manager/downloads.go
type DownloadStore (line 14) | type DownloadStore struct
method RegisterFile (line 33) | func (s *DownloadStore) RegisterFile(fp string, contentType string, ke...
method Serve (line 64) | func (s *DownloadStore) Serve(hash string, w http.ResponseWriter, r *h...
method waitAndRemoveFile (line 87) | func (s *DownloadStore) waitAndRemoveFile(hash string, w *http.Respons...
type storeFile (line 19) | type storeFile struct
function NewDownloadStore (line 27) | func NewDownloadStore() *DownloadStore {
FILE: internal/manager/enums.go
type SystemStatusEnum (line 9) | type SystemStatusEnum
method IsValid (line 23) | func (e SystemStatusEnum) IsValid() bool {
method String (line 31) | func (e SystemStatusEnum) String() string {
method UnmarshalGQL (line 35) | func (e *SystemStatusEnum) UnmarshalGQL(v interface{}) error {
method MarshalGQL (line 48) | func (e SystemStatusEnum) MarshalGQL(w io.Writer) {
constant SystemStatusEnumSetup (line 12) | SystemStatusEnumSetup SystemStatusEnum = "SETUP"
constant SystemStatusEnumNeedsMigration (line 13) | SystemStatusEnumNeedsMigration SystemStatusEnum = "NEEDS_MIGRATION"
constant SystemStatusEnumOk (line 14) | SystemStatusEnumOk SystemStatusEnum = "OK"
FILE: internal/manager/exclude_files.go
function excludeFiles (line 10) | func excludeFiles(files []string, patterns []string) ([]string, int) {
function matchFileRegex (line 39) | func matchFileRegex(file string, fileRegexps []*regexp.Regexp) bool {
function matchFile (line 48) | func matchFile(file string, patterns []string) bool {
function generateRegexps (line 58) | func generateRegexps(patterns []string) []*regexp.Regexp {
function matchFileSimple (line 86) | func matchFileSimple(file string, regExps []*regexp.Regexp) bool {
FILE: internal/manager/exclude_files_test.go
function TestExcludeFiles (line 53) | func TestExcludeFiles(t *testing.T) {
function runExclude (line 62) | func runExclude(filenames []string, patterns []string, expCount int) err...
function TestMatchFile (line 76) | func TestMatchFile(t *testing.T) {
function runMatch (line 85) | func runMatch(filenames []string, patterns []string, expCount int) error {
FILE: internal/manager/fingerprint.go
type fingerprintCalculator (line 16) | type fingerprintCalculator struct
method calculateOshash (line 20) | func (c *fingerprintCalculator) calculateOshash(f *models.BaseFile, o ...
method calculateMD5 (line 44) | func (c *fingerprintCalculator) calculateMD5(o file.Opener) (*models.F...
method CalculateFingerprints (line 63) | func (c *fingerprintCalculator) CalculateFingerprints(f *models.BaseFi...
FILE: internal/manager/generator.go
type generatorInfo (line 14) | type generatorInfo struct
method calculateFrameRate (line 36) | func (g *generatorInfo) calculateFrameRate(videoStream *ffmpeg.FFProbe...
method configure (line 86) | func (g *generatorInfo) configure() error {
function newGeneratorInfo (line 25) | func newGeneratorInfo(videoFile ffmpeg.VideoFile) (*generatorInfo, error) {
function isValidFloat64 (line 82) | func isValidFloat64(value float64) bool {
FILE: internal/manager/generator_interactive_heatmap_speed.go
type InteractiveHeatmapSpeedGenerator (line 19) | type InteractiveHeatmapSpeedGenerator struct
method Generate (line 66) | func (g *InteractiveHeatmapSpeedGenerator) Generate(funscriptPath stri...
method LoadFunscriptData (line 92) | func (g *InteractiveHeatmapSpeedGenerator) LoadFunscriptData(path stri...
method RenderHeatmap (line 156) | func (g *InteractiveHeatmapSpeedGenerator) RenderHeatmap(heatmapPath s...
type Script (line 29) | type Script struct
method UpdateIntensityAndSpeed (line 134) | func (funscript *Script) UpdateIntensityAndSpeed() {
method CalculateMedian (line 200) | func (funscript *Script) CalculateMedian() int {
method getGradientTable (line 243) | func (funscript Script) getGradientTable(numSegments int, sceneDuratio...
type Action (line 42) | type Action struct
type GradientTable (line 51) | type GradientTable
method GetInterpolatedColorFor (line 214) | func (gt GradientTable) GetInterpolatedColorFor(t float64) colorful.Co...
method GetYRange (line 229) | func (gt GradientTable) GetYRange(t float64) [2]float64 {
function NewInteractiveHeatmapSpeedGenerator (line 57) | func NewInteractiveHeatmapSpeedGenerator(drawRange bool) *InteractiveHea...
function getSegmentColor (line 329) | func getSegmentColor(intensity float64) colorful.Color {
function LoadFunscriptData (line 366) | func LoadFunscriptData(path string) (Script, error) {
function convertRange (line 387) | func convertRange(value int, fromLow int, fromHigh int, toLow int, toHig...
function ConvertFunscri
Copy disabled (too large)
Download .json
Condensed preview — 1651 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (11,953K chars).
[
{
"path": ".dockerignore",
"chars": 791,
"preview": "####\n# Go\n####\n\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test "
},
{
"path": ".gitattributes",
"chars": 130,
"preview": "go.mod text eol=lf\ngo.sum text eol=lf\n*.go text eol=lf\nvendor/** -text\nui/v2.5/**/*.ts* text eol=lf\nui/v2.5/**/*.scss te"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 2016,
"preview": "name: Bug Report\ndescription: Create a report to help us fix the bug\nlabels: [\"bug report\"]\nbody:\n - type: markdown\n "
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 394,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Community forum\n url: https://discourse.stashapp.cc\n about: S"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 1740,
"preview": "name: Feature Request\ndescription: Request a new feature or idea to be added to Stash\nlabels: [\"feature request\"]\nbody:\n"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE/BugFix.md",
"chars": 711,
"preview": "---\nname: Bug Fix\nabout: Add a bug fix this project!\ntitle: \"[Bug Fix] Short Form Title (50 chars or less.)\"\nlabels: bug"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE/Feature.md",
"chars": 711,
"preview": "---\nname: Feature Addition\nabout: Add a feature to this project!\ntitle: \"[Feature] Short Form Title (50 chars or less.)\""
},
{
"path": ".github/workflows/build-compiler.yml",
"chars": 717,
"preview": "name: Compiler Build\n\non:\n workflow_dispatch:\n\nenv:\n COMPILER_IMAGE: ghcr.io/stashapp/compiler:13\n\njobs:\n build-compi"
},
{
"path": ".github/workflows/build.yml",
"chars": 11600,
"preview": "name: Build\n\non:\n push:\n branches:\n - develop\n - master\n - 'releases/**'\n pull_request:\n release:\n "
},
{
"path": ".github/workflows/golangci-lint.yml",
"chars": 612,
"preview": "name: Lint (golangci-lint)\non:\n push:\n tags:\n - v*\n branches:\n - master\n - develop\n - 'releas"
},
{
"path": ".gitignore",
"chars": 873,
"preview": "####\n# Go\n####\n\n# Vendored dependencies\nvendor\n\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# T"
},
{
"path": ".golangci.yml",
"chars": 1846,
"preview": "# options for analysis running\nrun:\n timeout: 5m\n\nlinters:\n disable-all: true\n enable:\n # Default set of linters f"
},
{
"path": ".gqlgenc.yml",
"chars": 525,
"preview": "model:\n package: graphql\n filename: ./pkg/stashbox/graphql/generated_models.go\nclient:\n package: graphql\n filename: "
},
{
"path": ".idea/codeStyles/codeStyleConfig.xml",
"chars": 149,
"preview": "<component name=\"ProjectCodeStyleConfiguration\">\n <state>\n <option name=\"PREFERRED_PROJECT_CODE_STYLE\" value=\"Defaul"
},
{
"path": ".idea/dataSources.xml",
"chars": 599,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"DataSourceManagerImpl\" format=\"xml\" mult"
},
{
"path": ".idea/encodings.xml",
"chars": 135,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"Encoding\" addBOMForNewFiles=\"with NO BOM"
},
{
"path": ".idea/go.iml",
"chars": 581,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n <component name=\"Go\" enabled=\"true\" />\n "
},
{
"path": ".idea/misc.xml",
"chars": 174,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"JavaScriptSettings\">\n <option name=\"l"
},
{
"path": ".idea/modules.xml",
"chars": 256,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/sqldialects.xml",
"chars": 170,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"SqlDialectMappings\">\n <file url=\"PROJ"
},
{
"path": ".idea/vcs.xml",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": ".mockery.yml",
"chars": 82,
"preview": "dir: ./pkg/models\nname: \".*ReaderWriter\"\noutpkg: mocks\noutput: ./pkg/models/mocks\n"
},
{
"path": "LICENSE",
"chars": 34523,
"preview": " GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C)"
},
{
"path": "Makefile",
"chars": 13758,
"preview": "IS_WIN_SHELL =\nifeq (${SHELL}, sh.exe)\n IS_WIN_SHELL = true\nendif\nifeq (${SHELL}, cmd)\n IS_WIN_SHELL = true\nendif\n\nifd"
},
{
"path": "README.md",
"chars": 9108,
"preview": "# Stash\n\n[](h"
},
{
"path": "cmd/phasher/main.go",
"chars": 3042,
"preview": "// TODO: document in README.md\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\n\tflag \"github.com/spf13/"
},
{
"path": "cmd/stash/main.go",
"chars": 3650,
"preview": "//go:generate go run github.com/99designs/gqlgen\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n"
},
{
"path": "cmd/stash/main_test.go",
"chars": 65,
"preview": "package main\n\nimport \"testing\"\n\nfunc TestStub(t *testing.T) {\n\n}\n"
},
{
"path": "docker/build/x86_64/Dockerfile",
"chars": 1264,
"preview": "# This dockerfile should be built with `make docker-build` from the stash root.\n\n# Build Frontend\nFROM node:24-alpine AS"
},
{
"path": "docker/build/x86_64/Dockerfile-CUDA",
"chars": 2056,
"preview": "# This dockerfile should be built with `make docker-cuda-build` from the stash root.\nARG CUDA_VERSION=12.8.0\n\n# Build Fr"
},
{
"path": "docker/build/x86_64/README.md",
"chars": 1994,
"preview": "# Introduction\n\nThis dockerfile is used to build a stash docker container using the current source code. This is ideal f"
},
{
"path": "docker/ci/x86_64/Dockerfile",
"chars": 1354,
"preview": "FROM --platform=$BUILDPLATFORM alpine:latest AS binary\nARG TARGETPLATFORM\nWORKDIR /\nCOPY stash-* /\nRUN if [ \"$TARGETPLA"
},
{
"path": "docker/ci/x86_64/README.md",
"chars": 224,
"preview": "This Dockerfile is used by CI to build the `stashapp/stash` Docker image. It must be run after cross-compiling - that is"
},
{
"path": "docker/ci/x86_64/docker_push.sh",
"chars": 366,
"preview": "#!/bin/bash\n\nDOCKER_TAGS=\"\"\n\nfor TAG in \"$@\"\ndo\n\tDOCKER_TAGS=\"$DOCKER_TAGS -t stashapp/stash:$TAG\"\ndone\n\necho \"$DOCKER_P"
},
{
"path": "docker/compiler/Dockerfile",
"chars": 3247,
"preview": "### OSXCROSS\nFROM debian:bookworm AS osxcross\n# add osxcross\nWORKDIR /tmp/osxcross\nARG OSXCROSS_REVISION=5e1b71fcceb2395"
},
{
"path": "docker/compiler/Makefile",
"chars": 504,
"preview": "host=ghcr.io\nuser=stashapp\nrepo=compiler\nversion=13\n\nVERSION_IMAGE = ${host}/${user}/${repo}:${version}\nLATEST_IMAGE = $"
},
{
"path": "docker/compiler/README.md",
"chars": 415,
"preview": "Modified from https://github.com/bep/dockerfiles/tree/master/ci-goreleaser\n\nWhen the Dockerfile is changed, the version "
},
{
"path": "docker/production/README.md",
"chars": 2451,
"preview": "# Docker Installation (for most 64-bit GNU/Linux systems)\nStashApp is supported on most systems that support Docker. You"
},
{
"path": "docker/production/docker-compose.yml",
"chars": 1660,
"preview": "# APPNICENAME=Stash\n# APPDESCRIPTION=An organizer for your porn, written in Go\nservices:\n stash:\n image: stashapp/st"
},
{
"path": "docs/CONTRIBUTING.md",
"chars": 2849,
"preview": "## Goals and design vision\n\nThe goal of stash is to be:\n- an application for organising and viewing adult content - curr"
},
{
"path": "docs/DEVELOPMENT.md",
"chars": 7943,
"preview": "# Building from Source\n\n## Pre-requisites\n\n* [Go](https://golang.org/dl/)\n* [GolangCI](https://golangci-lint.run/) - A m"
},
{
"path": "go.mod",
"chars": 5535,
"preview": "module github.com/stashapp/stash\n\ngo 1.24.3\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.17.73\n\tgithub.com/WithoutPants/so"
},
{
"path": "go.sum",
"chars": 115074,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "gqlgen.yml",
"chars": 5736,
"preview": "# Refer to https://gqlgen.com/config/ for detailed .gqlgen.yml documentation.\n\nschema:\n - \"graphql/schema/types/*.graph"
},
{
"path": "graphql/schema/schema.graphql",
"chars": 21738,
"preview": "\"The query root for this schema\"\ntype Query {\n # Filters\n findSavedFilter(id: ID!): SavedFilter\n findSavedFilters(mod"
},
{
"path": "graphql/schema/types/config.graphql",
"chars": 18049,
"preview": "input SetupInput {\n \"Empty to indicate $HOME/.stash/config.yml default\"\n configLocation: String!\n stashes: [StashConf"
},
{
"path": "graphql/schema/types/dlna.graphql",
"chars": 719,
"preview": "type DLNAIP {\n ipAddress: String!\n \"Time until IP will be no longer allowed/disallowed\"\n until: Time\n}\n\ntype DLNAStat"
},
{
"path": "graphql/schema/types/file.graphql",
"chars": 3607,
"preview": "type Fingerprint {\n type: String!\n value: String!\n}\n\ntype Folder {\n id: ID!\n path: String!\n basename: String!\n\n pa"
},
{
"path": "graphql/schema/types/filters.graphql",
"chars": 28148,
"preview": "enum SortDirectionEnum {\n ASC\n DESC\n}\n\ninput FindFilterType {\n q: String\n page: Int\n \"use per_page = -1 to indicate"
},
{
"path": "graphql/schema/types/gallery-chapter.graphql",
"chars": 407,
"preview": "type GalleryChapter {\n id: ID!\n gallery: Gallery!\n title: String!\n image_index: Int!\n created_at: Time!\n updated_a"
},
{
"path": "graphql/schema/types/gallery.graphql",
"chars": 2638,
"preview": "type GalleryPathsType {\n cover: String!\n preview: String! # Resolver\n}\n\n\"Gallery type\"\ntype Gallery {\n id: ID!\n titl"
},
{
"path": "graphql/schema/types/group.graphql",
"chars": 3299,
"preview": "\"GroupDescription represents a relationship to a group with a description of the relationship\"\ntype GroupDescription {\n "
},
{
"path": "graphql/schema/types/image.graphql",
"chars": 2212,
"preview": "type Image {\n id: ID!\n title: String\n code: String\n # rating expressed as 1-100\n rating100: Int\n url: String @depr"
},
{
"path": "graphql/schema/types/job.graphql",
"chars": 410,
"preview": "enum JobStatus {\n READY\n RUNNING\n FINISHED\n STOPPING\n CANCELLED\n FAILED\n}\n\ntype Job {\n id: ID!\n status: JobStatu"
},
{
"path": "graphql/schema/types/logging.graphql",
"chars": 141,
"preview": "enum LogLevel {\n Trace\n Debug\n Info\n Progress\n Warning\n Error\n}\n\ntype LogEntry {\n time: Time!\n level: LogLevel!\n"
},
{
"path": "graphql/schema/types/metadata.graphql",
"chars": 10350,
"preview": "input GenerateMetadataInput {\n covers: Boolean\n sprites: Boolean\n previews: Boolean\n imagePreviews: Boolean\n previe"
},
{
"path": "graphql/schema/types/migration.graphql",
"chars": 334,
"preview": "input MigrateSceneScreenshotsInput {\n # if true, delete screenshot files after migrating\n deleteFiles: Boolean\n # if "
},
{
"path": "graphql/schema/types/movie.graphql",
"chars": 1670,
"preview": "type Movie {\n id: ID!\n name: String!\n aliases: String\n \"Duration in seconds\"\n duration: Int\n date: String\n # rati"
},
{
"path": "graphql/schema/types/package.graphql",
"chars": 517,
"preview": "enum PackageType {\n Scraper\n Plugin\n}\n\ntype Package {\n package_id: String!\n name: String!\n version: String\n date: "
},
{
"path": "graphql/schema/types/performer.graphql",
"chars": 4875,
"preview": "enum GenderEnum {\n MALE\n FEMALE\n TRANSGENDER_MALE\n TRANSGENDER_FEMALE\n INTERSEX\n NON_BINARY\n}\n\nenum CircumcisedEnu"
},
{
"path": "graphql/schema/types/plugin.graphql",
"chars": 1078,
"preview": "type PluginPaths {\n # path to javascript files\n javascript: [String!]\n # path to css files\n css: [String!]\n}\n\ntype P"
},
{
"path": "graphql/schema/types/scalars.graphql",
"chars": 472,
"preview": "\"An RFC3339 timestamp\"\nscalar Time\n\n\"\"\"\nTimestamp is a point in time. It is always output as RFC3339-compatible time poi"
},
{
"path": "graphql/schema/types/scene-marker-tag.graphql",
"chars": 69,
"preview": "type SceneMarkerTag {\n tag: Tag!\n scene_markers: [SceneMarker!]!\n}\n"
},
{
"path": "graphql/schema/types/scene-marker.graphql",
"chars": 1404,
"preview": "type SceneMarker {\n id: ID!\n scene: Scene!\n title: String!\n \"The required start time of the marker (in seconds). Sup"
},
{
"path": "graphql/schema/types/scene.graphql",
"chars": 6216,
"preview": "type SceneFileType {\n size: String\n duration: Float\n video_codec: String\n audio_codec: String\n width: Int\n height:"
},
{
"path": "graphql/schema/types/scraped-group.graphql",
"chars": 1299,
"preview": "\"A movie from a scraping operation...\"\ntype ScrapedMovie {\n stored_id: ID\n name: String\n aliases: String\n duration: "
},
{
"path": "graphql/schema/types/scraped-performer.graphql",
"chars": 1847,
"preview": "\"A performer from a scraping operation...\"\ntype ScrapedPerformer {\n \"Set if performer matched\"\n stored_id: ID\n name: "
},
{
"path": "graphql/schema/types/scraper.graphql",
"chars": 7491,
"preview": "enum ScrapeType {\n \"From text query\"\n NAME\n \"From existing object\"\n FRAGMENT\n \"From URL\"\n URL\n}\n\n\"Type of the cont"
},
{
"path": "graphql/schema/types/sql.graphql",
"chars": 616,
"preview": "type SQLQueryResult {\n \"The column names, in the order they appear in the result set.\"\n columns: [String!]!\n \"The ret"
},
{
"path": "graphql/schema/types/stash-box.graphql",
"chars": 717,
"preview": "type StashBox {\n endpoint: String!\n api_key: String!\n name: String!\n max_requests_per_minute: Int!\n}\n\ninput StashBox"
},
{
"path": "graphql/schema/types/stats.graphql",
"chars": 406,
"preview": "type StatsResultType {\n scene_count: Int!\n scenes_size: Float!\n scenes_duration: Float!\n image_count: Int!\n images_"
},
{
"path": "graphql/schema/types/studio.graphql",
"chars": 2284,
"preview": "type Studio {\n id: ID!\n name: String!\n url: String @deprecated(reason: \"Use urls\")\n urls: [String!]!\n parent_studio"
},
{
"path": "graphql/schema/types/tag.graphql",
"chars": 2339,
"preview": "type Tag {\n id: ID!\n name: String!\n \"Value that does not appear in the UI but overrides name for sorting\"\n sort_name"
},
{
"path": "graphql/schema/types/version.graphql",
"chars": 176,
"preview": "type Version {\n version: String\n hash: String!\n build_time: String!\n}\n\ntype LatestVersion {\n version: String!\n shor"
},
{
"path": "graphql/stash-box/query.graphql",
"chars": 2811,
"preview": "fragment URLFragment on URL {\n url\n type\n}\n\nfragment ImageFragment on Image {\n id\n url\n width\n height\n}\n\nfragment "
},
{
"path": "internal/api/authentication.go",
"chars": 3526,
"preview": "package api\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/m"
},
{
"path": "internal/api/bool_map.go",
"chars": 660,
"preview": "package api\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n)\n\nfunc MarshalBoolMap(val m"
},
{
"path": "internal/api/changeset_translator.go",
"chars": 11820,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\n\t\"github.com/stas"
},
{
"path": "internal/api/check_version.go",
"chars": 7950,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"string"
},
{
"path": "internal/api/context_keys.go",
"chars": 265,
"preview": "package api\n\n// https://stackoverflow.com/questions/40891345/fix-should-not-use-basic-type-string-as-key-in-context-with"
},
{
"path": "internal/api/custom_fields.go",
"chars": 310,
"preview": "package api\n\nimport \"github.com/stashapp/stash/pkg/models\"\n\nfunc handleUpdateCustomFields(input models.CustomFieldsInput"
},
{
"path": "internal/api/dir_list.go",
"chars": 1244,
"preview": "package api\n\nimport (\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/text/collate\"\n)\n\ntype dirLister []fs.Di"
},
{
"path": "internal/api/doc.go",
"chars": 82,
"preview": "// Package api provides the HTTP and Graphql API for the application.\npackage api\n"
},
{
"path": "internal/api/error.go",
"chars": 956,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/stashap"
},
{
"path": "internal/api/fields.go",
"chars": 359,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n)\n\ntype queryFields []string\n\nfunc collectQuery"
},
{
"path": "internal/api/images.go",
"chars": 2844,
"preview": "package api\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/static\"\n\t\"g"
},
{
"path": "internal/api/input.go",
"chars": 871,
"preview": "package api\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/stashapp/stash/pkg/sliceutil/stringslice\"\n)\n\n// TODO - apply handleIDs to oth"
},
{
"path": "internal/api/json.go",
"chars": 1551,
"preview": "package api\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\n// jsonNumberToNumber conv"
},
{
"path": "internal/api/json_test.go",
"chars": 1305,
"preview": "package api\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestConvertMapJSONNumbe"
},
{
"path": "internal/api/loaders/customfieldsloader_gen.go",
"chars": 5898,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/dataloaders.go",
"chars": 16741,
"preview": "// Package loaders contains the dataloaders used by the resolver in [api].\n// They are generated with `make generate-dat"
},
{
"path": "internal/api/loaders/fileloader_gen.go",
"chars": 5532,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/folderloader_gen.go",
"chars": 5857,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/folderparentfolderidsloader_gen.go",
"chars": 6384,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/galleryfileidsloader_gen.go",
"chars": 5981,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/galleryloader_gen.go",
"chars": 5756,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/grouploader_gen.go",
"chars": 5646,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/imagefileidsloader_gen.go",
"chars": 5927,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/imageloader_gen.go",
"chars": 5646,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/performerloader_gen.go",
"chars": 5866,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/scenefileidsloader_gen.go",
"chars": 5927,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/scenelastplayedloader_gen.go",
"chars": 5809,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// SceneLa"
},
{
"path": "internal/api/loaders/sceneloader_gen.go",
"chars": 5646,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/sceneocountloader_gen.go",
"chars": 5389,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// SceneOC"
},
{
"path": "internal/api/loaders/sceneohistoryloader_gen.go",
"chars": 5815,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// SceneOH"
},
{
"path": "internal/api/loaders/sceneplaycountloader_gen.go",
"chars": 5470,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// ScenePl"
},
{
"path": "internal/api/loaders/sceneplayhistoryloader_gen.go",
"chars": 5896,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// ScenePl"
},
{
"path": "internal/api/loaders/studioloader_gen.go",
"chars": 5701,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/loaders/tagloader_gen.go",
"chars": 5536,
"preview": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage loaders\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "internal/api/locale.go",
"chars": 1499,
"preview": "package api\n\nimport (\n\t\"golang.org/x/text/collate\"\n\t\"golang.org/x/text/language\"\n)\n\n// matcher defines a matcher for the"
},
{
"path": "internal/api/models.go",
"chars": 1838,
"preview": "package api\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stashapp/stash/pkg/sliceutil\"\n)\n\ntype"
},
{
"path": "internal/api/plugin_map.go",
"chars": 748,
"preview": "package api\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n)\n\nfunc MarshalPluginConfigM"
},
{
"path": "internal/api/resolver.go",
"chars": 10812,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/build\"\n\t\"gith"
},
{
"path": "internal/api/resolver_model_config.go",
"chars": 542,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/manager/config\"\n)\n\nfunc (r *configResultResolver)"
},
{
"path": "internal/api/resolver_model_file.go",
"chars": 2578,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/stash/pkg/mode"
},
{
"path": "internal/api/resolver_model_folder.go",
"chars": 964,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"path/filepath\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stasha"
},
{
"path": "internal/api/resolver_model_gallery.go",
"chars": 5888,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/stash/i"
},
{
"path": "internal/api/resolver_model_gallery_chapter.go",
"chars": 397,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *galleryChapterResolver) Gallery(ct"
},
{
"path": "internal/api/resolver_model_image.go",
"chars": 4376,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/stash/internal"
},
{
"path": "internal/api/resolver_model_movie.go",
"chars": 6175,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/stash/internal"
},
{
"path": "internal/api/resolver_model_performer.go",
"chars": 8340,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/sta"
},
{
"path": "internal/api/resolver_model_plugin.go",
"chars": 1205,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/pkg/plugin\"\n)\n\ntype pluginURLBuilder struct {\n\tBaseURL str"
},
{
"path": "internal/api/resolver_model_saved_filter.go",
"chars": 196,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *savedFilterResolver) Filter(ctx co"
},
{
"path": "internal/api/resolver_model_scene.go",
"chars": 10540,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp"
},
{
"path": "internal/api/resolver_model_scene_marker.go",
"chars": 1770,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/api/urlbuilders\"\n\t\"github.com/stashapp/stash/pkg/"
},
{
"path": "internal/api/resolver_model_studio.go",
"chars": 6299,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/stash/internal"
},
{
"path": "internal/api/resolver_model_tag.go",
"chars": 5579,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/api/loaders\"\n\t\"github.com/stashapp/stash/internal"
},
{
"path": "internal/api/resolver_mutation_configure.go",
"chars": 22753,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\n\t\"git"
},
{
"path": "internal/api/resolver_mutation_dlna.go",
"chars": 1110,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n)\n\nfunc (r *mutationResolver) En"
},
{
"path": "internal/api/resolver_mutation_file.go",
"chars": 10796,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/desktop\"\n\t\"github.com/stashapp/"
},
{
"path": "internal/api/resolver_mutation_gallery.go",
"chars": 19781,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/mana"
},
{
"path": "internal/api/resolver_mutation_group.go",
"chars": 13567,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/static\"\n\t\"github.com"
},
{
"path": "internal/api/resolver_mutation_image.go",
"chars": 13477,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/"
},
{
"path": "internal/api/resolver_mutation_job.go",
"chars": 504,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n)\n\nfunc (r *mutationRe"
},
{
"path": "internal/api/resolver_mutation_metadata.go",
"chars": 5613,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/stashapp/stash/internal/identify\"\n\t\"git"
},
{
"path": "internal/api/resolver_mutation_migrate.go",
"chars": 1593,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/i"
},
{
"path": "internal/api/resolver_mutation_movie.go",
"chars": 9324,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/static\"\n\t\"github.com"
},
{
"path": "internal/api/resolver_mutation_package.go",
"chars": 1971,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/i"
},
{
"path": "internal/api/resolver_mutation_performer.go",
"chars": 22834,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/pkg/model"
},
{
"path": "internal/api/resolver_mutation_plugin.go",
"chars": 2519,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/i"
},
{
"path": "internal/api/resolver_mutation_saved_filter.go",
"chars": 2639,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/mitchellh/mapstructure\"\n\t\"github.c"
},
{
"path": "internal/api/resolver_mutation_scene.go",
"chars": 36743,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/stashapp/stash/internal/ma"
},
{
"path": "internal/api/resolver_mutation_scraper.go",
"chars": 227,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n)\n\nfunc (r *mutationResolver) ReloadScra"
},
{
"path": "internal/api/resolver_mutation_stash_box.go",
"chars": 5537,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/"
},
{
"path": "internal/api/resolver_mutation_studio.go",
"chars": 10067,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stas"
},
{
"path": "internal/api/resolver_mutation_tag.go",
"chars": 10780,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stas"
},
{
"path": "internal/api/resolver_mutation_tag_test.go",
"chars": 2949,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stashapp/sta"
},
{
"path": "internal/api/resolver_query_configuration.go",
"chars": 10776,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/manager/config"
},
{
"path": "internal/api/resolver_query_dlna.go",
"chars": 264,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/dlna\"\n\t\"github.com/stashapp/stash/internal/manage"
},
{
"path": "internal/api/resolver_query_find_file.go",
"chars": 2685,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stashapp/sta"
},
{
"path": "internal/api/resolver_query_find_folder.go",
"chars": 2042,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver"
},
{
"path": "internal/api/resolver_query_find_gallery.go",
"chars": 1528,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindGall"
},
{
"path": "internal/api/resolver_query_find_group.go",
"chars": 1205,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindGrou"
},
{
"path": "internal/api/resolver_query_find_image.go",
"chars": 2831,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"slices\"\n\t\"strconv\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/stashapp/stas"
},
{
"path": "internal/api/resolver_query_find_movie.go",
"chars": 1473,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindMovi"
},
{
"path": "internal/api/resolver_query_find_performer.go",
"chars": 1818,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindPerf"
},
{
"path": "internal/api/resolver_query_find_saved_filter.go",
"chars": 1762,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/mitchellh/mapstructure\"\n\t\"github.com/stashapp/stash"
},
{
"path": "internal/api/resolver_query_find_scene.go",
"chars": 5759,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"slices\"\n\t\"strconv\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\n\t\"github.com/stashapp/sta"
},
{
"path": "internal/api/resolver_query_find_scene_marker.go",
"chars": 1221,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindSceneMarkers(ct"
},
{
"path": "internal/api/resolver_query_find_studio.go",
"chars": 1511,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindStud"
},
{
"path": "internal/api/resolver_query_find_tag.go",
"chars": 1469,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\nfunc (r *queryResolver) FindTag("
},
{
"path": "internal/api/resolver_query_job.go",
"chars": 1008,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/p"
},
{
"path": "internal/api/resolver_query_logs.go",
"chars": 443,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n)\n\nfunc (r *queryResolver) Logs(ctx cont"
},
{
"path": "internal/api/resolver_query_metadata.go",
"chars": 229,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n)\n\nfunc (r *queryResolver) SystemStatus("
},
{
"path": "internal/api/resolver_query_package.go",
"chars": 4300,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t"
},
{
"path": "internal/api/resolver_query_plugin.go",
"chars": 424,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/pkg/plugin\"\n"
},
{
"path": "internal/api/resolver_query_scene.go",
"chars": 1073,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/api/urlbuilders\"\n\t\"github.com/s"
},
{
"path": "internal/api/resolver_query_scraper.go",
"chars": 15654,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/match\"\n\t\"github."
},
{
"path": "internal/api/resolver_subscription_job.go",
"chars": 1041,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/pkg/job\"\n)\n\n"
},
{
"path": "internal/api/resolver_subscription_logging.go",
"chars": 1183,
"preview": "package api\n\nimport (\n\t\"context\"\n\n\t\"github.com/stashapp/stash/internal/log\"\n\t\"github.com/stashapp/stash/internal/manager"
},
{
"path": "internal/api/routes.go",
"chars": 251,
"preview": "package api\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/stashapp/stash/pkg/txn\"\n)\n\ntype routes struct {\n\ttxnManager txn.Manager\n"
},
{
"path": "internal/api/routes_custom.go",
"chars": 893,
"preview": "package api\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/go-chi/chi/v5\"\n\t\"github.com/stashapp/stash/pkg/utils\"\n)\n\ntype"
},
{
"path": "internal/api/routes_downloads.go",
"chars": 886,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stashapp/stash/internal/manager\""
},
{
"path": "internal/api/routes_gallery.go",
"chars": 4065,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stashapp/st"
},
{
"path": "internal/api/routes_group.go",
"chars": 2745,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stashapp/st"
},
{
"path": "internal/api/routes_image.go",
"chars": 5621,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/go-chi/chi/v"
},
{
"path": "internal/api/routes_performer.go",
"chars": 2103,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stashapp/st"
},
{
"path": "internal/api/routes_plugin.go",
"chars": 2383,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stas"
},
{
"path": "internal/api/routes_scene.go",
"chars": 17831,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"gi"
},
{
"path": "internal/api/routes_studio.go",
"chars": 1960,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stashapp/st"
},
{
"path": "internal/api/routes_tag.go",
"chars": 1873,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/stashapp/st"
},
{
"path": "internal/api/scraped_content.go",
"chars": 5709,
"preview": "package api\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stashapp/stash/pkg/scraper\"\n)\n\n// mar"
},
{
"path": "internal/api/server.go",
"chars": 18351,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"path"
},
{
"path": "internal/api/session.go",
"chars": 4269,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/stashapp/"
},
{
"path": "internal/api/stash_box.go",
"chars": 1305,
"preview": "package api\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/inter"
},
{
"path": "internal/api/timestamp.go",
"chars": 1210,
"preview": "package api\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/sta"
},
{
"path": "internal/api/timestamp_test.go",
"chars": 1893,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestTimestampSymmetry(t *testing.T) {\n\tn := time.No"
},
{
"path": "internal/api/types.go",
"chars": 213,
"preview": "package api\n\nimport (\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stashapp/stash/pkg/sliceutil\"\n)\n\nfunc stashID"
},
{
"path": "internal/api/urlbuilders/doc.go",
"chars": 104,
"preview": "// Package urlbuilders provides the builders used to build URLs to pass to clients.\npackage urlbuilders\n"
},
{
"path": "internal/api/urlbuilders/gallery.go",
"chars": 657,
"preview": "package urlbuilders\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\ntype GalleryURLBuilder struct {\n\tBa"
},
{
"path": "internal/api/urlbuilders/group.go",
"chars": 739,
"preview": "package urlbuilders\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\ntype GroupURLBuilder struct {\n\tBase"
},
{
"path": "internal/api/urlbuilders/image.go",
"chars": 1090,
"preview": "package urlbuilders\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/internal/manager\"\n\t\"github.com/stashapp/stash/pkg/"
},
{
"path": "internal/api/urlbuilders/performer.go",
"chars": 655,
"preview": "package urlbuilders\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\ntype PerformerURLBuilder struct {\n\t"
},
{
"path": "internal/api/urlbuilders/scene.go",
"chars": 1683,
"preview": "package urlbuilders\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\ntype SceneURLBuil"
},
{
"path": "internal/api/urlbuilders/scene_markers.go",
"chars": 866,
"preview": "package urlbuilders\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\ntype SceneMarkerURLBuilder struct {"
},
{
"path": "internal/api/urlbuilders/studio.go",
"chars": 607,
"preview": "package urlbuilders\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n)\n\ntype StudioURLBuilder struct {\n\tBas"
},
{
"path": "internal/api/urlbuilders/tag.go",
"chars": 570,
"preview": "package urlbuilders\n\nimport (\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"strconv\"\n)\n\ntype TagURLBuilder struct {\n\tBaseURL"
},
{
"path": "internal/autotag/doc.go",
"chars": 514,
"preview": "// Package autotag provides the autotagging functionality for the application.\n//\n// The autotag functionality sets medi"
},
{
"path": "internal/autotag/gallery.go",
"chars": 2688,
"preview": "package autotag\n\nimport (\n\t\"context\"\n\t\"slices\"\n\n\t\"github.com/stashapp/stash/pkg/gallery\"\n\t\"github.com/stashapp/stash/pkg"
},
{
"path": "internal/autotag/gallery_test.go",
"chars": 6179,
"preview": "package autotag\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/stashapp/stash/pkg/models\"\n\t\"github.com/stashapp/stash/pkg"
}
]
// ... and 1451 more files (download for full content)
About this extraction
This page contains the full source code of the stashapp/stash GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1651 files (10.5 MB), approximately 2.8M tokens, and a symbol index with 12481 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.