feat 添加coach 客户端

This commit is contained in:
timerzz 2024-12-06 17:07:14 +08:00
parent ab2c85f42f
commit ea5315348b
7 changed files with 86 additions and 22 deletions

View File

@ -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

View File

@ -14,19 +14,50 @@ import (
proxy2 "github.com/timerzz/proxypool/pkg/proxy" proxy2 "github.com/timerzz/proxypool/pkg/proxy"
) )
type US struct { const (
pool *proxy.ProxyPool BaseUrl_Coach = "https://www.coach.com"
defaultTimeOut time.Duration BaseUrl_CoachOutlet = "https://www.coachoutlet.com"
)
type USClientBuilder struct {
pool *proxy.ProxyPool
} }
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
View 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"},
})
}

View File

@ -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{})
} }

View File

@ -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)
}