node build fixed
This commit is contained in:
342
seanime-2.9.10/internal/onlinestream/providers/zoro.go
Normal file
342
seanime-2.9.10/internal/onlinestream/providers/zoro.go
Normal file
@@ -0,0 +1,342 @@
|
||||
package onlinestream_providers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/gocolly/colly"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/samber/lo"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"seanime/internal/onlinestream/sources"
|
||||
"seanime/internal/util"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
hibikeonlinestream "seanime/internal/extension/hibike/onlinestream"
|
||||
)
|
||||
|
||||
type Zoro struct {
|
||||
BaseURL string
|
||||
Client *http.Client
|
||||
UserAgent string
|
||||
logger *zerolog.Logger
|
||||
}
|
||||
|
||||
func NewZoro(logger *zerolog.Logger) hibikeonlinestream.Provider {
|
||||
return &Zoro{
|
||||
BaseURL: "https://hianime.to",
|
||||
UserAgent: util.GetRandomUserAgent(),
|
||||
Client: &http.Client{},
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Zoro) GetSettings() hibikeonlinestream.Settings {
|
||||
return hibikeonlinestream.Settings{
|
||||
EpisodeServers: []string{VidcloudServer, VidstreamingServer},
|
||||
SupportsDub: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Zoro) Search(opts hibikeonlinestream.SearchOptions) ([]*hibikeonlinestream.SearchResult, error) {
|
||||
var results []*hibikeonlinestream.SearchResult
|
||||
|
||||
query := opts.Query
|
||||
dubbed := opts.Dub
|
||||
|
||||
z.logger.Debug().Str("query", query).Bool("dubbed", dubbed).Msg("zoro: Searching anime")
|
||||
|
||||
c := colly.NewCollector()
|
||||
|
||||
c.OnHTML(".flw-item", func(e *colly.HTMLElement) {
|
||||
id := strings.Split(strings.Split(e.ChildAttr(".film-name a", "href"), "/")[1], "?")[0]
|
||||
title := e.ChildText(".film-name a")
|
||||
url := strings.Split(z.BaseURL+e.ChildAttr(".film-name a", "href"), "?")[0]
|
||||
subOrDub := hibikeonlinestream.Sub
|
||||
foundSub := false
|
||||
foundDub := false
|
||||
if e.ChildText(".tick-item.tick-dub") != "" {
|
||||
foundDub = true
|
||||
}
|
||||
if e.ChildText(".tick-item.tick-sub") != "" {
|
||||
foundSub = true
|
||||
}
|
||||
if foundSub && foundDub {
|
||||
subOrDub = hibikeonlinestream.SubAndDub
|
||||
} else if foundDub {
|
||||
subOrDub = hibikeonlinestream.Dub
|
||||
}
|
||||
results = append(results, &hibikeonlinestream.SearchResult{
|
||||
ID: id,
|
||||
Title: title,
|
||||
URL: url,
|
||||
SubOrDub: subOrDub,
|
||||
})
|
||||
})
|
||||
|
||||
searchURL := z.BaseURL + "/search?keyword=" + url.QueryEscape(query)
|
||||
|
||||
err := c.Visit(searchURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dubbed {
|
||||
results = lo.Filter(results, func(r *hibikeonlinestream.SearchResult, _ int) bool {
|
||||
return r.SubOrDub == hibikeonlinestream.Dub || r.SubOrDub == hibikeonlinestream.SubAndDub
|
||||
})
|
||||
}
|
||||
|
||||
z.logger.Debug().Int("count", len(results)).Msg("zoro: Fetched anime")
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (z *Zoro) FindEpisodes(id string) ([]*hibikeonlinestream.EpisodeDetails, error) {
|
||||
var episodes []*hibikeonlinestream.EpisodeDetails
|
||||
|
||||
z.logger.Debug().Str("id", id).Msg("zoro: Fetching episodes")
|
||||
|
||||
c := colly.NewCollector()
|
||||
|
||||
subOrDub := hibikeonlinestream.Sub
|
||||
|
||||
c.OnHTML("div.film-stats > div.tick", func(e *colly.HTMLElement) {
|
||||
if e.ChildText(".tick-item.tick-dub") != "" {
|
||||
subOrDub = hibikeonlinestream.Dub
|
||||
}
|
||||
if e.ChildText(".tick-item.tick-sub") != "" {
|
||||
if subOrDub == hibikeonlinestream.Dub {
|
||||
subOrDub = hibikeonlinestream.SubAndDub
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
watchUrl := fmt.Sprintf("%s/watch/%s", z.BaseURL, id)
|
||||
err := c.Visit(watchUrl)
|
||||
if err != nil {
|
||||
z.logger.Error().Err(err).Msg("zoro: Failed to fetch episodes")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get episodes
|
||||
|
||||
splitId := strings.Split(id, "-")
|
||||
idNum := splitId[len(splitId)-1]
|
||||
ajaxUrl := fmt.Sprintf("%s/ajax/v2/episode/list/%s", z.BaseURL, idNum)
|
||||
|
||||
c2 := colly.NewCollector(
|
||||
colly.UserAgent(z.UserAgent),
|
||||
)
|
||||
|
||||
c2.OnRequest(func(r *colly.Request) {
|
||||
r.Headers.Set("X-Requested-With", "XMLHttpRequest")
|
||||
r.Headers.Set("Referer", watchUrl)
|
||||
})
|
||||
|
||||
c2.OnResponse(func(r *colly.Response) {
|
||||
var jsonResponse map[string]interface{}
|
||||
err = json.Unmarshal(r.Body, &jsonResponse)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(jsonResponse["html"].(string)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
content := doc.Find(".detail-infor-content")
|
||||
content.Find("a").Each(func(i int, s *goquery.Selection) {
|
||||
id := s.AttrOr("href", "")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
hrefParts := strings.Split(s.AttrOr("href", ""), "/")
|
||||
if len(hrefParts) < 2 {
|
||||
return
|
||||
}
|
||||
if subOrDub == hibikeonlinestream.SubAndDub {
|
||||
subOrDub = "both"
|
||||
}
|
||||
id = fmt.Sprintf("%s$%s", strings.Replace(hrefParts[2], "?ep=", "$episode$", 1), subOrDub)
|
||||
epNumber, _ := strconv.Atoi(s.AttrOr("data-number", ""))
|
||||
url := z.BaseURL + s.AttrOr("href", "")
|
||||
title := s.AttrOr("title", "")
|
||||
episodes = append(episodes, &hibikeonlinestream.EpisodeDetails{
|
||||
Provider: ZoroProvider,
|
||||
ID: id,
|
||||
Number: epNumber,
|
||||
URL: url,
|
||||
Title: title,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
err = c2.Visit(ajaxUrl)
|
||||
if err != nil {
|
||||
z.logger.Error().Err(err).Msg("zoro: Failed to fetch episodes")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
z.logger.Debug().Int("count", len(episodes)).Msg("zoro: Fetched episodes")
|
||||
|
||||
return episodes, nil
|
||||
}
|
||||
|
||||
func (z *Zoro) FindEpisodeServer(episodeInfo *hibikeonlinestream.EpisodeDetails, server string) (*hibikeonlinestream.EpisodeServer, error) {
|
||||
var source *hibikeonlinestream.EpisodeServer
|
||||
|
||||
if server == DefaultServer {
|
||||
server = VidcloudServer
|
||||
}
|
||||
|
||||
z.logger.Debug().Str("server", server).Str("episodeID", episodeInfo.ID).Msg("zoro: Fetching server sources")
|
||||
|
||||
episodeParts := strings.Split(episodeInfo.ID, "$")
|
||||
|
||||
if len(episodeParts) < 3 {
|
||||
return nil, errors.New("invalid episode id")
|
||||
}
|
||||
|
||||
episodeID := fmt.Sprintf("%s?ep=%s", episodeParts[0], episodeParts[2])
|
||||
subOrDub := hibikeonlinestream.Sub
|
||||
if episodeParts[len(episodeParts)-1] == "dub" {
|
||||
subOrDub = hibikeonlinestream.Dub
|
||||
}
|
||||
|
||||
// Get server
|
||||
|
||||
var serverId string
|
||||
|
||||
c := colly.NewCollector(
|
||||
colly.UserAgent(z.UserAgent),
|
||||
)
|
||||
c.OnRequest(func(r *colly.Request) {
|
||||
r.Headers.Set("X-Requested-With", "XMLHttpRequest")
|
||||
})
|
||||
|
||||
c.OnResponse(func(r *colly.Response) {
|
||||
var jsonResponse map[string]interface{}
|
||||
err := json.Unmarshal(r.Body, &jsonResponse)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(jsonResponse["html"].(string)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch server {
|
||||
case VidcloudServer:
|
||||
serverId = z.findServerId(doc, 4, subOrDub)
|
||||
case VidstreamingServer:
|
||||
serverId = z.findServerId(doc, 4, subOrDub)
|
||||
case StreamSBServer:
|
||||
serverId = z.findServerId(doc, 4, subOrDub)
|
||||
case StreamtapeServer:
|
||||
serverId = z.findServerId(doc, 4, subOrDub)
|
||||
}
|
||||
})
|
||||
|
||||
ajaxEpisodeUrl := fmt.Sprintf("%s/ajax/v2/episode/servers?episodeId=%s", z.BaseURL, strings.Split(episodeID, "?ep=")[1])
|
||||
if err := c.Visit(ajaxEpisodeUrl); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if serverId == "" {
|
||||
return nil, ErrServerNotFound
|
||||
}
|
||||
|
||||
c2 := colly.NewCollector(
|
||||
colly.UserAgent(z.UserAgent),
|
||||
)
|
||||
c2.OnRequest(func(r *colly.Request) {
|
||||
r.Headers.Set("X-Requested-With", "XMLHttpRequest")
|
||||
})
|
||||
|
||||
c2.OnResponse(func(r *colly.Response) {
|
||||
var jsonResponse map[string]interface{}
|
||||
err := json.Unmarshal(r.Body, &jsonResponse)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, ok := jsonResponse["link"].(string); !ok {
|
||||
return
|
||||
}
|
||||
switch server {
|
||||
case VidcloudServer, VidstreamingServer:
|
||||
megacloud := onlinestream_sources.NewMegaCloud()
|
||||
sources, err := megacloud.Extract(jsonResponse["link"].(string))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
source = &hibikeonlinestream.EpisodeServer{
|
||||
Provider: ZoroProvider,
|
||||
Server: server,
|
||||
Headers: map[string]string{},
|
||||
VideoSources: sources,
|
||||
}
|
||||
case StreamtapeServer:
|
||||
streamtape := onlinestream_sources.NewStreamtape()
|
||||
sources, err := streamtape.Extract(jsonResponse["link"].(string))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
source = &hibikeonlinestream.EpisodeServer{
|
||||
Provider: ZoroProvider,
|
||||
Server: server,
|
||||
Headers: map[string]string{
|
||||
"Referer": jsonResponse["link"].(string),
|
||||
"User-Agent": z.UserAgent,
|
||||
},
|
||||
VideoSources: sources,
|
||||
}
|
||||
case StreamSBServer:
|
||||
streamsb := onlinestream_sources.NewStreamSB()
|
||||
sources, err := streamsb.Extract(jsonResponse["link"].(string))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
source = &hibikeonlinestream.EpisodeServer{
|
||||
Provider: ZoroProvider,
|
||||
Server: server,
|
||||
Headers: map[string]string{
|
||||
"Referer": jsonResponse["link"].(string),
|
||||
"watchsb": "streamsb",
|
||||
"User-Agent": z.UserAgent,
|
||||
},
|
||||
VideoSources: sources,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Get sources
|
||||
serverSourceUrl := fmt.Sprintf("%s/ajax/v2/episode/sources?id=%s", z.BaseURL, serverId)
|
||||
if err := c2.Visit(serverSourceUrl); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if source == nil {
|
||||
z.logger.Warn().Str("server", server).Msg("zoro: No sources found")
|
||||
return nil, ErrSourceNotFound
|
||||
}
|
||||
|
||||
z.logger.Debug().Str("server", server).Int("videoSources", len(source.VideoSources)).Msg("zoro: Fetched server sources")
|
||||
|
||||
return source, nil
|
||||
}
|
||||
|
||||
func (z *Zoro) findServerId(doc *goquery.Document, idx int, subOrDub hibikeonlinestream.SubOrDub) string {
|
||||
var serverId string
|
||||
doc.Find(fmt.Sprintf("div.ps_-block.ps_-block-sub.servers-%s > div.ps__-list > div", subOrDub)).Each(func(i int, s *goquery.Selection) {
|
||||
_serverId := s.AttrOr("data-server-id", "")
|
||||
if serverId == "" {
|
||||
if _serverId == strconv.Itoa(idx) {
|
||||
serverId = s.AttrOr("data-id", "")
|
||||
}
|
||||
}
|
||||
})
|
||||
return serverId
|
||||
}
|
||||
Reference in New Issue
Block a user