mirror of
https://github.com/stashapp/stash.git
synced 2026-06-15 07:41:37 -05:00
Compare commits
6 Commits
update-con
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c797d2147f | ||
|
|
631abda07a | ||
|
|
690782e1f5 | ||
|
|
26072e2b37 | ||
|
|
0ce36f678a | ||
|
|
8bd34dd002 |
3
.github/CODEOWNERS
vendored
Normal file
3
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/ui/v2.5/src/docs/en/Manual/ @DogmaDragon
|
||||||
|
/docs/ @DogmaDragon
|
||||||
|
README.md @DogmaDragon
|
||||||
2
go.mod
2
go.mod
@@ -115,7 +115,7 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/quic-go/qpack v0.6.0 // indirect
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
github.com/quic-go/quic-go v0.59.1 // indirect
|
||||||
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af // indirect
|
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af // indirect
|
||||||
github.com/rs/zerolog v1.30.0 // indirect
|
github.com/rs/zerolog v1.30.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -534,8 +534,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
|
|||||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic=
|
||||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
github.com/quic-go/quic-go v0.59.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||||
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af h1:er2acxbi3N1nvEq6HXHUAR1nTWEJmQfqiGR8EVT9rfs=
|
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af h1:er2acxbi3N1nvEq6HXHUAR1nTWEJmQfqiGR8EVT9rfs=
|
||||||
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
||||||
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
|
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/Yamashou/gqlgenc/clientv2"
|
"github.com/Yamashou/gqlgenc/clientv2"
|
||||||
|
"github.com/stashapp/stash/internal/build"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/scraper"
|
"github.com/stashapp/stash/pkg/scraper"
|
||||||
"github.com/stashapp/stash/pkg/stashbox/graphql"
|
"github.com/stashapp/stash/pkg/stashbox/graphql"
|
||||||
@@ -52,6 +53,23 @@ func setApiKeyHeader(apiKey string) clientv2.RequestInterceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setUserAgentHeader() clientv2.RequestInterceptor {
|
||||||
|
version, githash, _ := build.Version()
|
||||||
|
v := version
|
||||||
|
if v == "" {
|
||||||
|
v = githash
|
||||||
|
}
|
||||||
|
if v == "" {
|
||||||
|
v = "unknown"
|
||||||
|
}
|
||||||
|
ua := "stash/" + v
|
||||||
|
|
||||||
|
return func(ctx context.Context, req *http.Request, gqlInfo *clientv2.GQLRequestInfo, res interface{}, next clientv2.RequestInterceptorFunc) error {
|
||||||
|
req.Header.Set("User-Agent", ua)
|
||||||
|
return next(ctx, req, gqlInfo, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func rateLimit(n int) clientv2.RequestInterceptor {
|
func rateLimit(n int) clientv2.RequestInterceptor {
|
||||||
perSec := float64(n) / 60
|
perSec := float64(n) / 60
|
||||||
limiter := rate.NewLimiter(rate.Limit(perSec), 1)
|
limiter := rate.NewLimiter(rate.Limit(perSec), 1)
|
||||||
@@ -83,10 +101,11 @@ func NewClient(box models.StashBox, options ...ClientOption) *Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
authHeader := setApiKeyHeader(box.APIKey)
|
authHeader := setApiKeyHeader(box.APIKey)
|
||||||
|
userAgentHeader := setUserAgentHeader()
|
||||||
limitRequests := rateLimit(ret.maxRequestsPerMinute)
|
limitRequests := rateLimit(ret.maxRequestsPerMinute)
|
||||||
|
|
||||||
client := &graphql.Client{
|
client := &graphql.Client{
|
||||||
Client: clientv2.NewClient(ret.httpClient, box.Endpoint, nil, authHeader, limitRequests),
|
Client: clientv2.NewClient(ret.httpClient, box.Endpoint, nil, authHeader, userAgentHeader, limitRequests),
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.client = client
|
ret.client = client
|
||||||
|
|||||||
@@ -1068,8 +1068,8 @@ ul.selectable-list {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
bottom: $navbar-height;
|
bottom: $navbar-height;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
pointer-events: none;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
width: fit-content;
|
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm) {
|
@include media-breakpoint-up(sm) {
|
||||||
@@ -1080,6 +1080,7 @@ ul.selectable-list {
|
|||||||
.pagination-footer {
|
.pagination-footer {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 0.5rem 1rem 0.75rem;
|
padding: 0.5rem 1rem 0.75rem;
|
||||||
|
pointer-events: auto;
|
||||||
|
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
|
||||||
|
|||||||
@@ -838,13 +838,16 @@ export const PerformerTagger: React.FC<ITaggerProps> = ({ performers }) => {
|
|||||||
const selectedEndpoint =
|
const selectedEndpoint =
|
||||||
stashConfig?.general.stashBoxes[selectedEndpointIndex];
|
stashConfig?.general.stashBoxes[selectedEndpointIndex];
|
||||||
|
|
||||||
const selectedEndpointInput = useMemo(
|
const selectedEndpointInput = useMemo(() => {
|
||||||
() => ({
|
if (!selectedEndpoint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
endpoint: selectedEndpoint.endpoint,
|
endpoint: selectedEndpoint.endpoint,
|
||||||
index: selectedEndpointIndex,
|
index: selectedEndpointIndex,
|
||||||
}),
|
};
|
||||||
[selectedEndpoint, selectedEndpointIndex]
|
}, [selectedEndpoint, selectedEndpointIndex]);
|
||||||
);
|
|
||||||
|
|
||||||
if (!config) return <LoadingIndicator />;
|
if (!config) return <LoadingIndicator />;
|
||||||
|
|
||||||
@@ -931,7 +934,7 @@ export const PerformerTagger: React.FC<ITaggerProps> = ({ performers }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedEndpointIndex === -1 || !selectedEndpoint) {
|
if (selectedEndpointIndex === -1 || !selectedEndpointInput) {
|
||||||
return (
|
return (
|
||||||
<div className="my-4">
|
<div className="my-4">
|
||||||
<h3 className="text-center mt-4">
|
<h3 className="text-center mt-4">
|
||||||
|
|||||||
@@ -520,13 +520,16 @@ export const StudioTagger: React.FC<ITaggerProps> = ({ studios }) => {
|
|||||||
const selectedEndpoint =
|
const selectedEndpoint =
|
||||||
stashConfig?.general.stashBoxes[selectedEndpointIndex];
|
stashConfig?.general.stashBoxes[selectedEndpointIndex];
|
||||||
|
|
||||||
const selectedEndpointInput = useMemo(
|
const selectedEndpointInput = useMemo(() => {
|
||||||
() => ({
|
if (!selectedEndpoint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
endpoint: selectedEndpoint.endpoint,
|
endpoint: selectedEndpoint.endpoint,
|
||||||
index: selectedEndpointIndex,
|
index: selectedEndpointIndex,
|
||||||
}),
|
};
|
||||||
[selectedEndpoint, selectedEndpointIndex]
|
}, [selectedEndpoint, selectedEndpointIndex]);
|
||||||
);
|
|
||||||
|
|
||||||
if (!config) return <LoadingIndicator />;
|
if (!config) return <LoadingIndicator />;
|
||||||
|
|
||||||
@@ -612,7 +615,7 @@ export const StudioTagger: React.FC<ITaggerProps> = ({ studios }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedEndpointIndex === -1 || !selectedEndpoint) {
|
if (selectedEndpointIndex === -1 || !selectedEndpointInput) {
|
||||||
return (
|
return (
|
||||||
<div className="my-4">
|
<div className="my-4">
|
||||||
<h3 className="text-center mt-4">
|
<h3 className="text-center mt-4">
|
||||||
|
|||||||
@@ -534,13 +534,16 @@ export const TagTagger: React.FC<ITaggerProps> = ({ tags }) => {
|
|||||||
const selectedEndpoint =
|
const selectedEndpoint =
|
||||||
stashConfig?.general.stashBoxes[selectedEndpointIndex];
|
stashConfig?.general.stashBoxes[selectedEndpointIndex];
|
||||||
|
|
||||||
const selectedEndpointInput = useMemo(
|
const selectedEndpointInput = useMemo(() => {
|
||||||
() => ({
|
if (!selectedEndpoint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
endpoint: selectedEndpoint.endpoint,
|
endpoint: selectedEndpoint.endpoint,
|
||||||
index: selectedEndpointIndex,
|
index: selectedEndpointIndex,
|
||||||
}),
|
};
|
||||||
[selectedEndpoint, selectedEndpointIndex]
|
}, [selectedEndpoint, selectedEndpointIndex]);
|
||||||
);
|
|
||||||
|
|
||||||
if (!config) return <LoadingIndicator />;
|
if (!config) return <LoadingIndicator />;
|
||||||
|
|
||||||
@@ -619,7 +622,7 @@ export const TagTagger: React.FC<ITaggerProps> = ({ tags }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedEndpointIndex === -1 || !selectedEndpoint) {
|
if (selectedEndpointIndex === -1 || !selectedEndpointInput) {
|
||||||
return (
|
return (
|
||||||
<div className="my-4">
|
<div className="my-4">
|
||||||
<h3 className="text-center mt-4">
|
<h3 className="text-center mt-4">
|
||||||
|
|||||||
@@ -91,7 +91,9 @@ Enter the URL in the `edit` tab of an Item. If a scraper is installed that suppo
|
|||||||
|
|
||||||
## Tagger view
|
## Tagger view
|
||||||
|
|
||||||
The Tagger view is accessed from the scenes page. It allows the user to run scrapers on all items on the current page. The Tagger presents the user with potential matches for an item from a selected stash-box instance or metadata source if supported. The user needs to select the correct metadata information to save.
|
The Tagger view is available from supported list pages. Scenes can use stash-boxes and compatible metadata scrapers. Performers, studios, and tags use a configured stash-box instance.
|
||||||
|
|
||||||
|
The Tagger presents the user with potential matches for an item from a selected stash-box instance or metadata source if supported. The user needs to select the correct metadata information to save.
|
||||||
|
|
||||||
When used in combination with stash-box, the user can optionally submit scene fingerprints to contribute to a stash-box instance. A scene fingerprint consists of any generated hashes (`phash`, `oshash`, `md5`) and the scene duration. Fingerprint submissions are associated with your stash-box account. Submitting fingerprints assists others in matching their files, because stash-box returns a count of matching user submitted fingerprints with every potential match.
|
When used in combination with stash-box, the user can optionally submit scene fingerprints to contribute to a stash-box instance. A scene fingerprint consists of any generated hashes (`phash`, `oshash`, `md5`) and the scene duration. Fingerprint submissions are associated with your stash-box account. Submitting fingerprints assists others in matching their files, because stash-box returns a count of matching user submitted fingerprints with every potential match.
|
||||||
|
|
||||||
@@ -99,8 +101,11 @@ When used in combination with stash-box, the user can optionally submit scene fi
|
|||||||
|---|:---:|:---:|
|
|---|:---:|:---:|
|
||||||
| gallery | | |
|
| gallery | | |
|
||||||
| group | | |
|
| group | | |
|
||||||
|
| image | | |
|
||||||
| performer | ✔️ | |
|
| performer | ✔️ | |
|
||||||
| scene | ✔️ | ✔️ |
|
| scene | ✔️ | ✔️ |
|
||||||
|
| studio | ✔️ | |
|
||||||
|
| tag | ✔️ | |
|
||||||
|
|
||||||
## Identify task
|
## Identify task
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user