Files
go-account-register/services/bit_browser_service.go
2025-09-27 18:13:59 +08:00

346 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package services
import (
"encoding/json"
"fmt"
"go-account-register/libs"
"go-account-register/models"
"go-account-register/utils"
"log"
"strconv"
"time"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/proto"
)
type BitBrowserService struct {
}
var Browser libs.Browser
var Chrome libs.Chrome
type BitCookieParam struct {
Domain string `json:"domain"`
ExpirationDate float64 `json:"expirationDate"` // 必须为 number
HttpOnly bool `json:"httpOnly"`
Name string `json:"name"`
Path string `json:"path"`
Secure bool `json:"secure"`
Session bool `json:"session"`
StoreID *string `json:"storeId"` // 允许 null用指针
Value string `json:"value"`
SameSite *string `json:"sameSite,omitempty"` // 可选字段,不填时省略
}
func (*BitBrowserService) CreateBrowser(proxy *models.Proxy, cookies []*proto.NetworkCookieParam) string {
fingerprint := map[string]interface{}{
"name": fmt.Sprintf(`推特注册%s`, utils.RandString(10)),
"proxyMethod": 2,
"proxyType": "noproxy",
"host": "",
"port": 0,
"proxyUserName": "",
"proxyPassword": "",
"randomFingerprint": true,
"syncTabs": false,
"syncCookies": false,
"browserFingerPrint": map[string]interface{}{
"coreVersion": "130",
"ostype": "PC",
"os": "Win32",
"osVersion": "11,10",
"openWidth": 1920,
"openHeight": 1480,
"resolutionType": "0",
},
}
if cookies != nil {
var cookie []BitCookieParam
for _, v := range cookies {
cookie = append(cookie, BitCookieParam{
Domain: v.Domain,
ExpirationDate: float64(v.Expires),
HttpOnly: v.HTTPOnly,
Name: v.Name,
Path: v.Path,
Secure: v.Secure,
Session: false,
StoreID: nil,
Value: v.Value,
SameSite: (*string)(&v.SameSite),
})
}
data, _ := json.Marshal(cookie)
fingerprint["cookie"] = data
}
if proxy != nil {
var proxyHandle utils.ProxyHandle
protocol, username, password, ip, port, err2 := proxyHandle.ParseProxy(proxy.Type + "://" + proxy.Proxy)
if err2 == nil {
fingerprint["proxyType"] = protocol
fingerprint["host"] = ip
fingerprint["port"] = port
fingerprint["proxyUserName"] = username
fingerprint["proxyPassword"] = password
}
}
bitBrowserRequest := utils.NewBitBrowserRequest()
jsonStr, _ := bitBrowserRequest.CreateBrowser(fingerprint)
var rawData map[string]interface{}
if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
panic(err)
}
success := rawData["success"].(bool)
if success {
// 如果成功则将数据存入数据库
data := rawData["data"].(map[string]interface{})
id := data["id"].(string)
browserInstanceService := InitBrowserInstanceService()
var params = &models.BrowserInstance{
BrowserId: id,
Fingerprint: data,
UpdateTime: time.Now().Unix(),
CreateTime: time.Now().Unix(),
}
if proxy != nil && proxy.Type != "" {
params.Proxy = proxy.Type + "://" + proxy.Proxy
}
browserInstanceService.Create(params)
return id
}
return ""
}
// 获取当前浏览器的pid
func (*BitBrowserService) GetPid(id string) int {
// 获取当前
bitBrowserRequest := utils.NewBitBrowserRequest()
jsonStr, _ := bitBrowserRequest.GetPids([]string{id})
var result struct {
Data map[string]int `json:"data"` // 动态键名 → 值
Success bool `json:"success"`
}
if err := json.Unmarshal([]byte(jsonStr.Body()), &result); err != nil {
panic(err)
}
success := result.Success
if success {
data := result.Data
if value, exists := data[id]; exists {
return value
} else {
return 0
}
}
return 0
}
// 打开浏览器
func (*BitBrowserService) OpenBrowser(browserId string) string {
// 获取当前
bitBrowserRequest := utils.NewBitBrowserRequest()
data := map[string]interface{}{
"id": browserId,
"queue": true,
}
jsonStr, _ := bitBrowserRequest.OpenBrowser(data)
var rawData map[string]interface{}
if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
panic(err)
}
success := rawData["success"].(bool)
if success {
data := rawData["data"].(map[string]interface{})
ws := data["ws"].(string)
browserInstanceService := InitBrowserInstanceService()
browserInstanceService.Update(browserId, &models.BrowserInstance{
BrowserUrl: ws,
})
return ws
}
return ""
}
// 删除浏览器
func (*BitBrowserService) DeleteBrowser(browserId string) bool {
bitBrowserRequest := utils.NewBitBrowserRequest()
// 先关闭浏览器
_, err := bitBrowserRequest.CloseBrowser(browserId)
if err != nil {
log.Println("关闭浏览器失败")
}
// 删除浏览器
_, err2 := bitBrowserRequest.DeleteBrowser(browserId)
log.Println("删除浏览器,", err2 == nil)
return err2 == nil
}
func (bit *BitBrowserService) Register() *libs.ErrorInfo {
// 随机获取代理
proxyService := InitProxyService()
proxy := proxyService.GetInfo()
var browserId string
// 创建新的浏览器
if proxy != nil {
browserId = bit.CreateBrowser(proxy, nil)
} else {
browserId = bit.CreateBrowser(nil, nil)
}
// 打开浏览器
if browserId == "" {
return libs.ErrorCode["BrowserCreationFailed"]
}
ws := bit.OpenBrowser(browserId)
if ws == "" {
return libs.ErrorCode["BrowserCreationFailed"]
}
// 获取一个邮箱
emailService := InitEmailService()
emailInfo := emailService.GetEmailOne()
log.Println("当前邮箱信息", emailInfo)
obj := Browser.GetBitBrowser(ws)
page := obj.Page
page.MustNavigate("https://x.com/i/flow/signup").MustWaitLoad()
// 点击创建账号
createAccount := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-ywje51.r-184id4b.r-13qz1uu.r-2yi16.r-1qi8awa.r-3pj75a.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
createAccount.MustClick()
// 判断当前是否是邮箱注册
// _, err := page.Element(`input[name="email"]`)
// if err != nil {
switchButton := page.Timeout(5 * time.Second).MustElement(`button.css-146c3p1.r-bcqeeo.r-qvutc0.r-37j5jr.r-1ff274t.r-a023e6.r-rjixqe.r-16dba41`)
switchButton.MustClick()
// }
// 获取邮箱输入框
inputEmail := page.Timeout(5 * time.Second).MustElement(`input[name="email"]`)
inputEmail.MustFocus()
inputEmail.MustInput(emailInfo.Email)
// 获取名称输入框
inputName := page.Timeout(5 * time.Second).MustElement(`input[name="name"]`)
inputName.MustFocus()
nameStr := emailInfo.Name
if emailInfo.Name == "" {
nameStr = utils.RandString(12)
}
inputName.MustInput(nameStr)
// 随机生成生日
dateParams := utils.RandDate(18, 80)
dateSelects, _ := page.Timeout(5 * time.Second).Elements(`select.r-30o5oe.r-1niwhzg.r-17gur6a.r-1yadl64.r-18jsvk2.r-1loqt21.r-1inkyih.r-rjixqe.r-crgep1.r-1wzrnnt.r-1ny4l3l.r-t60dpp.r-xd6kpl.r-is05cd.r-ttdzmv`)
// 月份
dateSelects[0].WaitVisible()
dateSelects[0].MustSelect(strconv.Itoa(dateParams.Month))
// 日期
dateSelects[1].WaitVisible()
dateSelects[1].MustSelect(strconv.Itoa(dateParams.Day))
// 年份
dateSelects[2].WaitVisible()
dateSelects[2].MustSelect(strconv.Itoa(dateParams.Year))
// 点击下一步
ocfSignupNextLink := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfSignupNextLink"]`)
ocfSignupNextLink.MustClick()
// 判断是否需要验证码
time.Sleep(4 * time.Second)
_, err1 := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
if err1 != nil {
// res := getApiResponse(page, "")
}
//TODO 对接获取邮箱信息接口
time.Sleep(10 * time.Second)
codeValue := LoopGetEmailCode("pop.dragonsmail.com:993", emailInfo.Email, emailInfo.Password)
if codeValue == "0" {
emailService.Update(emailInfo.Email, models.Email{
Status: 0,
})
return libs.ErrorCode["MailboxUnavailable"]
}
// 获取邮箱验证码
log.Println("获取当前验证码", codeValue)
codeInput1, _ := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
codeInput1.MustInput(codeValue)
time.Sleep(2 * time.Second)
// 点击下一步
codeNextButton := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-19yznuf.r-64el8z.r-1fkl15p.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
codeNextButton.MustClick()
// // 点击验证按钮
// verifyButton := page.Timeout(5 * time.Second).MustElement(`button[data-theme="home.verifyButton"]`)
// verifyButton.MustClick()
// 输入密码
passwordInput, err2 := page.Timeout(5 * time.Second).Element(`input[name="password"]`)
if err2 != nil {
// res := getApiResponse(page, "")
}
passwordInput.MustInput(emailInfo.Password)
time.Sleep(5 * time.Second)
// 点击下一步
loginButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="LoginForm_Login_Button"]`)
loginButton.MustClick()
time.Sleep(5 * time.Second)
page.MustNavigate("https://x.com").MustWaitLoad()
time.Sleep(10 * time.Second)
// 获取cookie
cookieArr := getPageCookie(page, "https://x.com")
// 创建用户
twitterAccountService := InitTwitterAccountService()
twitterAccountService.Create(&models.TwitterAccount{
Name: nameStr,
Email: emailInfo.Email,
Password: emailInfo.Password,
Birthday: strconv.Itoa(dateParams.Year) + "-" + strconv.Itoa(dateParams.Month) + "-" + strconv.Itoa(dateParams.Day),
Cookies: cookieArr,
Status: "注册成功",
LoginStatus: "登录成功",
Proxy: func() string {
if proxy != nil && proxy.Type != "" {
return proxy.Type + "://" + proxy.Proxy
}
return ""
}(),
})
emailService.Update(emailInfo.Email, models.Email{
UseStatus: 1,
})
// 删除浏览器
bit.DeleteBrowser(browserId)
return libs.ErrorCode["RegisterSuccessful"]
}
// 获取指定页面的cookie列表
func getPageCookie(page *rod.Page, url string) []*proto.NetworkCookieParam {
cookieArr, _ := page.Cookies([]string{url})
var cookies []*proto.NetworkCookieParam
for _, cookie := range cookieArr {
cookies = append(cookies, &proto.NetworkCookieParam{
Name: cookie.Name,
Value: cookie.Value,
Domain: cookie.Domain,
Path: cookie.Path,
Expires: cookie.Expires, // 过期时间
HTTPOnly: cookie.HTTPOnly, // 禁止 JS 访问
Secure: cookie.Secure, // 仅 HTTPS 传输
})
}
return cookies
}
// 循环获取3次验证码
func LoopGetEmailCode(server, email, password string) string {
var emailImap utils.EmailImap
for i := 0; i < 3; i++ {
codeValue := emailImap.GetMailCode(server, email, password)
if codeValue != "0" {
return codeValue
}
time.Sleep(5 * time.Second)
}
return "0"
}
func (*BitBrowserService) AccountUnlock(id int64) *libs.ErrorInfo {
return libs.ErrorCode["UnlockedSuccessfully"]
}