github.com/fzfile/BaiduPCS-Go@v0.0.0-20200606205115-4408961cf336/internal/pcscommand/login.go (about)

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