新增获取账号地址的方法
This commit is contained in:
4
go.mod
4
go.mod
@@ -4,6 +4,7 @@ go 1.24.3
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.10.3
|
||||
github.com/corpix/uarand v0.2.0
|
||||
github.com/emersion/go-imap v1.2.1
|
||||
github.com/emersion/go-message v0.18.2
|
||||
github.com/fatih/structs v1.1.0
|
||||
@@ -15,6 +16,7 @@ require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/pquerna/otp v1.5.0
|
||||
github.com/redis/go-redis/v9 v9.14.0
|
||||
github.com/xuri/excelize/v2 v2.10.0
|
||||
golang.org/x/image v0.31.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.6.0
|
||||
@@ -30,7 +32,6 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/corpix/uarand v0.2.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
@@ -55,7 +56,6 @@ require (
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/xuri/efp v0.0.1 // indirect
|
||||
github.com/xuri/excelize/v2 v2.10.0 // indirect
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||
github.com/ysmood/fetchup v0.2.3 // indirect
|
||||
github.com/ysmood/goob v0.4.0 // indirect
|
||||
|
||||
11
go.sum
11
go.sum
@@ -111,8 +111,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tiendc/go-deepcopy v1.7.1 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4=
|
||||
github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
@@ -152,8 +153,6 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA=
|
||||
@@ -172,8 +171,6 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -195,8 +192,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
@@ -218,8 +213,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
|
||||
@@ -37,4 +37,5 @@ var ErrorCode = map[string]*ErrorInfo{
|
||||
"UnlockedFailed": {Code: 0, Data: "", Msg: "解锁失败"},
|
||||
"ViewSuccessful": {Code: 200, Data: "", Msg: "查看成功"},
|
||||
"NoPostsToView": {Code: 0, Data: "", Msg: "没有可查看的推文"},
|
||||
"GetAddressSuccessful": {Code: 200, Data: "", Msg: "获取地址成功"},
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ type TwitterAccount struct {
|
||||
RegisterDate string `gorm:"register_date"`
|
||||
RegisterAddress string `gorm:"register_address"`
|
||||
RegisterIp string `gorm:"register_ip"`
|
||||
Address string `gorm:"address"`
|
||||
UpdateTime int64 `gorm:"update_time"`
|
||||
CreateTime int64 `gorm:"create_time"`
|
||||
}
|
||||
|
||||
80
plugin/task-get-address-plugin.go
Normal file
80
plugin/task-get-address-plugin.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"go-account-register/config"
|
||||
"go-account-register/models"
|
||||
"go-account-register/services"
|
||||
paramsTypes "go-account-register/types"
|
||||
"log"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TaskGetAddressPlugin struct{}
|
||||
|
||||
func (*TaskGetAddressPlugin) Run(task *paramsTypes.Task) {
|
||||
|
||||
// 查询当前所有账号
|
||||
userService := services.InitTwitterAccountService()
|
||||
// 判断是否是补偿任务
|
||||
userList := userService.GetAvailableAccount(&models.TwitterAccount{
|
||||
Type: "get",
|
||||
})
|
||||
log.Println("可用账号数量:", len(userList))
|
||||
// 获取并发数
|
||||
appConfig, _ := config.LoadConfig()
|
||||
sem := make(chan struct{}, appConfig.Limit.BrowserRunMax) // 全局并发上限
|
||||
var globalWait sync.WaitGroup
|
||||
for j := 0; j < appConfig.Limit.BrowserRunMax; j++ {
|
||||
select {
|
||||
case <-task.Ctx.Done():
|
||||
log.Println("中断任务")
|
||||
return
|
||||
default:
|
||||
}
|
||||
log.Println(j)
|
||||
taskIndex := j
|
||||
if taskIndex >= len(userList) {
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
globalWait.Add(1)
|
||||
sem <- struct{}{} // 阻塞直到有空位
|
||||
go func() {
|
||||
defer func() {
|
||||
<-sem // 释放信号量
|
||||
globalWait.Done()
|
||||
}()
|
||||
getAddressWork(task, userList[taskIndex].ID)
|
||||
}()
|
||||
}
|
||||
|
||||
globalWait.Wait()
|
||||
|
||||
task.Message <- "Success"
|
||||
}
|
||||
|
||||
func getAddressWork(task *paramsTypes.Task, id int64) {
|
||||
UserService := services.InitTwitterAccountService()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Printf("Goroutine panic: %v\nStack: %s", r, debug.Stack())
|
||||
UserService.ChangeAccountLoginStatus(int(id), "账号下线")
|
||||
TwitterService.Logout(int(id))
|
||||
}
|
||||
}()
|
||||
|
||||
// 开始登录
|
||||
|
||||
res := TwitterService.Login(int(id))
|
||||
UserService.ChangeAccountLoginStatus(int(id), res.Msg)
|
||||
if res.Code == 200 {
|
||||
// 开始获取
|
||||
TwitterService.GetAccountAddress(int(id))
|
||||
TwitterService.Logout(int(id))
|
||||
UserService.ChangeAccountLoginStatus(int(id), "账号下线")
|
||||
}
|
||||
|
||||
log.Println(task.ID)
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
func ExportTwitterAccounts() ([]string, error) {
|
||||
accountService := InitTwitterAccountService()
|
||||
accounts := accountService.GetAll(&models.TwitterAccount{
|
||||
Type: "get",
|
||||
Type: "get_address",
|
||||
})
|
||||
|
||||
// 分类
|
||||
@@ -37,7 +37,7 @@ func ExportTwitterAccounts() ([]string, error) {
|
||||
continue
|
||||
}
|
||||
file := excelize.NewFile()
|
||||
titles := []string{"编号", "用户id", "用户名", "邮箱", "密码", "邮箱密码", "生日", "Token", "二步验证码", "Cookies", "类型", "状态", "登录状态", "代理", "浏览器ID", "浏览器地址", "注册时间", "注册地区", "注册IP", "更新时间", "创建时间"}
|
||||
titles := []string{"编号", "用户id", "用户名", "邮箱", "密码", "邮箱密码", "生日", "Token", "二步验证码", "Cookies", "类型", "状态", "登录状态", "代理", "浏览器ID", "浏览器地址", "注册时间", "注册地区", "注册IP", "地址", "更新时间", "创建时间"}
|
||||
for i, t := range titles {
|
||||
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
|
||||
file.SetCellValue("Sheet1", cell, t)
|
||||
@@ -63,6 +63,7 @@ func ExportTwitterAccounts() ([]string, error) {
|
||||
acc.RegisterDate,
|
||||
acc.RegisterAddress,
|
||||
acc.RegisterIp,
|
||||
acc.Address,
|
||||
acc.UpdateTime,
|
||||
acc.CreateTime,
|
||||
}
|
||||
|
||||
@@ -126,3 +126,18 @@ func (u *TwitterAccountService) GetAvailableImportAccount(params *models.Twitter
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
// 随机获取一个可用账号
|
||||
func (u *TwitterAccountService) GetRandomAccount(params *models.TwitterAccount) *models.TwitterAccount {
|
||||
var account models.TwitterAccount
|
||||
res := u.db.Model(&models.TwitterAccount{}).Where(`type = ? AND login_status IS NULL AND (status != ? OR status IS NULL)`, params.Type, params.Status)
|
||||
// if params.Username != "" {
|
||||
// res.Where("username LIKE ?", "%"+params.Username+"%")
|
||||
// }
|
||||
res.Order("RAND()").Limit(1).Find(&account)
|
||||
if account.ID == 0 {
|
||||
return nil
|
||||
}
|
||||
u.db.Model(&models.TwitterAccount{}).Where("id = ?", account.ID).Updates(map[string]interface{}{"login_status": "已选择", "update_time": time.Now().Unix()})
|
||||
return &account
|
||||
}
|
||||
|
||||
@@ -109,11 +109,52 @@ func (*TwitterService) Login(id int) *libs.ErrorInfo {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
getAccountInfo(page, int64(id))
|
||||
getRegisterInfo(page, int64(id), user.Password)
|
||||
// getAccountInfo(page, int64(id))
|
||||
// getRegisterInfo(page, int64(id), user.Password)
|
||||
return libs.ErrorCode["LoginSuccessful"]
|
||||
}
|
||||
|
||||
func (*TwitterService) GetAccountAddress(id int) *libs.ErrorInfo {
|
||||
UserService := InitTwitterAccountService()
|
||||
user := UserService.GetInfo(int64(id))
|
||||
obj := Browser.GetBrowser(id, &libs.Fingerprint{
|
||||
Proxy: user.Proxy,
|
||||
})
|
||||
// browser := obj.Browser
|
||||
page := obj.Page
|
||||
// 循环获取可用账号 到获取不到为止
|
||||
is := true
|
||||
for is {
|
||||
account := UserService.GetRandomAccount(&models.TwitterAccount{Type: "get_address", Status: "成功"})
|
||||
if account == nil {
|
||||
is = false
|
||||
}
|
||||
rod.Try(func() {
|
||||
// 进入账号信息页面
|
||||
page.MustNavigate("https://x.com/" + account.Name + "/about").MustWaitLoad()
|
||||
page.MustWaitNavigation()
|
||||
page.MustWaitLoad() // DOM 加载完成
|
||||
page.MustWaitIdle() // 基本静止(减少早期误判)
|
||||
page.MustActivate() // 前置
|
||||
// 获取地理位置
|
||||
locationElement, err := page.Timeout(10 * time.Second).Element(`#react-root > div > div > div.css-175oi2r.r-1f2l425.r-13qz1uu.r-417010.r-18u37iz > main > div > div > div > div.css-175oi2r.r-14lw9ot.r-jxzhtn.r-1ua6aaf.r-th6na.r-1phboty.r-16y2uox.r-184en5c.r-1abdc3e.r-1lg4w6u.r-f8sm7e.r-13qz1uu.r-1ye8kvj > div > div.css-175oi2r.r-16pcm1t > div.css-175oi2r.r-1wtj0ep.r-16x9es5.r-1mmae3n.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l > div > div.css-175oi2r.r-16y2uox.r-1wbh5a2 > div:nth-child(2)`)
|
||||
if err == nil {
|
||||
location, _ := locationElement.Text()
|
||||
UserService.Update(account.ID, &models.TwitterAccount{
|
||||
Address: location,
|
||||
Status: "成功",
|
||||
})
|
||||
} else {
|
||||
UserService.Update(account.ID, &models.TwitterAccount{
|
||||
Status: "失败",
|
||||
})
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
})
|
||||
}
|
||||
return libs.ErrorCode["GetAddressSuccessful"]
|
||||
}
|
||||
|
||||
// 获取账号信息
|
||||
func getAccountInfo(page *rod.Page, id int64) {
|
||||
profileButton := page.Timeout(10 * time.Second).MustElement(`a[data-testid="AppTabBar_Profile_Link"]`)
|
||||
|
||||
@@ -176,9 +176,9 @@ func (s *Scheduler) executeTask(task *paramsTypes.Task) {
|
||||
case 1:
|
||||
var taskViewPostPlugin plugin.TaskViewPostPlugin
|
||||
go taskViewPostPlugin.Run(task)
|
||||
// case 3:
|
||||
// var taskFollowClashPlugin plugin.TaskFollowClashPlugin
|
||||
// go taskFollowClashPlugin.Run(task)
|
||||
case 3:
|
||||
var taskGetAddressPlugin plugin.TaskGetAddressPlugin
|
||||
go taskGetAddressPlugin.Run(task)
|
||||
// case 7:
|
||||
// var taskSendGifPlugin plugin.TaskSendGifPlugin
|
||||
// go taskSendGifPlugin.Run(task)
|
||||
|
||||
Reference in New Issue
Block a user