github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/internal/pcscommand/login.go (about)

     1  package pcscommand
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	baidulogin "github.com/qjfoidnh/Baidu-Login"
     7  	"github.com/qjfoidnh/BaiduPCS-Go/internal/pcsfunctions/pcscaptcha"
     8  	"github.com/qjfoidnh/BaiduPCS-Go/pcsliner"
     9  	"github.com/qjfoidnh/BaiduPCS-Go/requester"
    10  	"image/png"
    11  	"io/ioutil"
    12  	"strings"
    13  )
    14  
    15  // handleVerifyImg 处理验证码, 下载到本地
    16  func handleVerifyImg(imgURL string) (savePath string, err error) {
    17  	imgContents, err := requester.Fetch("GET", imgURL, nil, nil)
    18  	if err != nil {
    19  		return "", fmt.Errorf("获取验证码失败, 错误: %s", err)
    20  	}
    21  
    22  	_, err = png.Decode(bytes.NewReader(imgContents))
    23  	if err != nil {
    24  		return "", fmt.Errorf("验证码解析错误: %s", err)
    25  	}
    26  
    27  	savePath = pcscaptcha.CaptchaPath()
    28  
    29  	return savePath, ioutil.WriteFile(savePath, imgContents, 0777)
    30  }
    31  
    32  // RunLogin 登录百度帐号
    33  func RunLogin(username, password string) (bduss, ptoken, stoken string, cookies string, err error) {
    34  	line := pcsliner.NewLiner()
    35  	defer line.Close()
    36  
    37  	bc := baidulogin.NewBaiduClinet()
    38  
    39  	if username == "" {
    40  		username, err = line.State.Prompt("请输入百度用户名(手机号/邮箱/用户名), 回车键提交 > ")
    41  		if err != nil {
    42  			return
    43  		}
    44  	}
    45  
    46  	if password == "" {
    47  		// liner 的 PasswordPrompt 不安全, 拆行之后密码就会显示出来了
    48  		fmt.Printf("请输入密码(输入的密码无回显, 确认输入完成, 回车提交即可) > ")
    49  		password, err = line.State.PasswordPrompt("")
    50  		if err != nil {
    51  			return
    52  		}
    53  	}
    54  
    55  	var vcode_raw, vcode, vcodestr string
    56  	// 移除验证码文件
    57  	defer func() {
    58  		pcscaptcha.RemoveCaptchaPath()
    59  		pcscaptcha.RemoveOldCaptchaPath()
    60  	}()
    61  
    62  for_1:
    63  	for i := 0; i < 10; i++ {
    64  	BEGIN:
    65  		lj := bc.BaiduLogin(username, password, vcode_raw, vcodestr)
    66  		switch lj.ErrInfo.No {
    67  		case "0": // 登录成功, 退出循环
    68  			return lj.Data.BDUSS, lj.Data.PToken, lj.Data.SToken, lj.Data.CookieString, nil
    69  		case "400023", "400101": // 需要验证手机或邮箱
    70  			fmt.Printf("\n需要验证手机或邮箱才能登录\n选择一种验证方式\n")
    71  			fmt.Printf("1: 手机: %s\n", lj.Data.Phone)
    72  			fmt.Printf("2: 邮箱: %s\n", lj.Data.Email)
    73  			fmt.Printf("\n")
    74  
    75  			var verifyType string
    76  			for et := 0; et < 3; et++ {
    77  				verifyType, err = line.State.Prompt("请输入验证方式 (1 或 2) > ")
    78  				if err != nil {
    79  					return
    80  				}
    81  
    82  				switch verifyType {
    83  				case "1":
    84  					verifyType = "mobile"
    85  				case "2":
    86  					verifyType = "email"
    87  				default:
    88  					fmt.Printf("[%d/3] 验证方式不合法\n", et+1)
    89  					continue
    90  				}
    91  				break
    92  			}
    93  			if verifyType != "mobile" && verifyType != "email" {
    94  				err = fmt.Errorf("验证方式不合法")
    95  				return
    96  			}
    97  			msg := ""
    98  			if lj.Data.AuthID != "" {
    99  				msg = bc.SendCodeToUser(verifyType, lj.Data.VerifyURL, lj.Data.AuthID) // 发送验证码
   100  			} else {
   101  				msg = bc.SendCodeToUser2(verifyType, lj.Data.Token)
   102  			}
   103  			fmt.Printf("消息: %s\n\n", msg)
   104  			if strings.Contains(msg, "系统出错") {
   105  				return
   106  			}
   107  			for et := 0; et < 3; et++ {
   108  				vcode, err = line.State.Prompt("请输入接收到的验证码 > ")
   109  				if err != nil {
   110  					return
   111  				}
   112  				nlj := &baidulogin.LoginJSON{}
   113  				if lj.Data.AuthID != "" {
   114  					// 此处 BDUSS 等信息尚未获取到, 仅仅完成了邮箱/电话验证
   115  					nlj = bc.VerifyCode(vcode, verifyType, lj.Data.VerifyURL, lj.Data.AuthID, lj.Data.LoginProxy, lj.Data.AuthSID)
   116  				} else {
   117  					// 此处 BDUSS 等信息已在请求中返回
   118  					nlj = bc.VerifyCode2(verifyType, lj.Data.Token, vcode, lj.Data.U)
   119  				}
   120  				if nlj.ErrInfo.No != "0" {
   121  					fmt.Printf("[%d/3] 错误消息: %s\n\n", et+1, nlj.ErrInfo.Msg)
   122  					if nlj.ErrInfo.No == "-2" { // 需要重发验证码
   123  						return
   124  					}
   125  					continue
   126  				} else {
   127  					vcode_raw = ""
   128  					vcodestr = ""
   129  						goto BEGIN
   130  				}
   131  				// 登录成功
   132  				return nlj.Data.BDUSS, nlj.Data.PToken, nlj.Data.SToken, nlj.Data.CookieString, nil
   133  			}
   134  			break for_1
   135  		case "500001", "500002": // 验证码
   136  			fmt.Printf("\n%s\n", lj.ErrInfo.Msg)
   137  			vcodestr = lj.Data.CodeString
   138  			if vcodestr == "" {
   139  				err = fmt.Errorf("未找到codeString")
   140  				return
   141  			}
   142  
   143  			// 图片验证码
   144  			var (
   145  				verifyImgURL = "https://wappass.baidu.com/cgi-bin/genimage?" + vcodestr
   146  				savePath     string
   147  			)
   148  
   149  			savePath, err = handleVerifyImg(verifyImgURL)
   150  			if err != nil {
   151  				fmt.Println(err)
   152  			} else {
   153  				fmt.Printf("打开以下路径, 以查看验证码\n%s\n\n", savePath)
   154  			}
   155  
   156  			fmt.Printf("或者打开以下的网址, 以查看验证码\n")
   157  			fmt.Printf("%s\n\n", verifyImgURL)
   158  
   159  			vcode_raw, err = line.State.Prompt("请输入验证码 > ")
   160  			if err != nil {
   161  				return
   162  			}
   163  			continue
   164  		default:
   165  			err = fmt.Errorf("错误代码: %s, 消息: %s", lj.ErrInfo.No, lj.ErrInfo.Msg)
   166  			return
   167  		}
   168  	}
   169  	return
   170  }