2 Commits

Author SHA1 Message Date
6c02f72e13 chg: feat: add more audio options (#22) 2024-12-11 14:17:05 -03:00
339db28d5a Feat/Flaresolverr bugfixes (#21)
* chg: fix: add pt-bt to audio detection

* chg: fix: add retry when flaresolverr response is without body

* chg: fix: add back under attack verification
2024-12-11 14:12:12 -03:00
2 changed files with 70 additions and 4 deletions

View File

@@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"net/http/cookiejar"
"net/url"
"strings" "strings"
"sync" "sync"
) )
@@ -19,6 +21,10 @@ type FlareSolverr struct {
initiated bool initiated bool
} }
var (
ErrListSessions = fmt.Errorf("failed to list sessions")
)
func NewFlareSolverr(url string, timeoutMilli int) *FlareSolverr { func NewFlareSolverr(url string, timeoutMilli int) *FlareSolverr {
poolSize := 5 poolSize := 5
httpClient := &http.Client{} httpClient := &http.Client{}
@@ -48,6 +54,14 @@ func (f *FlareSolverr) FillSessionPool() error {
// Pre-initialize the pool with existing sessions // Pre-initialize the pool with existing sessions
sessions, err := f.ListSessions() sessions, err := f.ListSessions()
if err != nil { if err != nil {
// if fail to list sessions, it may not support the sessions.list command
// create new dumb sessions to fill the pool
if err == ErrListSessions {
for len(f.sessionPool) < cap(f.sessionPool) {
f.sessionPool <- "dumb-session"
}
return nil
}
fmt.Println("Failed to list existing FlareSolverr sessions:", err) fmt.Println("Failed to list existing FlareSolverr sessions:", err)
return err return err
} else { } else {
@@ -134,6 +148,9 @@ func (f *FlareSolverr) ListSessions() ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if sessionsResponse["sessions"] == nil {
return nil, ErrListSessions
}
sessions := sessionsResponse["sessions"].([]interface{}) sessions := sessionsResponse["sessions"].([]interface{})
var sessionIDs []string var sessionIDs []string
@@ -172,7 +189,7 @@ type Response struct {
} `json:"solution"` } `json:"solution"`
} }
func (f *FlareSolverr) Get(url string) (io.ReadCloser, error) { func (f *FlareSolverr) Get(_url string) (io.ReadCloser, error) {
// Check if the FlareSolverr instance was initiated // Check if the FlareSolverr instance was initiated
if !f.initiated { if !f.initiated {
return io.NopCloser(bytes.NewReader([]byte(""))), nil return io.NopCloser(bytes.NewReader([]byte(""))), nil
@@ -188,7 +205,7 @@ func (f *FlareSolverr) Get(url string) (io.ReadCloser, error) {
body := map[string]string{ body := map[string]string{
"cmd": "request.get", "cmd": "request.get",
"url": url, "url": _url,
"maxTimeout": fmt.Sprintf("%d", f.maxTimeout), "maxTimeout": fmt.Sprintf("%d", f.maxTimeout),
"session": session, "session": session,
} }
@@ -196,6 +213,7 @@ func (f *FlareSolverr) Get(url string) (io.ReadCloser, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
req, err := http.NewRequest("POST", fmt.Sprintf("%s/v1", f.url), bytes.NewBuffer(jsonBody)) req, err := http.NewRequest("POST", fmt.Sprintf("%s/v1", f.url), bytes.NewBuffer(jsonBody))
if err != nil { if err != nil {
return nil, err return nil, err
@@ -225,6 +243,40 @@ func (f *FlareSolverr) Get(url string) (io.ReadCloser, error) {
return nil, fmt.Errorf("under attack") return nil, fmt.Errorf("under attack")
} }
// Return the response body // If the response body is empty but cookies are present, make a new request
if response.Solution.Response == "" && len(response.Solution.Cookies) > 0 {
// Create a new request with cookies
client := &http.Client{}
cookieJar, err := cookiejar.New(&cookiejar.Options{})
if err != nil {
return nil, err
}
for _, cookie := range response.Solution.Cookies {
cookieJar.SetCookies(&url.URL{Host: cookie.Domain}, []*http.Cookie{
{
Name: cookie.Name,
Value: cookie.Value,
Domain: cookie.Domain,
Path: cookie.Path,
},
})
}
client.Jar = cookieJar
secondReq, err := http.NewRequest("GET", _url, nil)
if err != nil {
return nil, err
}
secondResp, err := client.Do(secondReq)
if err != nil {
return nil, err
}
// Return the body of the second request
return secondResp.Body, nil
}
// Return the original response body
return io.NopCloser(bytes.NewReader([]byte(response.Solution.Response))), nil return io.NopCloser(bytes.NewReader([]byte(response.Solution.Response))), nil
} }

View File

@@ -1,10 +1,14 @@
package schema package schema
import "strings"
type Audio string type Audio string
const ( const (
AudioPortuguese = "Português" AudioPortuguese = "Português"
AudioPortuguese2 = "Portugues" AudioPortuguese2 = "Portugues"
AudioPortuguese3 = "PT-BR"
AudioPortuguese4 = "Dublado"
AudioEnglish = "Inglês" AudioEnglish = "Inglês"
AudioEnglish2 = "Ingles" AudioEnglish2 = "Ingles"
AudioSpanish = "Espanhol" AudioSpanish = "Espanhol"
@@ -28,11 +32,14 @@ const (
AudioThai = "Tailandês" AudioThai = "Tailandês"
AudioThai2 = "Tailandes" AudioThai2 = "Tailandes"
AudioTurkish = "Turco" AudioTurkish = "Turco"
AudioHindi = "Hindi"
) )
var AudioList = []Audio{ var AudioList = []Audio{
AudioPortuguese, AudioPortuguese,
AudioPortuguese2, AudioPortuguese2,
AudioPortuguese3,
AudioPortuguese4,
AudioEnglish, AudioEnglish,
AudioEnglish2, AudioEnglish2,
AudioSpanish, AudioSpanish,
@@ -56,6 +63,7 @@ var AudioList = []Audio{
AudioThai, AudioThai,
AudioThai2, AudioThai2,
AudioTurkish, AudioTurkish,
AudioHindi,
} }
func (a Audio) String() string { func (a Audio) String() string {
@@ -64,7 +72,7 @@ func (a Audio) String() string {
func GetAudioFromString(s string) *Audio { func GetAudioFromString(s string) *Audio {
for _, a := range AudioList { for _, a := range AudioList {
if string(a) == s { if strings.EqualFold(string(a), s) {
return &a return &a
} }
} }
@@ -77,6 +85,10 @@ func (a Audio) toTag() string {
return "brazilian" return "brazilian"
case AudioPortuguese2: case AudioPortuguese2:
return "brazilian" return "brazilian"
case AudioPortuguese3:
return "brazilian"
case AudioPortuguese4:
return "brazilian"
case AudioEnglish: case AudioEnglish:
return "eng" return "eng"
case AudioEnglish2: case AudioEnglish2:
@@ -123,6 +135,8 @@ func (a Audio) toTag() string {
return "tha" return "tha"
case AudioTurkish: case AudioTurkish:
return "tur" return "tur"
case AudioHindi:
return "hin"
default: default:
return "" return ""
} }