修改登录获取信息脚本

This commit is contained in:
zyj
2025-11-26 19:55:55 +08:00
parent b448227d3e
commit 6404f753a5
10 changed files with 314 additions and 26 deletions

View File

@@ -102,3 +102,13 @@ func (*Twitter) Test(ctx *gin.Context) {
"data": "", "data": "",
}) })
} }
func (t *Twitter) Export(ctx *gin.Context) {
var TwitterService services.TwitterService
code, msg, files := TwitterService.ExportAccounts()
ctx.JSON(http.StatusOK, gin.H{
"code": code,
"msg": msg,
"files": files,
})
}

14
go.mod
View File

@@ -49,17 +49,23 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/tiendc/go-deepcopy v1.7.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // 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/fetchup v0.2.3 // indirect
github.com/ysmood/goob v0.4.0 // indirect github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/got v0.40.0 // indirect github.com/ysmood/got v0.40.0 // indirect
github.com/ysmood/gson v0.7.3 // indirect github.com/ysmood/gson v0.7.3 // indirect
github.com/ysmood/leakless v0.9.0 // indirect github.com/ysmood/leakless v0.9.0 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.37.0 // indirect golang.org/x/crypto v0.43.0 // indirect
golang.org/x/net v0.39.0 // indirect golang.org/x/net v0.46.0 // indirect
golang.org/x/sys v0.32.0 // indirect golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.29.0 // indirect golang.org/x/text v0.30.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect google.golang.org/protobuf v1.34.1 // indirect
) )

21
go.sum
View File

@@ -96,6 +96,11 @@ github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE= github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE=
github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -108,10 +113,18 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.10.0 h1:8aKsP7JD39iKLc6dH5Tw3dgV3sPRh8uRVXu/fMstfW4=
github.com/xuri/excelize/v2 v2.10.0/go.mod h1:SC5TzhQkaOsTWpANfm+7bJCldzcnU/jrhqkTi/iBHBU=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ= github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns= github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ= github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
@@ -141,6 +154,8 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= 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 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= 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= golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA=
golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA= golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -159,6 +174,8 @@ 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.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 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= 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= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -180,6 +197,8 @@ 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.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 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -201,6 +220,8 @@ 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.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= 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.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= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -3,24 +3,27 @@ package models
import "github.com/go-rod/rod/lib/proto" import "github.com/go-rod/rod/lib/proto"
type TwitterAccount struct { type TwitterAccount struct {
ID int64 `gorm:"id;primary_key;auto_increment"` ID int64 `gorm:"id;primary_key;auto_increment"`
Uid string `gorm:"uid"` Uid string `gorm:"uid"`
Name string `gorm:"name"` Name string `gorm:"name"`
Email string `gorm:"email"` Email string `gorm:"email"`
Password string `gorm:"password"` Password string `gorm:"password"`
EmailPassword string `gorm:"email_password"` EmailPassword string `gorm:"email_password"`
Birthday string `gorm:"birthday"` Birthday string `gorm:"birthday"`
Token string `gorm:"token"` Token string `gorm:"token"`
Fa2 string `gorm:"fa2"` Fa2 string `gorm:"fa2"`
Cookies []*proto.NetworkCookieParam `gorm:"img;type:json;serializer:json"` Cookies []*proto.NetworkCookieParam `gorm:"img;type:json;serializer:json"`
Type string `gorm:"type"` Type string `gorm:"type"`
Status string `gorm:"status"` Status string `gorm:"status"`
LoginStatus string `gorm:"login_status"` LoginStatus string `gorm:"login_status"`
Proxy string `gorm:"proxy"` Proxy string `gorm:"proxy"`
BrowserId string `gorm:"browser_id"` BrowserId string `gorm:"browser_id"`
BrowserUrl string `gorm:"browser_url"` BrowserUrl string `gorm:"browser_url"`
UpdateTime int64 `gorm:"update_time"` RegisterDate string `gorm:"register_date"`
CreateTime int64 `gorm:"create_time"` RegisterAddress string `gorm:"register_address"`
RegisterIp string `gorm:"register_ip"`
UpdateTime int64 `gorm:"update_time"`
CreateTime int64 `gorm:"create_time"`
} }
// 实现 TableName 方法指定表名 // 实现 TableName 方法指定表名

101
plugin/task-get-plugin.go Normal file
View File

@@ -0,0 +1,101 @@
package plugin
import (
"go-account-register/config"
"go-account-register/models"
"go-account-register/services"
paramsTypes "go-account-register/types"
"log"
"math"
"runtime/debug"
"sync"
"time"
)
type TaskGetPlugin struct{}
func (*TaskGetPlugin) Run(task *paramsTypes.Task) {
// 查询当前所有账号
userService := services.InitTwitterAccountService()
// 判断是否是补偿任务
var userList []models.TwitterAccount
userList = userService.GetAvailableAccount(&models.TwitterAccount{
Type: "get",
})
if task.Data.Compensate == 1 {
// 补偿任务
userList = userService.GetAccountListByStatus(&models.TwitterAccount{
Status: "成功",
Type: "get",
})
} else {
// 清空当前运行的账号状态
userService.ClearAccountStatus(&models.TwitterAccount{
Type: "get",
})
}
log.Println("可用账号数量:", len(userList))
// 获取并发数
appConfig, _ := config.LoadConfig()
num := math.Ceil(float64(len(userList)) / float64(appConfig.Limit.BrowserRunMax))
sem := make(chan struct{}, appConfig.Limit.BrowserRunMax) // 全局并发上限
var globalWait sync.WaitGroup
for i := 0; i < int(num); i++ {
select {
case <-task.Ctx.Done():
log.Println("中断任务")
return
default:
}
log.Println("批次:", i+1)
for j := 0; j < appConfig.Limit.BrowserRunMax; j++ {
log.Println(i*appConfig.Limit.BrowserRunMax + j)
taskIndex := i*appConfig.Limit.BrowserRunMax + j
if taskIndex >= len(userList) {
break
}
time.Sleep(5 * time.Second)
globalWait.Add(1)
sem <- struct{}{} // 阻塞直到有空位
go func() {
defer func() {
<-sem // 释放信号量
globalWait.Done()
}()
getAccountWork(task, userList[taskIndex].ID)
}()
}
}
globalWait.Wait()
task.Message <- "Success"
}
func getAccountWork(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 {
// 开始拟人
// res = TwitterService.LoopViewPost(int(id))
time.Sleep(2 * time.Second)
UserService.ChangeAccountStatus(int(id), "成功")
TwitterService.Logout(int(id))
UserService.ChangeAccountLoginStatus(int(id), "账号下线")
}
log.Println(task.ID)
}

View File

@@ -17,4 +17,5 @@ func (*Twitter) TwitterRouterInit(app *gin.Engine) {
twitter.GET("/logout", twitterApi.Logout) // 退出登录 twitter.GET("/logout", twitterApi.Logout) // 退出登录
twitter.POST("/register1", twitterApi.Register1) twitter.POST("/register1", twitterApi.Register1)
twitter.GET("/test", twitterApi.Test) twitter.GET("/test", twitterApi.Test)
twitter.GET("/export", twitterApi.Export) // 导出接口
} }

View File

@@ -0,0 +1,83 @@
package services
import (
"go-account-register/models"
"log"
"github.com/xuri/excelize/v2"
)
// 导出 Twitter 账号数据到 Excel
func ExportTwitterAccounts() ([]string, error) {
accountService := InitTwitterAccountService()
accounts := accountService.GetAll(&models.TwitterAccount{
Type: "get",
})
// 分类
countryMap := map[string][]models.TwitterAccount{
"United States": {},
"Singapore": {},
"Japan": {},
"Taiwan": {},
"Other": {},
}
for _, acc := range accounts {
addr := acc.RegisterAddress
if addr == "United States" || addr == "Singapore" || addr == "Japan" || addr == "Taiwan" {
countryMap[addr] = append(countryMap[addr], acc)
} else {
countryMap["Other"] = append(countryMap["Other"], acc)
}
}
var files []string
for k, v := range countryMap {
if len(v) == 0 {
continue
}
file := excelize.NewFile()
titles := []string{"编号", "用户id", "用户名", "邮箱", "密码", "邮箱密码", "生日", "Token", "二步验证码", "Cookies", "类型", "状态", "登录状态", "代理", "浏览器ID", "浏览器地址", "注册时间", "注册地区", "注册IP", "更新时间", "创建时间"}
for i, t := range titles {
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
file.SetCellValue("Sheet1", cell, t)
}
for row, acc := range v {
vals := []interface{}{
acc.ID,
acc.Uid,
acc.Name,
acc.Email,
acc.Password,
acc.EmailPassword,
acc.Birthday,
acc.Token,
acc.Fa2,
acc.Cookies,
acc.Type,
acc.Status,
acc.LoginStatus,
acc.Proxy,
acc.BrowserId,
acc.BrowserUrl,
acc.RegisterDate,
acc.RegisterAddress,
acc.RegisterIp,
acc.UpdateTime,
acc.CreateTime,
}
for col, val := range vals {
cell, _ := excelize.CoordinatesToCellName(col+1, row+2)
file.SetCellValue("Sheet1", cell, val)
}
}
filename := "twitter_accounts_" + k + ".xlsx"
if err := file.SaveAs(filename); err != nil {
log.Println("保存文件失败:", filename, err)
} else {
files = append(files, filename)
log.Println("已导出:", filename)
}
}
return files, nil
}

View File

@@ -17,6 +17,12 @@ func InitTwitterAccountService() *TwitterAccountService {
return &TwitterAccountService{db: db} return &TwitterAccountService{db: db}
} }
func (t *TwitterAccountService) GetAll(params *models.TwitterAccount) []models.TwitterAccount {
var accounts []models.TwitterAccount
t.db.Model(&models.TwitterAccount{}).Where(params).Find(&accounts)
return accounts
}
func (t *TwitterAccountService) Create(params *models.TwitterAccount) int64 { func (t *TwitterAccountService) Create(params *models.TwitterAccount) int64 {
params.CreateTime = time.Now().Unix() params.CreateTime = time.Now().Unix()
params.UpdateTime = time.Now().Unix() params.UpdateTime = time.Now().Unix()

View File

@@ -110,6 +110,7 @@ func (*TwitterService) Login(id int) *libs.ErrorInfo {
fmt.Println(err) fmt.Println(err)
} }
getAccountInfo(page, int64(id)) getAccountInfo(page, int64(id))
getRegisterInfo(page, int64(id), user.Password)
return libs.ErrorCode["LoginSuccessful"] return libs.ErrorCode["LoginSuccessful"]
} }
@@ -170,6 +171,53 @@ func getAccountInfo(page *rod.Page, id int64) {
}) })
} }
func getRegisterInfo(page *rod.Page, id int64, password string) {
// 进入账号信息页面
page.MustNavigate("https://x.com/settings/your_twitter_data/account").MustWaitLoad()
page.MustWaitNavigation()
page.MustWaitLoad() // DOM 加载完成
page.MustWaitIdle() // 基本静止(减少早期误判)
page.MustActivate() // 前置
// 判断当前是否需要输入密码
inpurPassword, err := page.Timeout(5 * time.Second).Element(`input[name="current_password"]`)
if err == nil {
if is, err1 := inpurPassword.Visible(); err1 == nil && is {
inpurPassword.MustInput(password)
}
ConfirmButton := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-ddtstp.r-1xpp3t0.r-2yi16.r-1qi8awa.r-3pj75a.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
ConfirmButton.MustClick()
}
time.Sleep(5 * time.Second)
// 获取创建时间
dateElement := page.Timeout(10 * time.Second).MustElement(`#react-root > div > div > div.css-175oi2r.r-1f2l425.r-13qz1uu.r-417010.r-18u37iz > main > div > div > div > section:nth-child(2) > div.css-175oi2r.r-qocrb3.r-14lw9ot.r-1h0z5md.r-1jx8gzb.r-f8sm7e.r-13qz1uu.r-1ye8kvj > div > div:nth-child(6) > div:nth-child(2)`)
createdAt, _ := dateElement.Text()
// 获取注册IP
ipElement := page.Timeout(10 * time.Second).MustElement(`#react-root > div > div > div.css-175oi2r.r-1f2l425.r-13qz1uu.r-417010.r-18u37iz > main > div > div > div > section:nth-child(2) > div.css-175oi2r.r-qocrb3.r-14lw9ot.r-1h0z5md.r-1jx8gzb.r-f8sm7e.r-13qz1uu.r-1ye8kvj > div > div:nth-child(6) > div:nth-child(3)`)
ipAddr, _ := ipElement.Text()
// 分离IP地址和地区
var ip, region string
// ipAddr 格式: "68.132.165.85 (United States)"
if strings.Contains(ipAddr, "(") {
parts := strings.Split(ipAddr, " (")
ip = strings.TrimSpace(parts[0])
if len(parts) > 1 {
region = strings.TrimRight(parts[1], ")")
}
} else {
ip = ipAddr
}
log.Println("注册IP:", ip)
log.Println("注册地区:", region)
log.Println("创建时间:", createdAt)
userService := InitTwitterAccountService()
userService.Update(id, &models.TwitterAccount{
RegisterIp: ip,
RegisterDate: createdAt,
RegisterAddress: region,
})
}
// 退出登录 // 退出登录
func (*TwitterService) Logout(id int) { func (*TwitterService) Logout(id int) {
Browser.CancelBrowser(id) Browser.CancelBrowser(id)
@@ -709,3 +757,12 @@ func (*TwitterService) LoopViewPost(id int) *libs.ErrorInfo {
} }
return libs.ErrorCode["ViewSuccessful"] return libs.ErrorCode["ViewSuccessful"]
} }
// 导出 Twitter 账号数据到 Excel
func (s *TwitterService) ExportAccounts() (code int, msg string, files []string) {
result, err := ExportTwitterAccounts()
if err != nil {
return 500, "导出失败", nil
}
return 200, "导出成功", result
}

View File

@@ -170,9 +170,9 @@ func (s *Scheduler) processQueue() {
func (s *Scheduler) executeTask(task *paramsTypes.Task) { func (s *Scheduler) executeTask(task *paramsTypes.Task) {
// 根据类型判断任务 // 根据类型判断任务
switch task.Type { switch task.Type {
// case 6: case 2:
// var taskNurturingClashPlugin plugin.TaskNurturingClashPlugin var taskGetPlugin plugin.TaskGetPlugin
// go taskNurturingClashPlugin.Run(task) go taskGetPlugin.Run(task)
case 1: case 1:
var taskViewPostPlugin plugin.TaskViewPostPlugin var taskViewPostPlugin plugin.TaskViewPostPlugin
go taskViewPostPlugin.Run(task) go taskViewPostPlugin.Run(task)