Files
hk4e/robot/login/http_login.go
2023-02-14 22:57:35 +08:00

166 lines
4.8 KiB
Go

package login
import (
"encoding/base64"
"encoding/json"
"math"
"strconv"
"hk4e/common/region"
"hk4e/dispatch/api"
"hk4e/pkg/endec"
"hk4e/pkg/httpclient"
"hk4e/pkg/logger"
"hk4e/pkg/random"
"hk4e/protocol/proto"
"github.com/pkg/errors"
pb "google.golang.org/protobuf/proto"
)
type DispatchInfo struct {
GateIp string
GatePort uint32
DispatchKey []byte
}
func GetDispatchInfo(regionListUrl string, curRegionUrl string, regionListParam string, curRegionParam string, keyId string) (*DispatchInfo, error) {
logger.Info("http get url: %v", regionListUrl+"/query_region_list"+regionListParam)
regionListBase64, err := httpclient.GetRaw(regionListUrl+"/query_region_list"+regionListParam, "")
if err != nil {
return nil, err
}
regionListData, err := base64.StdEncoding.DecodeString(regionListBase64)
if err != nil {
return nil, err
}
queryRegionListHttpRsp := new(proto.QueryRegionListHttpRsp)
err = pb.Unmarshal(regionListData, queryRegionListHttpRsp)
if err != nil {
return nil, err
}
logger.Info("region list: %v", queryRegionListHttpRsp.RegionList)
if len(queryRegionListHttpRsp.RegionList) == 0 {
return nil, errors.New("no region found")
}
if curRegionUrl == "" {
selectRegion := queryRegionListHttpRsp.RegionList[0]
logger.Info("select region: %v", selectRegion)
curRegionUrl = selectRegion.DispatchUrl
}
logger.Info("http get url: %v", curRegionUrl+curRegionParam)
regionCurrJson, err := httpclient.GetRaw(curRegionUrl+curRegionParam, "")
if err != nil {
return nil, err
}
queryCurRegionRspJson := new(api.QueryCurRegionRspJson)
err = json.Unmarshal([]byte(regionCurrJson), queryCurRegionRspJson)
if err != nil {
return nil, err
}
encryptedRegionInfo, err := base64.StdEncoding.DecodeString(queryCurRegionRspJson.Content)
if err != nil {
return nil, err
}
chunkSize := 256
regionInfoLength := len(encryptedRegionInfo)
numChunks := int(math.Ceil(float64(regionInfoLength) / float64(chunkSize)))
regionCurrData := make([]byte, 0)
_, encRsaKeyMap, _ := region.LoadRsaKey()
encPubPrivKey, exist := encRsaKeyMap[keyId]
if !exist {
logger.Error("can not found key id: %v", keyId)
return nil, err
}
for i := 0; i < numChunks; i++ {
from := i * chunkSize
to := int(math.Min(float64((i+1)*chunkSize), float64(regionInfoLength)))
chunk := encryptedRegionInfo[from:to]
privKey, err := endec.RsaParsePrivKey(encPubPrivKey)
if err != nil {
logger.Error("parse rsa priv key error: %v", err)
return nil, err
}
decrypt, err := endec.RsaDecrypt(chunk, privKey)
if err != nil {
logger.Error("rsa dec error: %v", err)
return nil, err
}
regionCurrData = append(regionCurrData, decrypt...)
}
queryCurrRegionHttpRsp := new(proto.QueryCurrRegionHttpRsp)
err = pb.Unmarshal(regionCurrData, queryCurrRegionHttpRsp)
if err != nil {
return nil, err
}
regionInfo := queryCurrRegionHttpRsp.RegionInfo
if regionInfo == nil {
return nil, errors.New("region info is nil")
}
ec2b, err := random.LoadEc2bKey(regionInfo.SecretKey)
if err != nil {
return nil, err
}
dispatchInfo := &DispatchInfo{
GateIp: regionInfo.GateserverIp,
GatePort: regionInfo.GateserverPort,
DispatchKey: ec2b.XorKey(),
}
return dispatchInfo, nil
}
type AccountInfo struct {
AccountId uint32
Token string
ComboToken string
}
func AccountLogin(url string, account string, password string) (*AccountInfo, error) {
loginAccountRequestJson := &api.LoginAccountRequestJson{
Account: account,
Password: password,
IsCrypto: true,
}
logger.Info("http post url: %v", url+"/hk4e_global/mdk/shield/api/login")
loginResult, err := httpclient.PostJson[api.LoginResult](url+"/hk4e_global/mdk/shield/api/login", loginAccountRequestJson, "")
if err != nil {
return nil, err
}
if loginResult.Retcode != 0 {
logger.Error("login error msg: %v", loginResult.Message)
return nil, errors.New("login error")
}
accountId, err := strconv.Atoi(loginResult.Data.Account.Uid)
if err != nil {
return nil, err
}
loginTokenData := &api.LoginTokenData{
Uid: loginResult.Data.Account.Uid,
Token: loginResult.Data.Account.Token,
}
loginTokenDataJson, err := json.Marshal(loginTokenData)
if err != nil {
return nil, err
}
comboTokenReq := &api.ComboTokenReq{
AppID: 4,
ChannelID: 1,
Data: string(loginTokenDataJson),
}
logger.Info("http post url: %v", url+"/hk4e_global/combo/granter/login/v2/login")
comboTokenRsp, err := httpclient.PostJson[api.ComboTokenRsp](url+"/hk4e_global/combo/granter/login/v2/login", comboTokenReq, "")
if err != nil {
return nil, err
}
if comboTokenRsp.Retcode != 0 {
logger.Error("v2 login error msg: %v", comboTokenRsp.Message)
return nil, errors.New("v2 login error")
}
accountInfo := &AccountInfo{
AccountId: uint32(accountId),
Token: loginResult.Data.Account.Token,
ComboToken: comboTokenRsp.Data.ComboToken,
}
return accountInfo, nil
}