//go:build windows
package yu_proxy_pool
import (
yu_curl "gogs.qqck.cn/s/tools/curl"
yu_proxy "gogs.qqck.cn/s/tools/proxy"
yu_strconv "gogs.qqck.cn/s/tools/strconv"
"strings"
"sync"
"time"
)
// Pool 代理池
type Pool struct {
// 并发锁
lock sync.Mutex
// 代理池
list []*pool_item
// 代理API
// 提取链接或直连地址
url string
// 0:返回代理列表,1:直连地址,默认为0
url_type byte
// 代理有效时长,默认为30秒,单位:秒
valid_time int64
// 代理池内有效时间低于该值就视为无效代理,默认为10秒,单位:秒
failure_time int64
// 0:http/https,1:socks5
_type byte
// 认证账号密码,如果代理需要身份认证的情况下填写
user, pass string
domain bool
// 访问代理API的提取最少间隔,默认不限制
request_space int64
// 最后调用时间,单位:秒
time_last int64
// 单个 IP 最多使用次数,默认为:1
get_max int
// 已提取计数
get_count int
response string // 最后提取信息
}
type pool_item struct {
*yu_proxy.Info
i int // 已使用计数
}
func New() (t *Pool) {
t = &Pool{}
t.list = make([]*pool_item, 0)
t.SetUrlList().SetValidTime(30).SetFailureTime(10).SetHttp().SetDomain(true).SetGetMax(1)
return
}
// -----------------------------------------------------------------------------------------------------API
// SetUrl 设置提取代理api链接
func (t *Pool) SetUrl(v string) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.url = v
return t
}
// GetUrl 获取提取代理api链接
func (t *Pool) GetUrl() string {
t.lock.Lock()
defer t.lock.Unlock()
return t.url
}
// SetUrlList 设置提取代理 api 链接 返回类型为:代理列表
func (t *Pool) SetUrlList() *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.url_type = 0
return t
}
// SetUrlTunnel 设置提取代理 api 链接 返回类型为:隧道代理,直连地址
func (t *Pool) SetUrlTunnel() *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.url_type = 1
return t
}
// SetValidTime 设置代理有效时长,默认为30秒,单位:秒
func (t *Pool) SetValidTime(v int64) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
if v < 1 {
v = 30
}
t.valid_time = v
return t
}
// GetValidTime 获取代理有效时长,单位:秒
func (t *Pool) GetValidTime() int64 {
t.lock.Lock()
defer t.lock.Unlock()
return t.valid_time
}
// SetFailureTime 设置代理池内有效时间低于该值就视为无效代理,默认为10秒,单位:秒
func (t *Pool) SetFailureTime(v int64) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
if v < 1 {
v = 10
}
t.failure_time = v
return t
}
// GetFailureTime 获取代理池内有效时间低于该值就视为无效代理,单位:秒
func (t *Pool) GetFailureTime() int64 {
t.lock.Lock()
defer t.lock.Unlock()
return t.failure_time
}
// SetHttp 设置代理类型为:http/https
func (t *Pool) SetHttp() *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t._type = 0
return t
}
// SetSocks5 设置代理类型为:socks5
func (t *Pool) SetSocks5() *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t._type = 1
return t
}
// SetUser 设置代理认证账号,如果代理需要身份认证的情况下填写
func (t *Pool) SetUser(v string) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.user = v
return t
}
// GetUser 获取代理认证账号
func (t *Pool) GetUser() string {
t.lock.Lock()
defer t.lock.Unlock()
return t.user
}
// SetPass 设置代理认证密码,如果代理需要身份认证的情况下填写
func (t *Pool) SetPass(v string) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.pass = v
return t
}
// GetPass 获取代理认证密码
func (t *Pool) GetPass() string {
t.lock.Lock()
defer t.lock.Unlock()
return t.pass
}
// SetDomain
//
// @Description: 设置是否由代理解析域名,默认:true
func (t *Pool) SetDomain(value bool) *Pool {
t.domain = value
return t
}
// SetRequestSpace 设置访问代理API的提取最少间隔,默认不限制
func (t *Pool) SetRequestSpace(v int64) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.request_space = v
return t
}
// GetRequestSpace 获取访问代理API的提取最少间隔
func (t *Pool) GetRequestSpace() int64 {
t.lock.Lock()
defer t.lock.Unlock()
return t.request_space
}
// SetGetMax 单个 IP 最多使用次数,默认为:1
func (t *Pool) SetGetMax(n int) *Pool {
t.lock.Lock()
defer t.lock.Unlock()
t.get_max = n
return t
}
// Size 取当前IP池内剩余IP数
func (t *Pool) Size() int {
t.lock.Lock()
defer t.lock.Unlock()
return len(t.list)
}
// Clear 清空代理池提取的代理信息
func (t *Pool) Clear() {
t.lock.Lock()
defer t.lock.Unlock()
t.list = make([]*pool_item, 0)
}
// -----------------------------------------------------------------------------------------------------Get
// Get 计次提取
func (t *Pool) Get() *yu_proxy.Info {
t.lock.Lock()
defer t.lock.Unlock()
if t.get_max < 1 {
return nil
}
var j_get bool
_get:
for len(t.list) > 0 {
if !t.list[0].IsValid() {
t.list = t.list[1:]
continue
}
if t.list[0].i >= t.get_max {
t.list = t.list[1:]
continue
}
t.list[0].i++
return t.list[0].Copy()
}
if j_get = !j_get; j_get && t.request_url() {
goto _get
}
return nil
}
// GetCheck 计次提取并使用校验函数校验是否可用(只在从列表提取新的IP的时候才会校验)
func (t *Pool) GetCheck(on func(*yu_proxy.Info) bool) *yu_proxy.Info {
if on == nil {
return t.Get()
}
var j_info *pool_item
j_check := false
t.lock.Lock()
if t.get_max > 0 {
var j_get bool
_get:
for len(t.list) > 0 {
if !t.list[0].IsValid() {
t.list = t.list[1:]
continue
}
if t.list[0].i >= t.get_max {
t.list = t.list[1:]
continue
}
if t.list[0].i == 0 {
j_info, j_check, t.list = t.list[0], true, t.list[1:]
break
}
t.list[0].i++
j_info = t.list[0]
break
}
if j_get = !j_get; j_info == nil && j_get && t.request_url() {
goto _get
}
}
t.lock.Unlock()
if j_info == nil {
return nil
}
if !j_check {
return j_info.Copy()
}
if !on(j_info.Info) {
return nil
}
j_info.i++
t.lock.Lock()
t.list = append(t.list, nil)
for j_i := len(t.list) - 1; j_i > 0; j_i-- {
t.list[j_i] = t.list[j_i-1]
}
t.list[0] = j_info
t.lock.Unlock()
return j_info.Copy()
}
// GetCheckEx 计次提取并使用校验函数校验是否可用(不管是不是从列表提取新的IP都进行校验)
func (t *Pool) GetCheckEx(on func(*yu_proxy.Info) bool) *yu_proxy.Info {
if on == nil {
return t.Get()
}
var j_info *pool_item
t.lock.Lock()
if t.get_max > 0 {
var j_get bool
_get:
for len(t.list) > 0 {
if !t.list[0].IsValid() {
t.list = t.list[1:]
continue
}
if t.list[0].i >= t.get_max {
t.list = t.list[1:]
continue
}
j_info = t.list[0]
break
}
if j_get = !j_get; j_info == nil && j_get && t.request_url() {
goto _get
}
}
t.lock.Unlock()
if j_info == nil {
return nil
}
if !on(j_info.Info) {
return nil
}
j_info.i++
t.lock.Lock()
t.list = append(t.list, nil)
for j_i := len(t.list) - 1; j_i > 0; j_i-- {
t.list[j_i] = t.list[j_i-1]
}
t.list[0] = j_info
t.lock.Unlock()
return j_info.Copy()
}
func (t *Pool) GetResponse() string {
return t.response
}
func (t *Pool) request_url() bool {
if t.url_type == 0 {
j_time := time.Now().Unix()
if j_time-t.time_last < t.request_space {
return false
}
j_curl := yu_curl.NewRequest().SetSslVerifyHost(yu_curl.SSLVERSION_DEFAULT).SetSslVerifyPeer(false).SetTimeout(1000 * 30)
defer j_curl.Close()
if j_curl.Get(t.url).RespErr() != nil || j_curl.RespStatusCode() != 200 {
return false
}
t.response = j_curl.RespBodyS()
j_proxy_list := []string(nil)
if strings.Index(t.response, "\r\n") > -1 {
j_proxy_list = strings.Split(t.response, "\r\n")
} else if strings.Index(t.response, "\\r\\n") > -1 {
j_proxy_list = strings.Split(t.response, "\\r\\n")
} else if strings.Index(t.response, "\r") > -1 {
j_proxy_list = strings.Split(t.response, "\r")
} else if strings.Index(t.response, "\\r") > -1 {
j_proxy_list = strings.Split(t.response, "\\r")
} else if strings.Index(t.response, "\n") > -1 {
j_proxy_list = strings.Split(t.response, "\n")
} else if strings.Index(t.response, "\\n") > -1 {
j_proxy_list = strings.Split(t.response, "\\n")
} else if strings.Index(t.response, " ") > -1 {
j_proxy_list = strings.Split(t.response, " ")
} else if strings.Index(t.response, "
") > -1 {
j_proxy_list = strings.Split(t.response, "
")
} else {
j_proxy_list = append(j_proxy_list, t.response)
}
t.time_last, j_time = j_time, j_time+t.valid_time-t.failure_time
for j_i := 0; j_i < len(j_proxy_list); j_i++ {
j_proxy_info := &pool_item{Info: yu_proxy.NewInfo().SetAuthorization(t.user, t.pass)}
if strings.Index(j_proxy_list[j_i], " ") > -1 {
if j_ip_port := strings.Split(j_proxy_list[j_i], " "); len(j_ip_port) == 3 {
j_proxy_list[j_i] = j_ip_port[0]
j_proxy_info.User, j_proxy_info.Pass = j_ip_port[1], j_ip_port[2]
}
}
if strings.Count(j_proxy_list[j_i], ".") == 3 && strings.Count(j_proxy_list[j_i], ":") == 1 {
j_addr := strings.Split(j_proxy_list[j_i], ":")
j_proxy_info.Host, j_proxy_info.Port, j_proxy_info.Type, j_proxy_info.Timeout, j_proxy_info.Domain = j_addr[0], yu_strconv.ParseInt(j_addr[1]), t._type, j_time, t.domain
t.list = append(t.list, j_proxy_info)
}
}
return len(t.list) > 0
} else if t.url_type == 1 {
j_len := 100
t.list = make([]*pool_item, j_len)
for j_num := 0; j_num < j_len; j_num++ {
t.list[j_num] = &pool_item{}
t.list[j_num].Info = yu_proxy.NewInfo()
t.list[j_num].Host = t.url
t.list[j_num].User = t.user
t.list[j_num].Pass = t.pass
t.list[j_num].Type = t._type
t.list[j_num].Timeout = -1
t.list[j_num].Domain = t.domain
}
return true
}
return false
}