构建上传工具 / build (push) Successful in 1m12s
- 实现了抖音API请求失败时的自动重试逻辑,间隔100毫秒 - 添加了上下文取消支持,避免无限重试 - 将HTTP客户端改为全局变量,提升性能和连接复用 - 前端上传线程数限制从100调整为500 - 更新类型声明以符合最新Go语言规范
149 lines
2.7 KiB
Go
149 lines
2.7 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"dypid-client/internal/config"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
var httpClient = &http.Client{
|
|
Transport: &http.Transport{
|
|
MaxIdleConns: 500,
|
|
MaxIdleConnsPerHost: 500,
|
|
IdleConnTimeout: 30 * time.Minute,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
|
|
var limit chan struct{}
|
|
|
|
func init() {
|
|
//限制同时请求数为500
|
|
limit = make(chan struct{}, 500)
|
|
}
|
|
|
|
// InitConn 创建连接池
|
|
func InitConn() {
|
|
wg := &sync.WaitGroup{}
|
|
|
|
for range 10 {
|
|
wg.Go(func() {
|
|
for range 50 {
|
|
resp, err := httpClient.Get(config.APPConfig.Url + "/api/test")
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
defer func() {
|
|
io.Copy(io.Discard, resp.Body)
|
|
resp.Body.Close()
|
|
}()
|
|
}
|
|
})
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func UploadDataToServer(ctx context.Context, data string) error {
|
|
limit <- struct{}{}
|
|
defer func() {
|
|
<-limit
|
|
}()
|
|
|
|
//根据账号是否有视频判断要存储的token
|
|
params := url.Values{}
|
|
secUserId := strings.Split(data, "----")[1]
|
|
hasVideo, err := CheckHasVideo(secUserId)
|
|
if err != nil {
|
|
for err != nil {
|
|
fmt.Println("抖音请求api重试")
|
|
//定时器定时100毫秒
|
|
ticker := time.NewTicker(100 * time.Millisecond)
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return err
|
|
case <-ticker.C:
|
|
ticker.Stop()
|
|
hasVideo, err = CheckHasVideo(secUserId)
|
|
}
|
|
}
|
|
}
|
|
if hasVideo {
|
|
params.Set("token", config.APPConfig.HasVideoToken)
|
|
} else {
|
|
params.Set("token", config.APPConfig.NoVideoToken)
|
|
}
|
|
|
|
params.Set("data", data)
|
|
|
|
//http://127.0.0.1:8080/api/data?token=123456&data=123456
|
|
request, err := http.NewRequest(
|
|
"POST",
|
|
config.APPConfig.Url+"/api/data?"+params.Encode(),
|
|
nil,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
request.WithContext(ctx)
|
|
|
|
resp, err := httpClient.Do(request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
io.Copy(io.Discard, resp.Body)
|
|
resp.Body.Close()
|
|
}()
|
|
|
|
return err
|
|
}
|
|
|
|
var douYinClient = &http.Client{}
|
|
|
|
func CheckHasVideo(secUserId string) (bool, error) {
|
|
req, err := http.NewRequest(
|
|
"GET",
|
|
"https://imdesktop.douyin.com/aweme/v1/web/user/profile/other/?sec_user_id="+secUserId,
|
|
nil,
|
|
)
|
|
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false, err
|
|
}
|
|
req.Header.Add("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
|
|
req.Header.Add("Accept", "*/*")
|
|
req.Header.Add("Host", "imdesktop.douyin.com")
|
|
req.Header.Add("Connection", "keep-alive")
|
|
|
|
res, err := douYinClient.Do(req)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false, err
|
|
}
|
|
defer res.Body.Close()
|
|
|
|
body, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false, err
|
|
}
|
|
|
|
if gjson.Get(string(body), "user.aweme_count").Int() > 0 {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|