147 lines
3.7 KiB
Go
147 lines
3.7 KiB
Go
package fc2
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"path"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/gocolly/colly/v2"
|
|
|
|
"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 = (*FC2)(nil)
|
|
|
|
const (
|
|
Name = "FC2"
|
|
Priority = 1000
|
|
)
|
|
|
|
const (
|
|
baseURL = "https://adult.contents.fc2.com/"
|
|
movieURL = "https://adult.contents.fc2.com/article/%s/"
|
|
sampleURL = "https://adult.contents.fc2.com/api/v2/videos/%s/sample"
|
|
)
|
|
|
|
type FC2 struct {
|
|
*scraper.Scraper
|
|
}
|
|
|
|
func New() *FC2 {
|
|
return &FC2{scraper.NewDefaultScraper(Name, baseURL, Priority)}
|
|
}
|
|
|
|
func (fc2 *FC2) NormalizeID(id string) string {
|
|
return ParseNumber(id)
|
|
}
|
|
|
|
func (fc2 *FC2) GetMovieInfoByID(id string) (info *model.MovieInfo, err error) {
|
|
return fc2.GetMovieInfoByURL(fmt.Sprintf(movieURL, id))
|
|
}
|
|
|
|
func (fc2 *FC2) ParseIDFromURL(rawURL string) (string, error) {
|
|
homepage, err := url.Parse(rawURL)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return path.Base(homepage.Path), nil
|
|
}
|
|
|
|
func (fc2 *FC2) GetMovieInfoByURL(rawURL string) (info *model.MovieInfo, err error) {
|
|
id, err := fc2.ParseIDFromURL(rawURL)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
info = &model.MovieInfo{
|
|
ID: id,
|
|
Number: fmt.Sprintf("FC2-%s", id),
|
|
Provider: fc2.Name(),
|
|
Homepage: rawURL,
|
|
Actors: []string{},
|
|
PreviewImages: []string{},
|
|
Genres: []string{},
|
|
}
|
|
|
|
c := fc2.ClonedCollector()
|
|
|
|
// Headers
|
|
c.OnXML(`//div[@class="items_article_headerInfo"]`, func(e *colly.XMLElement) {
|
|
info.Title = e.ChildText(`.//h3/text()`)
|
|
info.Genres = e.ChildTexts(`.//section[@class="items_article_TagArea"]/div/a`)
|
|
info.Maker = e.ChildText(`.//ul/li[last()]/a`)
|
|
{ /* score */
|
|
class := e.ChildAttr(`.//li[@class="items_article_StarA"]/a/p/span`, "class")
|
|
info.Score = parser.ParseScore(regexp.MustCompile(`(\d+)$`).FindString(class))
|
|
}
|
|
{ /* release date */
|
|
ss := strings.Split(e.ChildText(`.//div[@class="items_article_Releasedate"]/p`), ":")
|
|
info.ReleaseDate = parser.ParseDate(ss[len(ss)-1])
|
|
}
|
|
})
|
|
|
|
// Summary
|
|
c.OnXML(`//section[@class="items_article_Contents"]/iframe`, func(e *colly.XMLElement) {
|
|
d := c.Clone()
|
|
d.OnXML(`//html/body/div`, func(e *colly.XMLElement) {
|
|
info.Summary = strings.TrimSpace(e.Text)
|
|
})
|
|
d.Visit(e.Request.AbsoluteURL(e.Attr("src")))
|
|
})
|
|
|
|
// Thumb
|
|
c.OnXML(`//div[@class="items_article_MainitemThumb"]/span/img`, func(e *colly.XMLElement) {
|
|
info.ThumbURL = e.Request.AbsoluteURL(e.Attr("src"))
|
|
})
|
|
|
|
// Preview Images
|
|
c.OnXML(`//section[@class="items_article_SampleImages"]/ul/li`, func(e *colly.XMLElement) {
|
|
info.PreviewImages = append(info.PreviewImages, e.Request.AbsoluteURL(e.ChildAttr(`.//a`, "href")))
|
|
})
|
|
|
|
// Cover (fallbacks)
|
|
c.OnScraped(func(_ *colly.Response) {
|
|
if info.ThumbURL != "" {
|
|
info.CoverURL = info.ThumbURL
|
|
} else if len(info.PreviewImages) > 0 {
|
|
// Use first preview image as cover due to
|
|
// thumb image poor resolution.
|
|
info.CoverURL = info.PreviewImages[0]
|
|
}
|
|
})
|
|
|
|
// Preview Video
|
|
//c.OnScraped(func(r *colly.Response) {
|
|
// d := c.Clone()
|
|
// d.OnResponse(func(r *colly.Response) {
|
|
// data := struct {
|
|
// Path string `json:"path"`
|
|
// Code int `json:"code"`
|
|
// }{}
|
|
// if err := json.Unmarshal(r.Body, &data); err == nil && data.Code == http.StatusOK {
|
|
// info.PreviewVideoURL = data.Path
|
|
// }
|
|
// })
|
|
// d.Visit(fmt.Sprintf(sampleURL, info.ID))
|
|
//})
|
|
|
|
err = c.Visit(info.Homepage)
|
|
return
|
|
}
|
|
|
|
func ParseNumber(s string) string {
|
|
if ss := regexp.MustCompile(`^(?i)(?:FC2(?:[-_]?PPV)?[-_]?)?(\d+)$`).FindStringSubmatch(s); len(ss) == 2 {
|
|
return ss[1]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func init() {
|
|
provider.RegisterMovieFactory(Name, New)
|
|
}
|