mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Feature: Add Various Scraper Fields (#6249)
* Support aliases in stashbox studio query --------- Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
parent
b2c8f09585
commit
a08d2e258a
9 changed files with 105 additions and 8 deletions
|
|
@ -59,6 +59,10 @@ type ScrapedStudio {
|
||||||
urls: [String!]
|
urls: [String!]
|
||||||
parent: ScrapedStudio
|
parent: ScrapedStudio
|
||||||
image: String
|
image: String
|
||||||
|
details: String
|
||||||
|
"Aliases must be comma-delimited to be parsed correctly"
|
||||||
|
aliases: String
|
||||||
|
tags: [ScrapedTag!]
|
||||||
|
|
||||||
remote_site_id: String
|
remote_site_id: String
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ fragment ImageFragment on Image {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
...URLFragment
|
...URLFragment
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ type ScrapedStudio struct {
|
||||||
Parent *ScrapedStudio `json:"parent"`
|
Parent *ScrapedStudio `json:"parent"`
|
||||||
Image *string `json:"image"`
|
Image *string `json:"image"`
|
||||||
Images []string `json:"images"`
|
Images []string `json:"images"`
|
||||||
|
Details *string `json:"details"`
|
||||||
|
Aliases *string `json:"aliases"`
|
||||||
|
Tags []*ScrapedTag `json:"tags"`
|
||||||
RemoteSiteID *string `json:"remote_site_id"`
|
RemoteSiteID *string `json:"remote_site_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +58,14 @@ func (s *ScrapedStudio) ToStudio(endpoint string, excluded map[string]bool) *Stu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.Details != nil && !excluded["details"] {
|
||||||
|
ret.Details = *s.Details
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Aliases != nil && !excluded["aliases"] {
|
||||||
|
ret.Aliases = NewRelatedStrings(stringslice.FromString(*s.Aliases, ","))
|
||||||
|
}
|
||||||
|
|
||||||
if s.Parent != nil && s.Parent.StoredID != nil && !excluded["parent"] && !excluded["parent_studio"] {
|
if s.Parent != nil && s.Parent.StoredID != nil && !excluded["parent"] && !excluded["parent_studio"] {
|
||||||
parentId, _ := strconv.Atoi(*s.Parent.StoredID)
|
parentId, _ := strconv.Atoi(*s.Parent.StoredID)
|
||||||
ret.ParentID = &parentId
|
ret.ParentID = &parentId
|
||||||
|
|
@ -108,6 +119,17 @@ func (s *ScrapedStudio) ToPartial(id string, endpoint string, excluded map[strin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.Details != nil && !excluded["details"] {
|
||||||
|
ret.Details = NewOptionalString(*s.Details)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Aliases != nil && !excluded["aliases"] {
|
||||||
|
ret.Aliases = &UpdateStrings{
|
||||||
|
Values: stringslice.FromString(*s.Aliases, ","),
|
||||||
|
Mode: RelationshipUpdateModeSet,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if s.Parent != nil && !excluded["parent"] {
|
if s.Parent != nil && !excluded["parent"] {
|
||||||
if s.Parent.StoredID != nil {
|
if s.Parent.StoredID != nil {
|
||||||
parentID, _ := strconv.Atoi(*s.Parent.StoredID)
|
parentID, _ := strconv.Atoi(*s.Parent.StoredID)
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,12 @@ func (t *ImageFragment) GetHeight() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
type StudioFragment struct {
|
type StudioFragment struct {
|
||||||
Name string "json:\"name\" graphql:\"name\""
|
Name string "json:\"name\" graphql:\"name\""
|
||||||
ID string "json:\"id\" graphql:\"id\""
|
ID string "json:\"id\" graphql:\"id\""
|
||||||
Urls []*URLFragment "json:\"urls\" graphql:\"urls\""
|
Aliases []string "json:\"aliases\" graphql:\"aliases\""
|
||||||
Parent *StudioFragment_Parent "json:\"parent,omitempty\" graphql:\"parent\""
|
Urls []*URLFragment "json:\"urls\" graphql:\"urls\""
|
||||||
Images []*ImageFragment "json:\"images\" graphql:\"images\""
|
Parent *StudioFragment_Parent "json:\"parent,omitempty\" graphql:\"parent\""
|
||||||
|
Images []*ImageFragment "json:\"images\" graphql:\"images\""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *StudioFragment) GetName() string {
|
func (t *StudioFragment) GetName() string {
|
||||||
|
|
@ -101,6 +102,12 @@ func (t *StudioFragment) GetID() string {
|
||||||
}
|
}
|
||||||
return t.ID
|
return t.ID
|
||||||
}
|
}
|
||||||
|
func (t *StudioFragment) GetAliases() []string {
|
||||||
|
if t == nil {
|
||||||
|
t = &StudioFragment{}
|
||||||
|
}
|
||||||
|
return t.Aliases
|
||||||
|
}
|
||||||
func (t *StudioFragment) GetUrls() []*URLFragment {
|
func (t *StudioFragment) GetUrls() []*URLFragment {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
t = &StudioFragment{}
|
t = &StudioFragment{}
|
||||||
|
|
@ -845,6 +852,7 @@ fragment ImageFragment on Image {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
... URLFragment
|
... URLFragment
|
||||||
}
|
}
|
||||||
|
|
@ -980,6 +988,7 @@ fragment ImageFragment on Image {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
... URLFragment
|
... URLFragment
|
||||||
}
|
}
|
||||||
|
|
@ -1115,6 +1124,7 @@ fragment ImageFragment on Image {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
... URLFragment
|
... URLFragment
|
||||||
}
|
}
|
||||||
|
|
@ -1250,6 +1260,7 @@ fragment ImageFragment on Image {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
... URLFragment
|
... URLFragment
|
||||||
}
|
}
|
||||||
|
|
@ -1543,6 +1554,7 @@ fragment ImageFragment on Image {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
... URLFragment
|
... URLFragment
|
||||||
}
|
}
|
||||||
|
|
@ -1641,6 +1653,7 @@ const FindStudioDocument = `query FindStudio ($id: ID, $name: String) {
|
||||||
fragment StudioFragment on Studio {
|
fragment StudioFragment on Studio {
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
|
aliases
|
||||||
urls {
|
urls {
|
||||||
... URLFragment
|
... URLFragment
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package stashbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
|
|
@ -63,8 +64,11 @@ func studioFragmentToScrapedStudio(s graphql.StudioFragment) *models.ScrapedStud
|
||||||
images = append(images, image.URL)
|
images = append(images, image.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aliases := strings.Join(s.Aliases, ", ")
|
||||||
|
|
||||||
st := &models.ScrapedStudio{
|
st := &models.ScrapedStudio{
|
||||||
Name: s.Name,
|
Name: s.Name,
|
||||||
|
Aliases: &aliases,
|
||||||
Images: images,
|
Images: images,
|
||||||
RemoteSiteID: &s.ID,
|
RemoteSiteID: &s.ID,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,19 @@ fragment ScrapedStudioData on ScrapedStudio {
|
||||||
name
|
name
|
||||||
urls
|
urls
|
||||||
image
|
image
|
||||||
|
details
|
||||||
|
aliases
|
||||||
|
tags {
|
||||||
|
...ScrapedSceneTagData
|
||||||
|
}
|
||||||
remote_site_id
|
remote_site_id
|
||||||
}
|
}
|
||||||
image
|
image
|
||||||
|
details
|
||||||
|
aliases
|
||||||
|
tags {
|
||||||
|
...ScrapedSceneTagData
|
||||||
|
}
|
||||||
remote_site_id
|
remote_site_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,9 +139,19 @@ fragment ScrapedSceneStudioData on ScrapedStudio {
|
||||||
name
|
name
|
||||||
urls
|
urls
|
||||||
image
|
image
|
||||||
|
details
|
||||||
|
aliases
|
||||||
|
tags {
|
||||||
|
...ScrapedSceneTagData
|
||||||
|
}
|
||||||
remote_site_id
|
remote_site_id
|
||||||
}
|
}
|
||||||
image
|
image
|
||||||
|
details
|
||||||
|
aliases
|
||||||
|
tags {
|
||||||
|
...ScrapedSceneTagData
|
||||||
|
}
|
||||||
remote_site_id
|
remote_site_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ export const ScrapedStudioRow: React.FC<IScrapedStudioRow> = ({
|
||||||
const value = resultValue ? [resultValue] : [];
|
const value = resultValue ? [resultValue] : [];
|
||||||
|
|
||||||
const selectValue = value.map((p) => {
|
const selectValue = value.map((p) => {
|
||||||
const aliases: string[] = [];
|
const aliases: string[] = p.aliases
|
||||||
|
? p.aliases.split(",").map((a) => a.trim())
|
||||||
|
: [];
|
||||||
return {
|
return {
|
||||||
id: p.stored_id ?? "",
|
id: p.stored_id ?? "",
|
||||||
name: p.name ?? "",
|
name: p.name ?? "",
|
||||||
|
|
@ -55,10 +57,11 @@ export const ScrapedStudioRow: React.FC<IScrapedStudioRow> = ({
|
||||||
isDisabled={!isNew}
|
isDisabled={!isNew}
|
||||||
onSelect={(items) => {
|
onSelect={(items) => {
|
||||||
if (onChangeFn) {
|
if (onChangeFn) {
|
||||||
const { id, ...data } = items[0];
|
const { id, aliases, ...data } = items[0];
|
||||||
onChangeFn({
|
onChangeFn({
|
||||||
...data,
|
...data,
|
||||||
stored_id: id,
|
stored_id: id,
|
||||||
|
aliases: aliases?.join(", "),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,9 @@ const StudioDetails: React.FC<IStudioDetailsProps> = ({
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
{maybeRenderField("name", studio.name, !isNew)}
|
{maybeRenderField("name", studio.name, !isNew)}
|
||||||
{maybeRenderURLListField("urls", studio.urls)}
|
{maybeRenderURLListField("urls", studio.urls)}
|
||||||
|
{maybeRenderField("details", studio.details)}
|
||||||
|
{maybeRenderField("aliases", studio.aliases)}
|
||||||
|
{maybeRenderField("tags", studio.tags?.map((t) => t.name).join(", "))}
|
||||||
{maybeRenderField("parent_studio", studio.parent?.name, false)}
|
{maybeRenderField("parent_studio", studio.parent?.name, false)}
|
||||||
{maybeRenderStashBoxLink()}
|
{maybeRenderStashBoxLink()}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -232,6 +235,11 @@ const StudioModal: React.FC<IStudioModalProps> = ({
|
||||||
urls: studio.urls,
|
urls: studio.urls,
|
||||||
image: studio.image,
|
image: studio.image,
|
||||||
parent_id: studio.parent?.stored_id,
|
parent_id: studio.parent?.stored_id,
|
||||||
|
details: studio.details,
|
||||||
|
aliases: studio.aliases?.split(",").map((a) => a.trim()),
|
||||||
|
tag_ids: studio.tags?.map((t) => t.stored_id).filter((id) => id) as
|
||||||
|
| string[]
|
||||||
|
| undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
// stashid handling code
|
// stashid handling code
|
||||||
|
|
@ -261,6 +269,11 @@ const StudioModal: React.FC<IStudioModalProps> = ({
|
||||||
name: studio.parent?.name,
|
name: studio.parent?.name,
|
||||||
urls: studio.parent?.urls,
|
urls: studio.parent?.urls,
|
||||||
image: studio.parent?.image,
|
image: studio.parent?.image,
|
||||||
|
details: studio.parent?.details,
|
||||||
|
aliases: studio.parent?.aliases?.split(",").map((a) => a.trim()),
|
||||||
|
tag_ids: studio.parent?.tags
|
||||||
|
?.map((t) => t.stored_id)
|
||||||
|
.filter((id) => id) as string[] | undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
// stashid handling code
|
// stashid handling code
|
||||||
|
|
|
||||||
|
|
@ -739,7 +739,11 @@ xPathScrapers:
|
||||||
URL: $performer/@href
|
URL: $performer/@href
|
||||||
Studio:
|
Studio:
|
||||||
Name: $studio
|
Name: $studio
|
||||||
URL: $studio/@href
|
URL: $studio/@href
|
||||||
|
Details: //div[@class="studioDescription"]
|
||||||
|
Aliases: //div[@class="studioAliases"]/span
|
||||||
|
Tags:
|
||||||
|
Name: //div[@class="studioTags"]/a
|
||||||
```
|
```
|
||||||
|
|
||||||
See also [#333](https://github.com/stashapp/stash/pull/333) for more examples.
|
See also [#333](https://github.com/stashapp/stash/pull/333) for more examples.
|
||||||
|
|
@ -822,6 +826,11 @@ jsonScrapers:
|
||||||
Name: data.performers.#.name
|
Name: data.performers.#.name
|
||||||
Studio:
|
Studio:
|
||||||
Name: data.site.name
|
Name: data.site.name
|
||||||
|
URL: data.site.url
|
||||||
|
Details: data.site.description
|
||||||
|
Aliases: data.site.aliases
|
||||||
|
Tags:
|
||||||
|
Name: data.site.tags.#.name
|
||||||
Tags:
|
Tags:
|
||||||
Name: data.tags.#.tag
|
Name: data.tags.#.tag
|
||||||
|
|
||||||
|
|
@ -839,6 +848,11 @@ jsonScrapers:
|
||||||
Name: $data.performers.#.name
|
Name: $data.performers.#.name
|
||||||
Studio:
|
Studio:
|
||||||
Name: $data.site.name
|
Name: $data.site.name
|
||||||
|
URL: $data.site.url
|
||||||
|
Details: $data.site.description
|
||||||
|
Aliases: $data.site.aliases
|
||||||
|
Tags:
|
||||||
|
Name: $data.site.tags.#.name
|
||||||
Tags:
|
Tags:
|
||||||
Name: $data.tags.#.tag
|
Name: $data.tags.#.tag
|
||||||
driver:
|
driver:
|
||||||
|
|
@ -955,7 +969,10 @@ URLs
|
||||||
### Studio
|
### Studio
|
||||||
|
|
||||||
```
|
```
|
||||||
|
Aliases
|
||||||
|
Details
|
||||||
Name
|
Name
|
||||||
|
Tags (see Tag fields)
|
||||||
URL
|
URL
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue