238 lines
5.3 KiB
Go
238 lines
5.3 KiB
Go
package cwclient
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func init() {
|
|
log.SetFlags(log.Llongfile | log.LstdFlags)
|
|
}
|
|
|
|
// Callback 发送代理连接获取内容后的回调函数
|
|
type Callback struct {
|
|
label string
|
|
hash string
|
|
Do func(tid, content string, err error)
|
|
}
|
|
|
|
// Client 客户端
|
|
type Client struct {
|
|
chromeProxyAddr string
|
|
|
|
register sync.Map
|
|
|
|
host string
|
|
port string
|
|
|
|
server *http.Server
|
|
listener net.Listener
|
|
lock sync.Mutex
|
|
}
|
|
|
|
// Label 区分不同任务类型
|
|
type Label struct {
|
|
label string
|
|
|
|
conditionJS string
|
|
conditionlock sync.Mutex
|
|
|
|
cli *Client
|
|
}
|
|
|
|
// GetHash 根据label获取hash路径
|
|
func (l *Label) GetHash(label string) string {
|
|
if cb, ok := l.cli.register.Load(label); ok {
|
|
return cb.(Callback).hash
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetLabel 根据hash获取路径label
|
|
func (l *Label) GetLabel(hash string) string {
|
|
if cb, ok := l.cli.register.Load(hash); ok {
|
|
return cb.(Callback).label
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Open 缓存了Label值. 每次调用少了label传参
|
|
func (l *Label) Open(urlstr string) (bodyRes string, ok bool) {
|
|
return l.cli.open(l, urlstr)
|
|
}
|
|
|
|
// SetContentCondition 设置识别到的内容条件. js代码. 必须是一个函数. 命名可以随意. 返回bool
|
|
func (l *Label) SetContentCondition(jsScript string) {
|
|
l.conditionlock.Lock()
|
|
defer l.conditionlock.Unlock()
|
|
l.conditionJS = jsScript
|
|
}
|
|
|
|
// SetContentConditionFromFile 设置识别到的内容条件. js代码. 从js文件 必须是一个函数. 命名可以随意. 返回bool
|
|
func (l *Label) SetContentConditionFromFile(jsScriptFile string) {
|
|
f, err := os.Open(jsScriptFile)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
data, err := ioutil.ReadAll(f)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
l.conditionlock.Lock()
|
|
defer l.conditionlock.Unlock()
|
|
log.Println(string(data))
|
|
l.conditionJS = string(data)
|
|
}
|
|
|
|
// GetPort Get return port string. default random.
|
|
func (cli *Client) GetPort() string {
|
|
return cli.port
|
|
}
|
|
|
|
// SetPort Set port string. before client call connect method
|
|
func (cli *Client) SetPort(port string) {
|
|
cli.port = port
|
|
}
|
|
|
|
// GetHost Get return host string
|
|
func (cli *Client) GetHost() string {
|
|
return cli.host
|
|
}
|
|
|
|
// SetHost Set host string. default http://127.0.0.1
|
|
func (cli *Client) SetHost(host string) {
|
|
cli.host = host
|
|
}
|
|
|
|
// Register 注册基础信息
|
|
func (cli *Client) Register(label string, callback func(tid, content string, err error)) *Label {
|
|
cb := Callback{Do: callback, hash: uuid.New().String()}
|
|
if _, ok := cli.register.Load(label); ok {
|
|
log.Panic("label: ", label, " is exists")
|
|
}
|
|
cli.register.Store(label, cb)
|
|
cli.register.Store(cb.hash, cb)
|
|
l := &Label{label: label, cli: cli}
|
|
return l
|
|
}
|
|
|
|
// UnRegister 卸载注册基础信息
|
|
func (cli *Client) UnRegister(label string) {
|
|
if cb, ok := cli.register.Load(label); ok {
|
|
cli.register.Delete(label)
|
|
cli.register.Delete(cb.(Callback).hash)
|
|
}
|
|
}
|
|
|
|
// Connect 连接初始化回调端口
|
|
func (cli *Client) Connect() {
|
|
|
|
cli.lock.Lock()
|
|
defer cli.lock.Unlock()
|
|
|
|
if cli.server == nil {
|
|
|
|
listener, err := net.Listen("tcp", ":0")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
cli.port = fmt.Sprintf("%d", listener.Addr().(*net.TCPAddr).Port)
|
|
|
|
router := gin.Default()
|
|
router.POST("/:label", func(c *gin.Context) {
|
|
label := c.Param("label")
|
|
if f, ok := cli.register.Load(label); ok {
|
|
callback := f.(Callback)
|
|
if tid, ok := c.GetPostForm("taskid"); ok {
|
|
content := c.PostForm("content")
|
|
errorStr := c.PostForm("error")
|
|
var err error = nil
|
|
if errorStr != "" {
|
|
err = fmt.Errorf(errorStr)
|
|
}
|
|
callback.Do(tid, content, err)
|
|
}
|
|
}
|
|
})
|
|
|
|
cli.server = &http.Server{
|
|
Addr: cli.host + ":" + cli.port,
|
|
Handler: router,
|
|
}
|
|
|
|
go func() {
|
|
err := cli.server.Serve(listener)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
|
|
} else {
|
|
log.Println("client had connected.")
|
|
}
|
|
|
|
// panic(http.Serve(listener, nil))
|
|
}
|
|
|
|
// Disconnect 断开连接
|
|
func (cli *Client) Disconnect() {
|
|
err := cli.server.Shutdown(context.Background())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// open 请求完url后 调用不同label注册的回调函数. bodyRes 请求后服务器返回的基础信息. 如果不需要debug一般不需要使用.
|
|
func (cli *Client) open(label *Label, urlstr string) (bodyRes string, ok bool) {
|
|
// urlstr = "https://playerduo.com/api/playerDuo-service-v2/rip113?lang=en&deviceType=browser"
|
|
|
|
if cli.server == nil {
|
|
panic("client is not connect. Client.Connect() ? ")
|
|
}
|
|
|
|
if callback, ok := cli.register.Load(label.label); ok {
|
|
data := url.Values{}
|
|
data["url"] = []string{urlstr}
|
|
data["callback"] = []string{cli.host + ":" + cli.port + "/" + callback.(Callback).hash}
|
|
data["label"] = []string{label.label}
|
|
|
|
func() {
|
|
label.conditionlock.Lock()
|
|
defer label.conditionlock.Unlock()
|
|
data["content_condition"] = []string{label.conditionJS}
|
|
}()
|
|
|
|
resp, err := http.DefaultClient.PostForm(cli.chromeProxyAddr+"/task/put", data)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
bodyRes, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
panic(err)
|
|
|
|
}
|
|
return string(bodyRes), true
|
|
}
|
|
|
|
log.Printf("label: %s is not exists", label.label)
|
|
return "", false
|
|
}
|
|
|
|
// New 创建Client并初始化
|
|
func New(addr string) *Client {
|
|
cli := &Client{}
|
|
cli.chromeProxyAddr = addr
|
|
cli.host = "http://127.0.0.1"
|
|
return cli
|
|
}
|