Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement scraping movies by URL #709

Merged
merged 8 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions gqlgen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ models:
model: github.com/stashapp/stash/pkg/models.ScrapedSceneTag
SceneFileType:
model: github.com/stashapp/stash/pkg/models.SceneFileType
ScrapedMovie:
model: github.com/stashapp/stash/pkg/models.ScrapedMovie
ScrapedMovieStudio:
model: github.com/stashapp/stash/pkg/models.ScrapedMovieStudio
14 changes: 13 additions & 1 deletion graphql/documents/data/scrapers.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ fragment ScrapedScenePerformerData on ScrapedScenePerformer {
aliases
}

fragment ScrapedMovieStudioData on ScrapedMovieStudio {
id
name
url
}

fragment ScrapedMovieData on ScrapedMovie {
name
aliases
Expand All @@ -47,6 +53,12 @@ fragment ScrapedMovieData on ScrapedMovie {
director
url
synopsis
front_image
back_image

studio {
...ScrapedMovieStudioData
}
}

fragment ScrapedSceneMovieData on ScrapedSceneMovie {
Expand Down Expand Up @@ -105,4 +117,4 @@ fragment ScrapedSceneData on ScrapedScene {
movies {
...ScrapedSceneMovieData
}
}
}
19 changes: 18 additions & 1 deletion graphql/documents/queries/scrapers/scrapers.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ query ListSceneScrapers {
}
}

query ListMovieScrapers {
listMovieScrapers {
id
name
movie {
urls
supported_scrapes
}
}
}

query ScrapePerformerList($scraper_id: ID!, $query: String!) {
scrapePerformerList(scraper_id: $scraper_id, query: $query) {
...ScrapedPerformerData
Expand Down Expand Up @@ -48,4 +59,10 @@ query ScrapeSceneURL($url: String!) {
scrapeSceneURL(url: $url) {
...ScrapedSceneData
}
}
}

query ScrapeMovieURL($url: String!) {
scrapeMovieURL(url: $url) {
...ScrapedMovieData
}
}
3 changes: 3 additions & 0 deletions graphql/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Query {
"""List available scrapers"""
listPerformerScrapers: [Scraper!]!
listSceneScrapers: [Scraper!]!
listMovieScrapers: [Scraper!]!

"""Scrape a list of performers based on name"""
scrapePerformerList(scraper_id: ID!, query: String!): [ScrapedPerformer!]!
Expand All @@ -70,6 +71,8 @@ type Query {
scrapeScene(scraper_id: ID!, scene: SceneUpdateInput!): ScrapedScene
"""Scrapes a complete performer record based on a URL"""
scrapeSceneURL(url: String!): ScrapedScene
"""Scrapes a complete movie record based on a URL"""
scrapeMovieURL(url: String!): ScrapedMovie

"""Scrape a performer using Freeones"""
scrapeFreeones(performer_name: String!): ScrapedPerformer
Expand Down
14 changes: 13 additions & 1 deletion graphql/schema/types/scraped-movie.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
type ScrapedMovieStudio {
"""Set if studio matched"""
id: ID
name: String!
url: String
}

"""A movie from a scraping operation..."""
type ScrapedMovie {
name: String
Expand All @@ -8,6 +15,11 @@ type ScrapedMovie {
director: String
url: String
synopsis: String
studio: ScrapedMovieStudio

"""This should be base64 encoded"""
front_image: String
back_image: String
}

input ScrapedMovieInput {
Expand All @@ -19,4 +31,4 @@ input ScrapedMovieInput {
director: String
url: String
synopsis: String
}
}
2 changes: 2 additions & 0 deletions graphql/schema/types/scraper.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type Scraper {
performer: ScraperSpec
"""Details for scene scraper"""
scene: ScraperSpec
"""Details for movie scraper"""
movie: ScraperSpec
}


Expand Down
8 changes: 8 additions & 0 deletions pkg/api/resolver_query_scraper.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func (r *queryResolver) ListSceneScrapers(ctx context.Context) ([]*models.Scrape
return manager.GetInstance().ScraperCache.ListSceneScrapers(), nil
}

func (r *queryResolver) ListMovieScrapers(ctx context.Context) ([]*models.Scraper, error) {
return manager.GetInstance().ScraperCache.ListMovieScrapers(), nil
}

func (r *queryResolver) ScrapePerformerList(ctx context.Context, scraperID string, query string) ([]*models.ScrapedPerformer, error) {
if query == "" {
return nil, nil
Expand All @@ -64,3 +68,7 @@ func (r *queryResolver) ScrapeScene(ctx context.Context, scraperID string, scene
func (r *queryResolver) ScrapeSceneURL(ctx context.Context, url string) (*models.ScrapedScene, error) {
return manager.GetInstance().ScraperCache.ScrapeSceneURL(url)
}

func (r *queryResolver) ScrapeMovieURL(ctx context.Context, url string) (*models.ScrapedMovie, error) {
return manager.GetInstance().ScraperCache.ScrapeMovieURL(url)
}
5 changes: 2 additions & 3 deletions pkg/api/urlbuilders/movie.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package urlbuilders
import "strconv"

type MovieURLBuilder struct {
BaseURL string
BaseURL string
MovieID string
}

func NewMovieURLBuilder(baseURL string, movieID int) MovieURLBuilder {
return MovieURLBuilder{
BaseURL: baseURL,
BaseURL: baseURL,
MovieID: strconv.Itoa(movieID),
}
}
Expand All @@ -21,4 +21,3 @@ func (b MovieURLBuilder) GetMovieFrontImageURL() string {
func (b MovieURLBuilder) GetMovieBackImageURL() string {
return b.BaseURL + "/movie/" + b.MovieID + "/backimage"
}

21 changes: 21 additions & 0 deletions pkg/models/model_scraped_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,24 @@ type ScrapedSceneTag struct {
ID *string `graphql:"id" json:"id"`
Name string `graphql:"name" json:"name"`
}

type ScrapedMovie struct {
Name *string `graphql:"name" json:"name"`
Aliases *string `graphql:"aliases" json:"aliases"`
Duration *string `graphql:"duration" json:"duration"`
Date *string `graphql:"date" json:"date"`
Rating *string `graphql:"rating" json:"rating"`
Director *string `graphql:"director" json:"director"`
Studio *ScrapedMovieStudio `graphql:"studio" json:"studio"`
Synopsis *string `graphql:"synopsis" json:"synopsis"`
URL *string `graphql:"url" json:"url"`
FrontImage *string `graphql:"front_image" json:"front_image"`
BackImage *string `graphql:"back_image" json:"back_image"`
}

type ScrapedMovieStudio struct {
// Set if studio matched
ID *string `graphql:"id" json:"id"`
Name string `graphql:"name" json:"name"`
URL *string `graphql:"url" json:"url"`
}
2 changes: 2 additions & 0 deletions pkg/scraper/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type scraper interface {

scrapeSceneByFragment(scene models.SceneUpdateInput) (*models.ScrapedScene, error)
scrapeSceneByURL(url string) (*models.ScrapedScene, error)

scrapeMovieByURL(url string) (*models.ScrapedMovie, error)
}

func getScraper(scraper scraperTypeConfig, config config, globalConfig GlobalConfig) scraper {
Expand Down
53 changes: 53 additions & 0 deletions pkg/scraper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ type config struct {
// Configuration for querying a scene by a URL
SceneByURL []*scrapeByURLConfig `yaml:"sceneByURL"`

// Configuration for querying a movie by a URL
MovieByURL []*scrapeByURLConfig `yaml:"movieByURL"`

// Scraper debugging options
DebugOptions *scraperDebugOptions `yaml:"debug"`

Expand Down Expand Up @@ -86,6 +89,12 @@ func (c config) validate() error {
}
}

for _, s := range c.MovieByURL {
if err := s.validate(); err != nil {
return err
}
}

return nil
}

Expand Down Expand Up @@ -225,6 +234,18 @@ func (c config) toScraper() *models.Scraper {
ret.Scene = &scene
}

movie := models.ScraperSpec{}
if len(c.MovieByURL) > 0 {
movie.SupportedScrapes = append(movie.SupportedScrapes, models.ScrapeTypeURL)
for _, v := range c.MovieByURL {
movie.Urls = append(movie.Urls, v.URL...)
}
}

if len(movie.SupportedScrapes) > 0 {
ret.Movie = &movie
}

return &ret
}

Expand Down Expand Up @@ -297,6 +318,20 @@ func (c config) matchesSceneURL(url string) bool {
return false
}

func (c config) supportsMovies() bool {
return len(c.MovieByURL) > 0
}

func (c config) matchesMovieURL(url string) bool {
for _, scraper := range c.MovieByURL {
if scraper.matchesURL(url) {
return true
}
}

return false
}

func (c config) ScrapeScene(scene models.SceneUpdateInput, globalConfig GlobalConfig) (*models.ScrapedScene, error) {
if c.SceneByFragment != nil {
s := getScraper(*c.SceneByFragment, c, globalConfig)
Expand All @@ -323,3 +358,21 @@ func (c config) ScrapeSceneURL(url string, globalConfig GlobalConfig) (*models.S

return nil, nil
}

func (c config) ScrapeMovieURL(url string, globalConfig GlobalConfig) (*models.ScrapedMovie, error) {
for _, scraper := range c.MovieByURL {
if scraper.matchesURL(url) {
s := getScraper(scraper.scraperTypeConfig, c, globalConfig)
ret, err := s.scrapeMovieByURL(url)
if err != nil {
return nil, err
}

if ret != nil {
return ret, nil
}
}
}

return nil, nil
}
34 changes: 34 additions & 0 deletions pkg/scraper/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,40 @@ func setSceneImage(s *models.ScrapedScene, globalConfig GlobalConfig) error {
return nil
}

func setMovieFrontImage(m *models.ScrapedMovie, globalConfig GlobalConfig) error {
// don't try to get the image if it doesn't appear to be a URL
if m == nil || m.FrontImage == nil || !strings.HasPrefix(*m.FrontImage, "http") {
// nothing to do
return nil
}

img, err := getImage(*m.FrontImage, globalConfig)
if err != nil {
return err
}

m.FrontImage = img

return nil
}

func setMovieBackImage(m *models.ScrapedMovie, globalConfig GlobalConfig) error {
// don't try to get the image if it doesn't appear to be a URL
if m == nil || m.BackImage == nil || !strings.HasPrefix(*m.BackImage, "http") {
// nothing to do
return nil
}

img, err := getImage(*m.BackImage, globalConfig)
if err != nil {
return err
}

m.BackImage = img

return nil
}

func getImage(url string, globalConfig GlobalConfig) (*string, error) {
client := &http.Client{
Timeout: imageGetTimeout,
Expand Down
10 changes: 10 additions & 0 deletions pkg/scraper/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ func (s *jsonScraper) scrapeSceneByURL(url string) (*models.ScrapedScene, error)
return scraper.scrapeScene(q)
}

func (s *jsonScraper) scrapeMovieByURL(url string) (*models.ScrapedMovie, error) {
doc, scraper, err := s.scrapeURL(url)
if err != nil {
return nil, err
}

q := s.getJsonQuery(doc)
return scraper.scrapeMovie(q)
}

func (s *jsonScraper) scrapePerformersByName(name string) ([]*models.ScrapedPerformer, error) {
scraper := s.getJsonScraper()

Expand Down
Loading