新增将账号导入到adspower的方法
This commit is contained in:
38
api/ads.go
Normal file
38
api/ads.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"go-account-register/models"
|
||||
"go-account-register/services"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AdsPower struct {
|
||||
}
|
||||
|
||||
// 导入账号
|
||||
func (a *AdsPower) ImportAccount(ctx *gin.Context) {
|
||||
// 查询当前的账号列表
|
||||
var twitterAccountService = services.InitTwitterAccountService()
|
||||
accountList := twitterAccountService.GetAvailableImportAccount(&models.TwitterAccount{
|
||||
Type: "raise",
|
||||
})
|
||||
// 循环创建AdsPower实例
|
||||
var AdsPowerService services.AdsPowerService
|
||||
log.Println("导入广告账号数量:", len(accountList))
|
||||
ticker := time.NewTicker(700 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
for _, account := range accountList {
|
||||
<-ticker.C
|
||||
AdsPowerService.CreateBrowser(account.ID)
|
||||
// 如果只需要每秒10次,可以限制最多处理10个
|
||||
}
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": "",
|
||||
})
|
||||
}
|
||||
@@ -35,4 +35,6 @@ var ErrorCode = map[string]*ErrorInfo{
|
||||
"AccountLocked": {Code: 0, Data: "", Msg: "账号锁定"},
|
||||
"UnlockedSuccessfully": {Code: 200, Data: "", Msg: "解锁成功"},
|
||||
"UnlockedFailed": {Code: 0, Data: "", Msg: "解锁失败"},
|
||||
"ViewSuccessful": {Code: 200, Data: "", Msg: "查看成功"},
|
||||
"NoPostsToView": {Code: 0, Data: "", Msg: "没有可查看的推文"},
|
||||
}
|
||||
|
||||
16
router/ads.go
Normal file
16
router/ads.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"go-account-register/api"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AdsPower struct{}
|
||||
|
||||
var apiAdspower api.AdsPower
|
||||
|
||||
func (a *AdsPower) AdsPowerRouterInit(app *gin.Engine) {
|
||||
adsPower := app.Group("/adspower")
|
||||
adsPower.POST("/import_account", apiAdspower.ImportAccount)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
var task Task
|
||||
var twitter Twitter
|
||||
var adsPower AdsPower
|
||||
|
||||
type Router struct {
|
||||
}
|
||||
@@ -13,4 +14,5 @@ type Router struct {
|
||||
func Init(app *gin.Engine) {
|
||||
task.TaskRouterInit(app)
|
||||
twitter.TwitterRouterInit(app)
|
||||
adsPower.AdsPowerRouterInit(app)
|
||||
}
|
||||
|
||||
475
services/ads_power_service.go
Normal file
475
services/ads_power_service.go
Normal file
@@ -0,0 +1,475 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go-account-register/config"
|
||||
"go-account-register/libs"
|
||||
"go-account-register/models"
|
||||
"go-account-register/utils"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/go-rod/rod/lib/input"
|
||||
"github.com/go-rod/rod/lib/proto"
|
||||
)
|
||||
|
||||
type AdsPowerService struct {
|
||||
}
|
||||
|
||||
func (*AdsPowerService) CreateBrowser(accountId int64) string {
|
||||
TwitterAccount := InitTwitterAccountService()
|
||||
user := TwitterAccount.GetInfo(accountId)
|
||||
fingerprint := map[string]interface{}{
|
||||
"name": fmt.Sprintf(`推特账号%d`, accountId),
|
||||
"group_id": "0",
|
||||
"platform": "",
|
||||
"user_proxy_config": map[string]interface{}{
|
||||
"proxy_soft": "no_proxy",
|
||||
"proxy_type": "socks5",
|
||||
},
|
||||
"fingerprint_config": map[string]interface{}{
|
||||
"webrtc": "proxy",
|
||||
"random_ua": map[string]interface{}{
|
||||
"ua_browser": []string{
|
||||
"chrome",
|
||||
},
|
||||
"ua_system_version": []string{
|
||||
"Windows 10",
|
||||
"Windows 11",
|
||||
"Mac OS X 15",
|
||||
"Mac OS X 14",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if user.Cookies != nil {
|
||||
fingerprint["cookie"] = user.Cookies
|
||||
} else {
|
||||
cookieObj := []map[string]interface{}{
|
||||
{
|
||||
"name": "auth_token",
|
||||
"value": user.Token,
|
||||
"domain": ".x.com",
|
||||
"path": "/",
|
||||
"httpOnly": false,
|
||||
"secure": true,
|
||||
"session": true,
|
||||
"expires": proto.TimeSinceEpoch(time.Now().Add(24 * time.Hour).Unix()),
|
||||
"sameSite": "unspecified",
|
||||
},
|
||||
}
|
||||
cookieJson, _ := json.Marshal(cookieObj)
|
||||
fingerprint["cookie"] = string(cookieJson)
|
||||
}
|
||||
if user.Proxy != "" {
|
||||
var proxyHandle utils.ProxyHandle
|
||||
protocol, username, password, ip, port, err2 := proxyHandle.ParseProxy(user.Proxy)
|
||||
if err2 == nil {
|
||||
fingerprint["user_proxy_config"] = map[string]interface{}{
|
||||
"proxy_soft": "other",
|
||||
"proxy_type": protocol,
|
||||
"proxy_host": ip,
|
||||
"proxy_port": port,
|
||||
"proxy_user": username,
|
||||
"proxy_password": password,
|
||||
}
|
||||
}
|
||||
}
|
||||
adsPowerRequest := utils.NewAdsPowerRequest()
|
||||
jsonStr, _ := adsPowerRequest.CreateBrowser(fingerprint)
|
||||
var rawData map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Println("创建浏览器返回数据", rawData)
|
||||
success := rawData["msg"].(string)
|
||||
if success == "Success" {
|
||||
// 如果成功则将数据存入数据库
|
||||
data := rawData["data"].(map[string]interface{})
|
||||
id := data["profile_id"].(string)
|
||||
// jsonData, _ := json.Marshal(data)
|
||||
TwitterAccount.Update(accountId, &models.TwitterAccount{
|
||||
BrowserId: id,
|
||||
})
|
||||
return id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*AdsPowerService) GetRunStatus(id string) int {
|
||||
adsPowerRequest := utils.NewAdsPowerRequest()
|
||||
jsonStr, _ := adsPowerRequest.GetRunStatus(id)
|
||||
var rawData map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
success := rawData["msg"].(string)
|
||||
if success == "success" {
|
||||
data := rawData["data"].(map[string]interface{})
|
||||
status := data["status"].(string)
|
||||
if status == "Active" {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 打开浏览器
|
||||
func (*AdsPowerService) OpenBrowser(accountId int, browserId string) string {
|
||||
// 获取当前
|
||||
adsPowerRequest := utils.NewAdsPowerRequest()
|
||||
data := map[string]interface{}{
|
||||
"profile_id": browserId,
|
||||
"delete_cache": "1",
|
||||
// "last_opened_tabs": "0",
|
||||
}
|
||||
jsonStr, _ := adsPowerRequest.OpenBrowser(data)
|
||||
var rawData map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
success := rawData["msg"].(string)
|
||||
if success == "success" {
|
||||
data := rawData["data"].(map[string]interface{})
|
||||
ws := data["ws"].(map[string]interface{})
|
||||
puppeteer := ws["puppeteer"].(string)
|
||||
TwitterAccount := InitTwitterAccountService()
|
||||
TwitterAccount.Update(int64(accountId), &models.TwitterAccount{
|
||||
BrowserUrl: puppeteer,
|
||||
})
|
||||
return puppeteer
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 删除浏览器
|
||||
func (*AdsPowerService) DeleteBrowser(browserId string) bool {
|
||||
adsPowerRequest := utils.NewAdsPowerRequest()
|
||||
// 先关闭浏览器
|
||||
_, err := adsPowerRequest.CloseBrowser(browserId)
|
||||
if err != nil {
|
||||
log.Println("关闭浏览器失败")
|
||||
}
|
||||
// 删除浏览器
|
||||
_, err2 := adsPowerRequest.DeleteBrowser(browserId)
|
||||
log.Println("删除浏览器,", err2 == nil)
|
||||
return err2 == nil
|
||||
}
|
||||
|
||||
// 关闭浏览器
|
||||
func (*AdsPowerService) CloseBrowser(browserId string) bool {
|
||||
adsPowerRequest := utils.NewAdsPowerRequest()
|
||||
jsonStr, _ := adsPowerRequest.CloseBrowser(browserId)
|
||||
var result struct {
|
||||
Data string `json:"data"` // 动态键名 → 值
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(jsonStr.Body()), &result); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func randNum(min, max int) int {
|
||||
return rand.Intn(max-min) + min
|
||||
}
|
||||
|
||||
func getKey(id string) input.Key {
|
||||
keys := map[string]input.Key{
|
||||
"0": input.Numpad0,
|
||||
"1": input.Numpad1,
|
||||
"2": input.Numpad2,
|
||||
"3": input.Numpad3,
|
||||
"4": input.Numpad4,
|
||||
"5": input.Numpad5,
|
||||
"6": input.Numpad6,
|
||||
"7": input.Numpad7,
|
||||
"8": input.Numpad8,
|
||||
"9": input.Numpad9,
|
||||
"+": input.NumpadAdd,
|
||||
}
|
||||
return keys[id]
|
||||
}
|
||||
|
||||
// 将指定元素滑动到顶部
|
||||
func scrollElementLocationCenter(el *rod.Element) {
|
||||
// 执行JS:滚动到视口顶部(平滑滚动)
|
||||
el.MustEval(`function() {
|
||||
this.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center", // 关键参数:垂直居中
|
||||
inline: "center" // 水平居中
|
||||
});
|
||||
}`)
|
||||
|
||||
// 等待滚动完成
|
||||
// time.Sleep(2 * time.Second)
|
||||
}
|
||||
|
||||
// 发推
|
||||
func (*AdsPowerService) SendPost(accountId int, Content string, Img []string) *libs.ErrorInfo {
|
||||
// 获取账号状态
|
||||
UserService := InitTwitterAccountService()
|
||||
user := UserService.GetInfo(int64(accountId))
|
||||
if user.LoginStatus != "登录成功" {
|
||||
return libs.ErrorCode["AccountHasBeenTakenOffline"]
|
||||
}
|
||||
// 获取实例
|
||||
obj := Browser.GetBitBrowser(user.BrowserUrl)
|
||||
page := obj.Page
|
||||
// 跳转到首页
|
||||
page.MustNavigate("https://x.com/home").MustWaitLoad()
|
||||
|
||||
err := rod.Try(func() {
|
||||
// 获取内容输入框
|
||||
textInput := page.Timeout(10 * time.Second).MustElement(`div.notranslate.public-DraftEditor-content`)
|
||||
textInput.MustInput(Content)
|
||||
// 检测字符串是否包含标签
|
||||
if strings.Contains(Content, "#") {
|
||||
_, err := page.Timeout(5 * time.Second).Element(`div.css-175oi2r.r-14lw9ot.r-z2wwpe.r-1upvrn0.r-h3f8nf.r-11yh6sk.r-1rnoaur`)
|
||||
time.Sleep(2 * time.Second)
|
||||
if err == nil {
|
||||
tagBuuton := page.Timeout(5 * time.Second).MustElement(`div.css-175oi2r.r-14lw9ot.r-z2wwpe.r-1upvrn0.r-h3f8nf.r-11yh6sk.r-1rnoaur div[data-testid="typeaheadResult"] button.css-175oi2r.r-x572qd.r-6dt33c.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
|
||||
tagBuuton.MustClick()
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
// 循环保存图片到本地
|
||||
if len(Img) > 0 {
|
||||
var file libs.File
|
||||
for _, v := range Img {
|
||||
tempFile, _ := file.DownloadImage(v)
|
||||
// 结束时删除临时文件
|
||||
defer os.Remove(tempFile)
|
||||
page.MustElement(`input[data-testid="fileInput"]`).MustSetFiles(tempFile)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
})
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
fmt.Println("请求空闲等待超时!")
|
||||
return libs.ErrorCode["SendPostFailed"]
|
||||
}
|
||||
|
||||
code := postButton(page)
|
||||
if code == 200 {
|
||||
return libs.ErrorCode["SendPostSuccessful"]
|
||||
}
|
||||
return libs.ErrorCode["SendPostFailed"]
|
||||
}
|
||||
|
||||
// 模拟人类刷帖子 限制时间
|
||||
func (*AdsPowerService) ViewPostsSpecifiedTime(accountId int) *libs.ErrorInfo {
|
||||
UserService := InitTwitterAccountService()
|
||||
user := UserService.GetInfo(int64(accountId))
|
||||
if user.LoginStatus != "登录成功" {
|
||||
return libs.ErrorCode["AccountHasBeenTakenOffline"]
|
||||
}
|
||||
// 获取实例
|
||||
obj := Browser.GetBitBrowser(user.BrowserUrl)
|
||||
page := obj.Page
|
||||
// 跳转到首页
|
||||
page.MustNavigate("https://x.com/home").MustWaitLoad()
|
||||
forYou := page.Timeout(10 * time.Second).MustElement(`div[data-testid="ScrollSnap-List"] div.css-175oi2r.r-14tvyh0.r-cpa5s6.r-16y2uox:nth-child(1)`)
|
||||
forYou.MustClick()
|
||||
page.MustWaitNavigation()
|
||||
// 是否检测到帖子列表
|
||||
err := rod.Try(func() {
|
||||
page.Timeout(5 * time.Second).MustElement(`article[data-testid="tweet"]`)
|
||||
})
|
||||
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
fmt.Println("请求空闲等待超时!")
|
||||
// 关闭浏览器
|
||||
Browser.CancelBrowser(accountId)
|
||||
return libs.ErrorCode["NetworkTimeout"]
|
||||
}
|
||||
var status chan string = make(chan string)
|
||||
// 获取配置中的时间限制
|
||||
appConfig, _ := config.LoadConfig()
|
||||
randTime := appConfig.Limit.ViweTimeMin + rand.Intn(appConfig.Limit.ViweTimeMax-appConfig.Limit.ViweTimeMin)
|
||||
go loopViewPosts(page, accountId, status, randTime)
|
||||
select {
|
||||
case res := <-status:
|
||||
if res == "fali" {
|
||||
return libs.ErrorCode["MaintainAccountFailed"]
|
||||
}
|
||||
if res == "success" {
|
||||
return libs.ErrorCode["MaintainAccountSuccessful"]
|
||||
}
|
||||
case <-time.After(time.Duration(randTime) * time.Minute):
|
||||
return libs.ErrorCode["MaintainAccountSuccessful"]
|
||||
}
|
||||
return libs.ErrorCode["MaintainAccountSuccessful"]
|
||||
// // 获取配置中的时间限制
|
||||
// appConfig, _ := config.LoadConfig()
|
||||
// randTime := appConfig.Limit.ViweTimeMin + rand.Intn(appConfig.Limit.ViweTimeMax-appConfig.Limit.ViweTimeMin)
|
||||
// // 获取当前时间戳
|
||||
// startTime := time.Now().Unix()
|
||||
// var activeTime int64 = time.Now().Unix()
|
||||
// // 函数报错则向这个通道发送消息
|
||||
// ch := make(chan string, 1)
|
||||
// for activeTime-startTime < int64(randTime*60) {
|
||||
// select {
|
||||
// case <-ch:
|
||||
// // 失败
|
||||
// return libs.ErrorCode["MaintainAccountFailed"]
|
||||
// default:
|
||||
// viewPosts(page, ch, accountId)
|
||||
// }
|
||||
// activeTime = time.Now().Unix()
|
||||
// }
|
||||
// return libs.ErrorCode["MaintainAccountSuccessful"]
|
||||
|
||||
// timer := time.NewTimer(time.Duration(randTime) * time.Minute)
|
||||
// defer timer.Stop()
|
||||
|
||||
// ticker := time.NewTicker(1 * time.Second)
|
||||
// defer ticker.Stop()
|
||||
|
||||
// for {
|
||||
// select {
|
||||
// case <-timer.C:
|
||||
// fmt.Println("30分钟已到,自动返回")
|
||||
// return libs.ErrorCode["MaintainAccountSuccessful"]
|
||||
// case <-ch:
|
||||
// // 失败
|
||||
// return libs.ErrorCode["MaintainAccountFailed"]
|
||||
// case <-ticker.C:
|
||||
// viewPosts(page, ch, accountId)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
func loopViewPosts(page *rod.Page, accountId int, status chan string, randTime int) {
|
||||
// 获取当前时间戳
|
||||
startTime := time.Now().Unix()
|
||||
var activeTime int64 = time.Now().Unix()
|
||||
// 函数报错则向这个通道发送消息
|
||||
ch := make(chan string, 1)
|
||||
for activeTime-startTime < int64(randTime*60) {
|
||||
viewPosts(page, ch, accountId)
|
||||
|
||||
activeTime = time.Now().Unix()
|
||||
}
|
||||
status <- "success"
|
||||
}
|
||||
|
||||
// 查看帖子
|
||||
func viewPosts(page *rod.Page, ch chan string, accountId int) bool {
|
||||
// 滑动滚动条
|
||||
log.Println("开始滚动", accountId)
|
||||
randomTrackScroll(page)
|
||||
log.Println("结束滚动", accountId)
|
||||
is := rand.Float64() // 生成随机数
|
||||
if is < 0.5 {
|
||||
err := rod.Try(func() {
|
||||
// 获取视口内的帖子列表
|
||||
list, err := getVisibleElements(page, `div[data-testid="tweetText"]`)
|
||||
if err != nil || len(list) <= 0 {
|
||||
return
|
||||
}
|
||||
// 等待两秒
|
||||
time.Sleep(2 * time.Second)
|
||||
// 随机选择一个点击进入帖子
|
||||
tweetText := list[rand.Intn(len(list))]
|
||||
log.Println("选择一个帖子:", accountId, tweetText)
|
||||
scrollElementLocationCenter(tweetText)
|
||||
// 禁用链接点击
|
||||
_, err3 := page.Evaluate(&rod.EvalOptions{
|
||||
JS: `(selector) => {
|
||||
const el = document.querySelector(selector);
|
||||
const links = el.querySelectorAll('a');
|
||||
links.forEach(a => {
|
||||
a.style.pointerEvents = 'none';
|
||||
});
|
||||
}`,
|
||||
JSArgs: []interface{}{`div[data-testid="tweetText"]`},
|
||||
})
|
||||
if err3 != nil {
|
||||
}
|
||||
tweetText.MustClick()
|
||||
// 恢复链接的点击行为(如果需要)
|
||||
_, _ = page.Evaluate(&rod.EvalOptions{
|
||||
JS: `(selector) => {
|
||||
const el = document.querySelector(selector);
|
||||
const links = el.querySelectorAll('a');
|
||||
links.forEach(a => {
|
||||
a.style.pointerEvents = '';
|
||||
});
|
||||
}`,
|
||||
JSArgs: []interface{}{`div[data-testid="tweetText"]`},
|
||||
})
|
||||
page.MustWaitNavigation()
|
||||
// 查看帖子 3-5分钟
|
||||
timeMin := 3 + rand.Intn(2)
|
||||
time.Sleep(time.Duration(timeMin) * time.Minute)
|
||||
// 退回到上一步
|
||||
// page.MustNavigateBack()
|
||||
// 等待新页面加载完成
|
||||
// page.MustWaitLoad()
|
||||
page.MustNavigate("https://x.com/home").MustWaitLoad()
|
||||
|
||||
// 判断当前URL是否与预期的URL一致
|
||||
url := page.MustEval("() => window.location.href").String()
|
||||
if url != "https://x.com/home" {
|
||||
// 如果不一致 就直接跳转
|
||||
page.MustNavigate("https://x.com/home").MustWaitLoad()
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
ch <- "error"
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 随机滚动
|
||||
func randomTrackScroll(page *rod.Page) {
|
||||
// height, _ := page.Eval(`() => document.body.scrollHeight`)
|
||||
// totalHeight := int(height.Value.Num())
|
||||
err := rod.Try(func() {
|
||||
var totalHeight int = 1000 + rand.Intn(1000)
|
||||
currentPos := 0
|
||||
log.Println("获取随机滚动的参数:", totalHeight)
|
||||
for currentPos < totalHeight {
|
||||
// 随机水平偏移(模拟人类不精确的滑动)
|
||||
xOffset := rand.Intn(20) - 10 // -10到10之间的随机值
|
||||
yDistance := 50 + rand.Intn(150)
|
||||
|
||||
err := page.Mouse.Scroll(float64(xOffset), float64(yDistance), 1)
|
||||
if err != nil {
|
||||
log.Printf("滚动失败: %v", err)
|
||||
}
|
||||
currentPos += yDistance
|
||||
|
||||
// 随机等待和偶尔的回滑
|
||||
if rand.Float32() < 0.1 { // 10%概率回滑一点
|
||||
backStep := 10 + rand.Intn(30)
|
||||
err := page.Mouse.Scroll(0, -float64(backStep), 1)
|
||||
if err != nil {
|
||||
log.Printf("回滑失败: %v", err)
|
||||
}
|
||||
currentPos -= backStep
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * time.Duration(50+rand.Intn(300)))
|
||||
log.Println("滚动完成")
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -108,3 +108,15 @@ func (u *TwitterAccountService) Update(id int64, params *models.TwitterAccount)
|
||||
func (u *TwitterAccountService) Delete(id int64) {
|
||||
u.db.Delete(&models.TwitterAccount{}, id)
|
||||
}
|
||||
|
||||
// 获取可用账号
|
||||
func (u *TwitterAccountService) GetAvailableImportAccount(params *models.TwitterAccount) []models.TwitterAccount {
|
||||
var users []models.TwitterAccount
|
||||
res := u.db.Model(&models.TwitterAccount{}).Where(`(browser_id = '' OR browser_id IS NULL) AND (login_status != "账号异常" OR login_status IS NULL)`).Where(params)
|
||||
// if params.Username != "" {
|
||||
// res.Where("username LIKE ?", "%"+params.Username+"%")
|
||||
// }
|
||||
res.Order("id DESC").Find(&users)
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
103
utils/ads_power_request.go
Normal file
103
utils/ads_power_request.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go-account-register/config"
|
||||
"log"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type AdsPowerRequest struct {
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewAdsPowerRequest() *AdsPowerRequest {
|
||||
appConfig, _ := config.LoadConfig()
|
||||
client := resty.New()
|
||||
client.SetBaseURL(appConfig.AdsPower.ApiUrl)
|
||||
|
||||
// 响应拦截器 (类似 axios 拦截器)
|
||||
client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
|
||||
if resp.StatusCode() != 200 {
|
||||
log.Println("请求失败,检查网络")
|
||||
return errors.New("request failed")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return &AdsPowerRequest{client: client}
|
||||
}
|
||||
|
||||
// Request 发送通用请求
|
||||
func (h *AdsPowerRequest) Request(method, url string, body interface{}, queryParams map[string]string) (*resty.Response, error) {
|
||||
req := h.client.R().
|
||||
SetHeader("Content-Type", "application/json")
|
||||
|
||||
if body != nil {
|
||||
req.SetBody(body)
|
||||
}
|
||||
if queryParams != nil {
|
||||
req.SetQueryParams(queryParams)
|
||||
}
|
||||
|
||||
resp, err := req.Execute(method, url)
|
||||
|
||||
if err != nil {
|
||||
log.Println("请求失败了:", err)
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开浏览器
|
||||
*/
|
||||
func (h *AdsPowerRequest) OpenBrowser(data map[string]interface{}) (*resty.Response, error) {
|
||||
return h.Request("POST", "/api/v2/browser-profile/start", data, nil)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 关闭浏览器
|
||||
* @param {String} id
|
||||
* @returns {*resty.Response, error}
|
||||
*/
|
||||
func (h *AdsPowerRequest) CloseBrowser(id string) (*resty.Response, error) {
|
||||
return h.Request("POST", "/api/v2/browser-profile/stop", map[string]interface{}{"profile_id": id}, nil)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建浏览器
|
||||
* @param {Object} data
|
||||
* @returns {*resty.Response, error}
|
||||
*/
|
||||
func (h *AdsPowerRequest) CreateBrowser(data map[string]interface{}) (*resty.Response, error) {
|
||||
return h.Request("POST", "/api/v2/browser-profile/create", data, nil)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 查询浏览器运行状态
|
||||
* @param {String} id
|
||||
* @returns {*resty.Response, error}
|
||||
*/
|
||||
func (h *AdsPowerRequest) GetRunStatus(id string) (*resty.Response, error) {
|
||||
return h.Request("GET", "/api/v2/browser-profile/active", nil, map[string]string{"profile_id": id})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 删除浏览器
|
||||
* @param {String} id
|
||||
* @returns {*resty.Response, error}
|
||||
*/
|
||||
func (h *AdsPowerRequest) DeleteBrowser(id string) (*resty.Response, error) {
|
||||
return h.Request("POST", "/api/v2/browser-profile/delete", map[string]interface{}{"profile_id": []string{id}}, nil)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 更新浏览器配置
|
||||
* @param {Object} data
|
||||
* @returns {*resty.Response, error}
|
||||
*/
|
||||
func (h *AdsPowerRequest) UpdateBrowser(data map[string]interface{}) (*resty.Response, error) {
|
||||
return h.Request("POST", "/api/v2/browser-profile/update", data, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user