refactor, bypass dns filtering using google dns, yts host resolution using qwant
This commit is contained in:
81
ytsclient/yts_resolver.go
Normal file
81
ytsclient/yts_resolver.go
Normal file
@ -0,0 +1,81 @@
|
||||
package ytsclient
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
r "github.com/levigross/grequests"
|
||||
)
|
||||
|
||||
|
||||
var ErrNotFound = errors.New("not found")
|
||||
|
||||
type SearchResponse struct {
|
||||
Status string `json:"status"`
|
||||
Data struct {
|
||||
Query struct {
|
||||
Locale string `json:"locale"`
|
||||
Query string `json:"query"`
|
||||
Offset int `json:"offset"`
|
||||
} `json:"query"`
|
||||
Cache struct {
|
||||
Key string `json:"key"`
|
||||
Created int `json:"created"`
|
||||
Expiration int `json:"expiration"`
|
||||
Status string `json:"status"`
|
||||
Age int `json:"age"`
|
||||
Version int `json:"version"`
|
||||
System string `json:"system"`
|
||||
Mode int `json:"mode"`
|
||||
} `json:"cache"`
|
||||
Result struct {
|
||||
Total int `json:"total"`
|
||||
Items []struct {
|
||||
Title string `json:"title"`
|
||||
Favicon string `json:"favicon"`
|
||||
URL string `json:"url"`
|
||||
Source string `json:"source"`
|
||||
Desc string `json:"desc"`
|
||||
ID string `json:"_id"`
|
||||
Score int `json:"score"`
|
||||
Position int `json:"position"`
|
||||
} `json:"items"`
|
||||
Filters struct {
|
||||
Freshness struct {
|
||||
Label string `json:"label"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Selected string `json:"selected"`
|
||||
Values []struct {
|
||||
Value string `json:"value"`
|
||||
Label string `json:"label"`
|
||||
Translate bool `json:"translate"`
|
||||
} `json:"values"`
|
||||
} `json:"freshness"`
|
||||
} `json:"filters"`
|
||||
Ads []interface{} `json:"ads"`
|
||||
} `json:"result"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
|
||||
func ResolveYts() (url string, err error) {
|
||||
res, err := r.Get("https://api.qwant.com/api/search/web?count=10&q=yts&t=web&uiv=4", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sr := &SearchResponse{}
|
||||
if err := res.JSON(sr); err != nil{
|
||||
return "", err
|
||||
}
|
||||
if len(sr.Data.Result.Items) == 0 {
|
||||
return "", ErrNotFound
|
||||
}
|
||||
for _, v := range sr.Data.Result.Items {
|
||||
if !strings.HasPrefix(v.URL, "https://yts.") {
|
||||
continue
|
||||
}
|
||||
return v.URL, nil
|
||||
}
|
||||
return "", ErrNotFound
|
||||
}
|
@ -1,31 +1,56 @@
|
||||
package ytsclient
|
||||
|
||||
import (
|
||||
r "github.com/levigross/grequests"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
r "github.com/levigross/grequests"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
type client struct {
|
||||
url string
|
||||
list string
|
||||
get string
|
||||
suggestions string
|
||||
}
|
||||
|
||||
var (
|
||||
defaultHost = "https://yts.am"
|
||||
apiPrefix = "/api/v2"
|
||||
dnsServer = "8.8.4.4"
|
||||
)
|
||||
|
||||
const (
|
||||
list = "/list_movies.json"
|
||||
get = "/movie_details.json"
|
||||
suggestions = "/movie_suggestions.json"
|
||||
)
|
||||
|
||||
func NewClient(url string) *Client {
|
||||
if url == "" {
|
||||
url = "https://yts.am/api/v2"
|
||||
|
||||
func NewClient(host ...string) Client {
|
||||
if len(host) == 0 || host[0] == "" {
|
||||
if host, err := ResolveYts(); err == nil {
|
||||
defaultHost = strings.TrimSuffix(host, "/")
|
||||
}
|
||||
host = []string{defaultHost}
|
||||
}
|
||||
return &Client{url, url + list, url + get, url + suggestions}
|
||||
d := net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
net.DefaultResolver = &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return d.DialContext(ctx, network, fmt.Sprintf("%s:53", dnsServer))
|
||||
},
|
||||
}
|
||||
return &client{host[0], host[0] + apiPrefix + list, host[0] + apiPrefix + get, host[0] + apiPrefix + suggestions}
|
||||
}
|
||||
|
||||
func (y *Client) List(params *ListParams) ([]Movie, error) {
|
||||
func (y *client) List(params *ListParams) ([]Movie, error) {
|
||||
if params == nil {
|
||||
params = &ListParams{}
|
||||
}
|
||||
@ -40,7 +65,7 @@ func (y *Client) List(params *ListParams) ([]Movie, error) {
|
||||
return resp.Data.Movies, nil
|
||||
}
|
||||
|
||||
func (y *Client) Search(search string, params *ListParams) ([]Movie, error) {
|
||||
func (y *client) Search(search string, params *ListParams) ([]Movie, error) {
|
||||
if params == nil {
|
||||
params = &ListParams{}
|
||||
}
|
||||
@ -56,7 +81,7 @@ func (y *Client) Search(search string, params *ListParams) ([]Movie, error) {
|
||||
return resp.Data.Movies, nil
|
||||
}
|
||||
|
||||
func (y *Client) Get(id string, params *MovieParams) (Movie, error) {
|
||||
func (y *client) Get(id string, params *MovieParams) (Movie, error) {
|
||||
if params == nil {
|
||||
params = &MovieParams{}
|
||||
}
|
||||
@ -73,7 +98,7 @@ func (y *Client) Get(id string, params *MovieParams) (Movie, error) {
|
||||
return resp.Data.Movie, nil
|
||||
}
|
||||
|
||||
func (y *Client) Suggestions(id int) ([]Movie, error) {
|
||||
func (y *client) Suggestions(id int) ([]Movie, error) {
|
||||
ro := &r.RequestOptions{
|
||||
Params: map[string]string{"movie_id": strconv.Itoa(id)},
|
||||
}
|
||||
@ -87,3 +112,10 @@ func (y *Client) Suggestions(id int) ([]Movie, error) {
|
||||
}
|
||||
return resp.Data.Movies, nil
|
||||
}
|
||||
|
||||
type Client interface {
|
||||
List(params *ListParams) ([]Movie, error)
|
||||
Search(search string, params *ListParams) ([]Movie, error)
|
||||
Get(id string, params *MovieParams) (Movie, error)
|
||||
Suggestions(id int) ([]Movie, error)
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package ytsclient
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -24,31 +26,45 @@ var (
|
||||
name string
|
||||
test func(t *testing.T)
|
||||
}{{
|
||||
name: "no dns server",
|
||||
test: func(t *testing.T) {
|
||||
dnsServer = "192.168.1.1"
|
||||
yc := NewClient()
|
||||
ms, err := yc.List(nil)
|
||||
require.Error(t, err)
|
||||
t.Log(err)
|
||||
require.Nil(t, ms)
|
||||
dnsServer = "8.8.8.8"
|
||||
},
|
||||
},{
|
||||
name: "default url",
|
||||
test: func(t *testing.T) {
|
||||
c := NewClient("")
|
||||
assert.Equal(t, "https://yts.am/api/v2", c.url)
|
||||
yc := NewClient()
|
||||
c, ok := yc.(*client)
|
||||
require.True(t, ok)
|
||||
assert.Contains(t, c.url,"https://yts.")
|
||||
},
|
||||
}, {
|
||||
name: "list",
|
||||
test: func(t *testing.T) {
|
||||
c := NewClient("")
|
||||
c := NewClient()
|
||||
_, err := c.List(nil)
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
}, {
|
||||
name: "search",
|
||||
test: func(t *testing.T) {
|
||||
c := NewClient("")
|
||||
c := NewClient()
|
||||
l, err := c.Search("South Park", nil)
|
||||
assert.NoError(t, err)
|
||||
require.NotEmpty(t, l)
|
||||
southParkMovie = l[0]
|
||||
assert.Equal(t, southParkID, strconv.Itoa(southParkMovie.ID))
|
||||
},
|
||||
}, {
|
||||
name: "list 50",
|
||||
test: func(t *testing.T) {
|
||||
c := NewClient("")
|
||||
c := NewClient()
|
||||
p := &ListParams{Limit: 50}
|
||||
l, err := c.List(p)
|
||||
assert.NoError(t, err)
|
||||
@ -57,7 +73,7 @@ var (
|
||||
}, {
|
||||
name: "get",
|
||||
test: func(t *testing.T) {
|
||||
c := NewClient("")
|
||||
c := NewClient()
|
||||
m, err := c.Get(southParkID, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, m)
|
||||
@ -66,6 +82,7 @@ var (
|
||||
}, {
|
||||
name: "magnet",
|
||||
test: func(t *testing.T) {
|
||||
require.NotEmpty(t, southParkMovie.Torrents)
|
||||
m, err := southParkMovie.Magnet(southParkMovie.Torrents[1])
|
||||
assert.NoError(t, err)
|
||||
// Don't test trackers list nor YTS extension
|
||||
@ -76,7 +93,7 @@ var (
|
||||
}, {
|
||||
name: "suggestions",
|
||||
test: func(t *testing.T) {
|
||||
c := NewClient("")
|
||||
c := NewClient()
|
||||
s, err := c.Suggestions(10)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, s)
|
||||
@ -89,3 +106,12 @@ func TestYTSClient(t *testing.T) {
|
||||
t.Run(test.name, test.test)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestResolveYts(t *testing.T) {
|
||||
defaultHost = ""
|
||||
host, err := ResolveYts()
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, host, "https://yts.")
|
||||
t.Log(host)
|
||||
}
|
||||
|
Reference in New Issue
Block a user