feat 添加coach 客户端
This commit is contained in:
parent
ab2c85f42f
commit
ea5315348b
@ -4,12 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/bytedance/sonic"
|
"github.com/bytedance/sonic"
|
||||||
"github.com/cloudwego/hertz/pkg/app/client"
|
"github.com/cloudwego/hertz/pkg/app/client"
|
||||||
"github.com/cloudwego/hertz/pkg/network/standard"
|
"github.com/cloudwego/hertz/pkg/network/standard"
|
||||||
"github.com/cloudwego/hertz/pkg/protocol"
|
"github.com/cloudwego/hertz/pkg/protocol"
|
||||||
"github.com/corpix/uarand"
|
"github.com/corpix/uarand"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type XMacHeader string
|
type XMacHeader string
|
@ -14,19 +14,50 @@ import (
|
|||||||
proxy2 "github.com/timerzz/proxypool/pkg/proxy"
|
proxy2 "github.com/timerzz/proxypool/pkg/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type US struct {
|
const (
|
||||||
|
BaseUrl_Coach = "https://www.coach.com"
|
||||||
|
BaseUrl_CoachOutlet = "https://www.coachoutlet.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
type USClientBuilder struct {
|
||||||
pool *proxy.ProxyPool
|
pool *proxy.ProxyPool
|
||||||
defaultTimeOut time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func USClient(pool *proxy.ProxyPool) *US {
|
func US(pool *proxy.ProxyPool) *USClientBuilder {
|
||||||
return &US{
|
return &USClientBuilder{
|
||||||
pool: pool,
|
pool: pool,
|
||||||
defaultTimeOut: 10 * time.Minute,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryRequest(ctx context.Context, urlPath string, respData any, proxyGetter func() proxy2.Proxy) error {
|
func (u *USClientBuilder) Coach() USClient {
|
||||||
|
return &us{
|
||||||
|
pool: u.pool,
|
||||||
|
defaultTimeOut: 10 * time.Minute,
|
||||||
|
baseUrl: BaseUrl_Coach,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *USClientBuilder) CoachOutlet() USClient {
|
||||||
|
return &us{
|
||||||
|
pool: u.pool,
|
||||||
|
defaultTimeOut: 10 * time.Minute,
|
||||||
|
baseUrl: BaseUrl_CoachOutlet,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type USClient interface {
|
||||||
|
RequestInventory(ctx context.Context, pid string) (inv Inventory, err error)
|
||||||
|
RequestProductDetail(ctx context.Context, pid string) (data ProductData, err error)
|
||||||
|
ViewAllBags(ctx context.Context, page int) (resp PageDataResponse, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type us struct {
|
||||||
|
pool *proxy.ProxyPool
|
||||||
|
defaultTimeOut time.Duration
|
||||||
|
baseUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryRequest(ctx context.Context, base, urlPath string, respData any, proxyGetter func() proxy2.Proxy) error {
|
||||||
for p := proxyGetter(); p != nil; p = proxyGetter() {
|
for p := proxyGetter(); p != nil; p = proxyGetter() {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@ -37,7 +68,7 @@ func tryRequest(ctx context.Context, urlPath string, respData any, proxyGetter f
|
|||||||
default:
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
resp, err := callByProxy(ctx, p, urlPath, respData)
|
resp, err := callByProxy(ctx, p, base, urlPath, respData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug(err.Error())
|
slog.Debug(err.Error())
|
||||||
continue
|
continue
|
||||||
@ -51,7 +82,7 @@ func tryRequest(ctx context.Context, urlPath string, respData any, proxyGetter f
|
|||||||
return errors.New("未获取到可用的代理")
|
return errors.New("未获取到可用的代理")
|
||||||
}
|
}
|
||||||
|
|
||||||
func callByProxy(ctx context.Context, p proxy2.Proxy, urlPath string, result any) (*resty.Response, error) {
|
func callByProxy(ctx context.Context, p proxy2.Proxy, base, urlPath string, result any) (*resty.Response, error) {
|
||||||
addr, err := proxy.UrlToMetadata(urlPath)
|
addr, err := proxy.UrlToMetadata(urlPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -66,7 +97,7 @@ func callByProxy(ctx context.Context, p proxy2.Proxy, urlPath string, result any
|
|||||||
|
|
||||||
var cli = restry_pool.GetRestyClient(conn)
|
var cli = restry_pool.GetRestyClient(conn)
|
||||||
defer restry_pool.PutRestyClient(cli)
|
defer restry_pool.PutRestyClient(cli)
|
||||||
return cli.R().SetResult(result).Get(urlPath)
|
return cli.SetBaseURL(base).R().SetResult(result).Get(urlPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Inventory struct {
|
type Inventory struct {
|
||||||
@ -88,12 +119,12 @@ type InventoryResponse struct {
|
|||||||
} `json:"inventory"`
|
} `json:"inventory"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *US) RequestInventory(ctx context.Context, pid string) (inv Inventory, err error) {
|
func (c *us) RequestInventory(ctx context.Context, pid string) (inv Inventory, err error) {
|
||||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
var resp InventoryResponse
|
var resp InventoryResponse
|
||||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/inventory?vgId=%s&includeVariantData=false", url.QueryEscape(pid))
|
urlPath := fmt.Sprintf("/api/inventory?vgId=%s&includeVariantData=false", url.QueryEscape(pid))
|
||||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
err = tryRequest(sctx, c.baseUrl, urlPath, &resp, c.pool.RandomIterator())
|
||||||
inv = resp.Inventory.InventoryInfo
|
inv = resp.Inventory.InventoryInfo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -123,12 +154,12 @@ type ProductDataResponse struct {
|
|||||||
ProductData []*ProductData `json:"productsData"`
|
ProductData []*ProductData `json:"productsData"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *US) RequestProductDetail(ctx context.Context, pid string) (data ProductData, err error) {
|
func (c *us) RequestProductDetail(ctx context.Context, pid string) (data ProductData, err error) {
|
||||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
var resp ProductDataResponse
|
var resp ProductDataResponse
|
||||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/get-products?ids=%s&includeInventory=false", url.QueryEscape(pid))
|
urlPath := fmt.Sprintf("/api/get-products?ids=%s&includeInventory=false", url.QueryEscape(pid))
|
||||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
err = tryRequest(sctx, c.baseUrl, urlPath, &resp, c.pool.RandomIterator())
|
||||||
if len(resp.ProductData) == 0 && err != nil {
|
if len(resp.ProductData) == 0 && err != nil {
|
||||||
err = fmt.Errorf("获取详情信息为空")
|
err = fmt.Errorf("获取详情信息为空")
|
||||||
return
|
return
|
||||||
@ -191,13 +222,13 @@ type Sales struct {
|
|||||||
DecimalPrice string `json:"decimalPrice"`
|
DecimalPrice string `json:"decimalPrice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *US) ViewAllBags(ctx context.Context, page int) (resp PageDataResponse, err error) {
|
func (c *us) ViewAllBags(ctx context.Context, page int) (resp PageDataResponse, err error) {
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/get-shop/bags/view-all?page=%d", page)
|
urlPath := fmt.Sprintf("/api/get-shop/bags/view-all?page=%d", page)
|
||||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
err = tryRequest(sctx, c.baseUrl, urlPath, &resp, c.pool.RandomIterator())
|
||||||
return
|
return
|
||||||
}
|
}
|
15
pkg/proxy/proxy_test.go
Normal file
15
pkg/proxy/proxy_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestNewProxyPool(t *testing.T) {
|
||||||
|
NewProxyPool(&Option{
|
||||||
|
Subscribes: []string{
|
||||||
|
"https://us.timerzz.com:26106/vmess/sub",
|
||||||
|
"https://us.timerzz.com:26106/trojan/sub",
|
||||||
|
"https://us.timerzz.com:26106/ssr/sub",
|
||||||
|
"https://us.timerzz.com:26106/ss/sub",
|
||||||
|
},
|
||||||
|
Clash: []string{"https://us.timerzz.com:26106/clash/proxies"},
|
||||||
|
})
|
||||||
|
}
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetDevDB() (*gorm.DB, error) {
|
func GetDevDB() (*gorm.DB, error) {
|
||||||
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", "192.168.31.55", "timerzz", "zhhg1997", "kedaya", "5432")
|
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", "192.168.31.55", "timerzz", "zhhg1997", "kedaya_dev", "5432")
|
||||||
return gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
return gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package storage
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
v2 "gitea.timerzz.com/kedaya_haitao/common/structs/v2"
|
v2 "gitea.timerzz.com/kedaya_haitao/common/structs/v2"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -86,3 +87,19 @@ func TestFullImage(t *testing.T) {
|
|||||||
//}
|
//}
|
||||||
//fmt.Printf("以下共%d个pid未找到: %s", len(nots), nots)
|
//fmt.Printf("以下共%d个pid未找到: %s", len(nots), nots)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProviderArticleApi_FindByPid(t *testing.T) {
|
||||||
|
db, err := GetDevDB()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var a v2.ProviderArticle
|
||||||
|
now := time.Now()
|
||||||
|
n := now.String()
|
||||||
|
fmt.Println(n)
|
||||||
|
tt := time.Now().Add(-30 * time.Minute)
|
||||||
|
s := tt.String()
|
||||||
|
fmt.Println(s)
|
||||||
|
db.Preload("HistoryAts", "created_at > ?", tt).First(&a, "pid=?", "CX607-IMXB8")
|
||||||
|
fmt.Println(a)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user