Compare commits

..

6 Commits

Author SHA1 Message Date
DogmaDragon
c797d2147f Create CODEOWNERS 2026-06-15 12:18:31 +03:00
InfiniteStash
631abda07a Add User-Agent header for stash-box requests (#7034) 2026-06-15 12:10:05 +10:00
dependabot[bot]
690782e1f5 Bump github.com/quic-go/quic-go from 0.59.0 to 0.59.1 (#6994)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.59.0 to 0.59.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.59.0...v0.59.1)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.59.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 10:31:40 +10:00
CynicalAtropos
26072e2b37 Fix: Tagger view UI crash without Stash-Box Config(#7042) 2026-06-14 17:19:48 -07:00
DogmaDragon
0ce36f678a Document pull request limit and bounty discussion requirement (#7027)
* Add guidelines for bounty pull requests in CONTRIBUTING.md

* Update CONTRIBUTING.md to clarify pull request limit

* Add exception mention
2026-06-14 16:52:13 -07:00
CynicalAtropos
8bd34dd002 Fix: Pagination Footer Centering With Sidebar (#7041) 2026-06-14 16:51:24 -07:00
9 changed files with 61 additions and 24 deletions

3
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,3 @@
/ui/v2.5/src/docs/en/Manual/ @DogmaDragon
/docs/ @DogmaDragon
README.md @DogmaDragon

2
go.mod
View File

@@ -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
View File

@@ -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=

View File

@@ -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

View File

@@ -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;

View File

@@ -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">

View File

@@ -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">

View File

@@ -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">

View File

@@ -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