Skip to content

Commit

Permalink
added support for v2.hentaihd.net
Browse files Browse the repository at this point in the history
  • Loading branch information
gan-of-culture committed Dec 12, 2021
1 parent 314e0ce commit e43c8b5
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ The following links will direct you to adult content. Please keep that in mind!
| [simply-hentai.com](https://www.simply-hentai.com) | :heavy_check_mark: | ? |
| [thehentaiworld.com](https://thehentaiworld.com) | :heavy_check_mark: |:heavy_check_mark:|
| [uncensoredhentai.xxx (1080p, 720p, 480p, 360p)](https://uncensoredhentai.xxx/) | ? |:heavy_check_mark:|
| [v2.hentaihd.net (1080p, 720p, 480p)](https://v2.hentaihd.net) | ? |:heavy_check_mark:|
| [yandere.re](https://yande.re/post) | :heavy_check_mark: | ? |
| [zhentube.com (1080p, 720p)](https://zhentube.com) | ? |:heavy_check_mark:|

Expand Down
2 changes: 2 additions & 0 deletions extractors/extractors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/gan-of-culture/get-sauce/extractors/hentaiguru"
"github.com/gan-of-culture/get-sauce/extractors/hentaihaven"
"github.com/gan-of-culture/get-sauce/extractors/hentaihavenred"
"github.com/gan-of-culture/get-sauce/extractors/hentaihd"
"github.com/gan-of-culture/get-sauce/extractors/hentaimama"
"github.com/gan-of-culture/get-sauce/extractors/hentaimoon"
"github.com/gan-of-culture/get-sauce/extractors/hentaipulse"
Expand Down Expand Up @@ -85,6 +86,7 @@ func init() {
"hentaihaven.com": htstreamingExtactor,
"hentaihaven.red": hentaihavenred.New(),
"hentaihaven.xxx": hentaihaven.New(),
"v2.hentaihd.net": hentaihd.New(),
"hentaimama.io": hentaimama.New(),
"hentaipulse.com": hentaipulse.New(),
"hentairox.com": htdoujinExtractor,
Expand Down
131 changes: 131 additions & 0 deletions extractors/hentaihd/hentaihd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package hentaihd

import (
"encoding/json"
"fmt"
"html"
"regexp"
"strings"

"github.com/gan-of-culture/get-sauce/request"
"github.com/gan-of-culture/get-sauce/static"
"github.com/gan-of-culture/get-sauce/utils"
)

type videoInfo struct {
Success bool `json:"success"`
Data []struct {
File string `json:"file"`
Label string `json:"label"`
Type string `json:"type"`
} `json:"data"`
Captions []interface{} `json:"captions"`
IsVr bool `json:"is_vr"`
}

const site = "https://v2.hentaihd.net/"
const videoProvider = "https://amhentai.com/"
const videoProviderAPI = videoProvider + "api/source/"

var reEpisodeURL = regexp.MustCompile(site + `\d+/.+/`)
var reParseURLShow = regexp.MustCompile(site + `anime/[\w-%]+/`)
var reVideoURL = regexp.MustCompile(videoProvider + `v/([^"]+)`)

type extractor struct{}

// New returns a hentaihd extractor.
func New() static.Extractor {
return &extractor{}
}

// Extract data from URL
func (e *extractor) Extract(URL string) ([]*static.Data, error) {
URLs := parseURL(URL)
if len(URLs) == 0 {
return nil, static.ErrURLParseFailed
}

data := []*static.Data{}
for _, u := range URLs {
d, err := extractData(u)
if err != nil {
return nil, utils.Wrap(err, u)
}
data = append(data, d)
}

return data, nil
}

func parseURL(URL string) []string {
if ok := reEpisodeURL.MatchString(URL); ok {
return []string{URL}
}

htmlString, err := request.Get(URL)
if err != nil {
return nil
}

if strings.Contains(URL, "/anime/") {
htmlString = strings.Split(htmlString, `<div class="bixbox"`)[0]
return utils.RemoveAdjDuplicates(reEpisodeURL.FindAllString(htmlString, -1))
}

// contains list of show that need to be derefenced to episode level
htmlString = strings.Split(htmlString, `<div id="sidebar">`)[0]

out := []string{}
for _, anime := range reParseURLShow.FindAllString(htmlString, -1) {
out = append(out, parseURL(anime)...)
}
return out

}

func extractData(URL string) (*static.Data, error) {
htmlString, err := request.Get(URL)
if err != nil {
return nil, err
}

matchedVideo := reVideoURL.FindStringSubmatch(htmlString) // 0=URL 1=ID
if len(matchedVideo) < 2 {
return nil, static.ErrDataSourceParseFailed
}

videoJSON, err := request.PostAsBytesWithHeaders(videoProviderAPI+matchedVideo[1], map[string]string{"Referer": matchedVideo[0]})
if err != nil {
return nil, err
}

video := videoInfo{}
err = json.Unmarshal(videoJSON, &video)
if err != nil {
return nil, err
}

streams := map[string]*static.Stream{}
for i, s := range video.Data {
size, _ := request.Size(s.File, site)
streams[fmt.Sprint(len(video.Data)-i-1)] = &static.Stream{
Type: static.DataTypeVideo,
URLs: []*static.URL{
{
URL: s.File,
Ext: s.Type,
},
},
Quality: s.Label,
Size: size,
}
}

return &static.Data{
Site: site,
Title: html.UnescapeString(utils.GetH1(&htmlString, -1)),
Type: static.DataTypeVideo,
Streams: streams,
URL: URL,
}, nil
}
68 changes: 68 additions & 0 deletions extractors/hentaihd/hentaihd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package hentaihd

import "testing"

func TestParseURL(t *testing.T) {
tests := []struct {
Name string
URL string
Want int
}{
{
Name: "Single Episode Raw",
URL: "https://v2.hentaihd.net/74888/shuumatsu-no-harem-episode-1-raw/",
Want: 1,
}, {
Name: "Single Episode Eng Sub",
URL: "https://v2.hentaihd.net/74923/shuumatsu-no-harem-episode-1-english-subbed/",
Want: 1,
}, {
Name: "Single Episode Preview",
URL: "https://v2.hentaihd.net/74886/shuumatsu-no-harem-previews/",
Want: 1,
}, {
Name: "Series",
URL: "https://v2.hentaihd.net/anime/accelerando-datenshi-tachi-no-sasayaki/",
Want: 11,
}, {
// this is the same logic for all extensions that group shows e.g. /genres/
// its hard to make a test for the other groups since the number of episodes always changes
Name: "Studio",
URL: "https://v2.hentaihd.net/studio/flavors-soft/",
Want: 11,
},
}
for _, tt := range tests {
t.Run(tt.Name, func(t *testing.T) {
URLs := parseURL(tt.URL)
if len(URLs) > tt.Want || len(URLs) == 0 {
t.Errorf("Got: %v - Want: %v", len(URLs), tt.Want)
}
})
}
}

func TestExtract(t *testing.T) {
tests := []struct {
Name string
URL string
Want int
}{
{
Name: "Single Episode",
URL: "https://v2.hentaihd.net/77536/chizuru-chan-kaihatsu-nikki-episodio-6-en-espanol/",
Want: 1,
},
}
for _, tt := range tests {
t.Run(tt.Name, func(t *testing.T) {
data, err := New().Extract(tt.URL)
if err != nil {
t.Error(err)
}
if len(data) > tt.Want || len(data) == 0 {
t.Errorf("Got: %v - Want: %v", len(data), tt.Want)
}
})
}
}
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ func init() {
flag.BoolVar(&config.ShowExtractedData, "j", false, "Show extracted data")
flag.BoolVar(&config.ShowInfo, "i", false, "Show info")
flag.IntVar(&config.Workers, "w", 1, "Number of workers used for downloading")
flag.StringVar(&config.Username, "un", "", "Username for exhentai/forum e hentai")
flag.StringVar(&config.UserPassword, "up", "", "User password for exhentai/forum e hentai")
flag.StringVar(&config.Username, "un", "", "Username for exhentai")
flag.StringVar(&config.UserPassword, "up", "", "User password for exhentai")
}

func download(URL string) {
Expand Down

0 comments on commit e43c8b5

Please sign in to comment.