Files
metatube-server/provider/getchu/getchu.go
T
2022-12-15 23:13:04 +08:00

142 lines
3.3 KiB
Go

package getchu
import (
"fmt"
"net/url"
"path"
"regexp"
"strings"
"github.com/antchfx/htmlquery"
"github.com/gocolly/colly/v2"
"golang.org/x/net/html"
"github.com/javtube/metatube-sdk-go/common/parser"
"github.com/javtube/metatube-sdk-go/model"
"github.com/javtube/metatube-sdk-go/provider"
"github.com/javtube/metatube-sdk-go/provider/internal/scraper"
)
var _ provider.MovieProvider = (*Getchu)(nil)
const (
Name = "Getchu"
Priority = 1000
)
const (
baseURL = "https://dl.getchu.com/"
movieURL = "https://dl.getchu.com/i/item%s"
)
type Getchu struct {
*scraper.Scraper
}
func New() *Getchu {
return &Getchu{scraper.NewDefaultScraper(Name, baseURL, Priority)}
}
func (gcu *Getchu) NormalizeID(id string) string {
if ss := regexp.MustCompile(`^(?i)(?:GETCHU[-_])?(\d+)$`).FindStringSubmatch(id); len(ss) == 2 {
return ss[1]
}
return ""
}
func (gcu *Getchu) GetMovieInfoByID(id string) (info *model.MovieInfo, err error) {
return gcu.GetMovieInfoByURL(fmt.Sprintf(movieURL, id))
}
func (gcu *Getchu) ParseIDFromURL(rawURL string) (string, error) {
homepage, err := url.Parse(rawURL)
if err != nil {
return "", err
}
return strings.TrimLeft(path.Base(homepage.Path), "item"), nil
}
func (gcu *Getchu) GetMovieInfoByURL(rawURL string) (info *model.MovieInfo, err error) {
id, err := gcu.ParseIDFromURL(rawURL)
if err != nil {
return
}
info = &model.MovieInfo{
ID: id,
Number: fmt.Sprintf("GETCHU-%s", id),
Provider: gcu.Name(),
Homepage: rawURL,
Actors: []string{},
PreviewImages: []string{},
Genres: []string{},
}
c := gcu.ClonedCollector()
// Misc
c.OnXML(`//td`, func(e *colly.XMLElement) {
switch {
// Title
case e.ChildAttr(`.//div`, "style") == "color: #333333; padding: 3px 0px 0px 5px;":
info.Title = strings.TrimSpace(e.Text)
// Cover
case e.Attr("bgcolor") == "#ffffff":
info.CoverURL = e.Request.AbsoluteURL(e.ChildAttr(`.//img`, "src"))
// Preview Images
case strings.Contains(e.Attr("style"), "background-color: #444444;"):
info.PreviewImages = append(info.PreviewImages,
e.Request.AbsoluteURL(e.ChildAttr(`.//a`, "href")))
}
})
// Fields
c.OnXML(`//tr`, func(e *colly.XMLElement) {
switch e.ChildText(`.//td[1]`) {
case "サークル":
info.Label = strings.TrimSpace(e.ChildText(`.//td[2]`))
case "作者":
// info.Director = e.ChildText(`.//td[2]`)
case "画像数&ページ数":
// info.Runtime = parser.ParseRuntime(e.ChildText(`.//td[2]`))
case "配信開始日":
info.ReleaseDate = parser.ParseDate(e.ChildText(`.//td[2]`))
case "趣向":
parser.ParseTexts(htmlquery.FindOne(e.DOM.(*html.Node), `.//td[2]`),
(*[]string)(&info.Genres))
case "作品内容":
info.Summary = strings.TrimSpace(e.ChildText(`.//td[2]`))
}
})
// Title (fallback)
c.OnXML(`//meta[@property="og:title"]`, func(e *colly.XMLElement) {
if info.Title != "" {
return
}
info.Title = e.Attr("content")
})
// Cover (fallback)
c.OnXML(`//meta[@property="og:image"]`, func(e *colly.XMLElement) {
if info.CoverURL != "" {
return
}
info.CoverURL = e.Request.AbsoluteURL(e.Attr("content"))
})
// Fallbacks
c.OnScraped(func(_ *colly.Response) {
if info.ThumbURL == "" {
info.ThumbURL = info.CoverURL // same as cover.
}
})
err = c.Visit(info.Homepage)
return
}
func init() {
provider.RegisterMovieFactory(Name, New)
}