2017年12月

使用golang开发联通流量机器人

背景

联通某次活动。

代码


package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
    "os"
    "strconv"
    "strings"

    "github.com/jasonlvhit/gocron"
    flag "github.com/spf13/pflag"
)

var (
    users  = make(map[string]Login)
    c      = &http.Client{}
    logger *log.Logger

    serialNumber    string
    serialNumberKey string
)

const (
    BOSS = iota
    FRIEND
    STRANGER
    ENEMY

    //serialNumberKey    = "xxxx"
    //serialNumber       = "1860000000"
    indexUrl           = "http://worose.com:11003/GrabFlows/index.html?chl=5&serialNumber=xxxx"
    loginStepOneUrl    = "http://worose.com:11003/GrabFlows/grabflows/login!dologinpre.action"
    loginStepTwoUrl    = "http://worose.com:11003/GrabFlows/grabflows/login!getAccessKey.action"
    loginUrl           = "http://worose.com:11003/GrabFlows/grabflows/login!accessByEncodePwd.action"
    getLastRobTimeUrl  = "http://worose.com:11003/GrabFlows/grabflows/rob!getLastRobTime.action"
    getFriendsListUrl  = "http://worose.com:11003/GrabFlows/grabflows/user!getFriendList.action"
    getStrangerListUrl = "http://worose.com:11003/GrabFlows/grabflows/rob!getStrangerList.action"
    getEnemyListUrl    = "http://worose.com:11003/GrabFlows/grabflows/rob!getEnemyList.action"
    doRobUrl           = "http://worose.com:11003/GrabFlows/grabflows/rob!doRob.action"
    cookieStr          = "serialNumber=%s; currentZl=%d; currentPieceNum=%d; robPieceNum=%d; isFirstLogin=0; JSESSIONIDGrabFlows=%s"
)

type APIResponse struct {
    RetCode string `json:"retCode"`
    RetMsg  string `json:"retMsg"`
}

type RobTime struct {
    APIResponse
    RobStrangerTime      string `json:"rob_stranger_time"`
    OvRobBossCooling     string `json:"ov_rob_boss_cooling"`
    OvRobStrangerCooling string `json:"ov_rob_stranger_cooling"`
    OvRobFriendsCooling  string `json:"ov_rob_friends_cooling"`
    OvRobEnemyCooling    string `json:"ov_rob_enemy_cooling"`
    RobBossTime          string `json:"rob_boss_time"`
    RobFriendsTime       string `json:"rob_friends_time"`
    RobEnemyTime         string `json:"rob_enemy_time"`
    OvSysTime            string `json:"ov_sys_time"`
}

type Stranger struct {
    LastLandTime    string `json:"lastLandTime"`
    RobbedPieceNum  string `json:"robbedPieceNum"`
    Diff            int    `json:"diff,string"`
    SerialNumber    string `json:"serialNumber"`
    HappenTime      string `json:"happenTime"`
    CurrentZl       int    `json:"currentZl,string"`
    CurrentPieceNum string `json:"currentPieceNum"`
    FirstLandTime   string `json:"firstLandTime"`
    Att1            int    `json:"att1,string"`
}

type StrangerList struct {
    APIResponse
    RetData   string `json:"retData"`
    Strangers []Stranger
}

type Enemy struct {
    CurrentPieceNum int    `json:"CURRENT_PIECE_NUM"`
    UserId          string `json:"USER_ID"`
    SerialNumber    string `json:"SERIAL_NUMBER"`
    FirstLandTime   int    `json:"FIRST_LAND_TIME"`
    LastRobbedTime  int    `json:"LAST_ROBBED_TIME"`
    Rn              int    `json:"RN"`
    Diff            int    `json:"DIFF"`
    LastLandTime    int    `json:"LAST_LAND_TIME"`
    CurrentZl       int    `json:"CURRENT_ZL"`
    NetTypeCode     string `json:"NET_TYPE_CODE"`
    HappenTime      string `json:"HAPPENTIME"`
    RobbedPieceNum  int    `json:"ROBBED_PIECE_NUM"`
    RobbedSendSms   int    `json:"ROBBED_SEND_SMS"`
    Att1            int    `json:"ATT1,string"`
}

type EnemyList struct {
    APIResponse
    RetData   string `json:"retData"`
    TotalPage int    `json:"totalPage,string"`
    Enemys    []Enemy
}

type Friend struct {
    SerialNumber       string `json:"SERIAL_NUMBER"`
    MMdiff             int    `json:"MMDIFF"`
    FirstShipTime      int    `json:"FIRST_FRIENDSHIP_TIME"`
    FriendSerialNumber string `json:"FRIEND_SERIAL_NUMBER"`
    LastLandTime       int    `json:"LAST_LAND_TIME"`
    CurrentZl          int    `json:"CURRENT_ZL"`
    Diff               int    `json:"DIFF"`
    Rn                 int    `json:"RN"`
    HappenTime         int    `json:"HAPPENTIME"`
    UserId             string `json:"USERID"`
    Att1               int    `json:"ATT1"`
}

type FriendList struct {
    APIResponse
    TotalCount int    `json:"totalCount,string"`
    TotalPage  int    `json:"tatalPage,string"`
    RetData    string `json:"retData"`
    Friends    []Friend
}

type AccessKey struct {
    APIResponse
    RetSeq string `json:"retSeq"`
    RetDwp string `json:"retdwp"`
}

type Login struct {
    APIResponse
    IsFirstLogin    int `json:"isFirstLogin,string"`
    RobPieceNum     int `json:"robPieceNum,string"`
    CurrentPieceNum int `json:"currentPieceNum,string"`
    CurrentZl       int `json:"currentZl,string"`
    SessionId       string
}

func task() {
    logger.Println("task runing.............")
    rb, err := getLastRobTime()
    if err != nil {
        logger.Println(err)
        return
    }
    if rb.OvRobBossCooling == "0" {
        go doBoss()
    }
    if rb.OvRobFriendsCooling == "0" {
        go doFriend()
    }
    if rb.OvRobStrangerCooling == "0" {
        go doStranger()
    }
    if rb.OvRobEnemyCooling == "0" {
        go doEnemy()
    }
}

func request(serialNumber, url string, values url.Values) ([]byte, error) {
    login := users[serialNumber]
    cookie := fmt.Sprintf(cookieStr, serialNumber, login.CurrentZl, login.CurrentPieceNum, login.RobPieceNum, login.SessionId)
    logger.Println(values.Encode())
    req, _ := http.NewRequest("POST", url, strings.NewReader(values.Encode()))
    req.Header.Add("Accept", "application/json;charset=utf-8, text/javascript, */*; q=0.01")
    req.Header.Add("Accept-Encoding", "gzip, deflate")
    req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.6")
    req.Header.Add("Connection", "keep-alive")
    req.Header.Add("Host", "worose.com:11003")
    req.Header.Add("Origin", "http://worose.com:11003")
    req.Header.Add("Referer", "http://worose.com:11003/GrabFlows/game.html")
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
    req.Header.Add("User-Agent", "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36")
    req.Header.Add("X-Requested-With", "XMLHttpRequest")
    req.Header.Add("Cookie", cookie)
    resp, err := c.Do(req)
    if err != nil {
        logger.Println(err)
        return nil, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        logger.Println(err)
        return nil, err
    }
    return b, err
}

func login() error {
    resp, err := http.Get(loginStepOneUrl)
    if err != nil {
        logger.Println(err)
        return err
    }
    b, _ := ioutil.ReadAll(resp.Body)
    logger.Println(string(b))
    logger.Println(resp.Cookies())
    defer resp.Body.Close()

    values := url.Values{}
    values.Add("primryKey", serialNumberKey)
    resp1, err := http.PostForm(loginStepTwoUrl, values)
    defer resp1.Body.Close()
    var ak AccessKey
    b, _ = ioutil.ReadAll(resp1.Body)
    json.Unmarshal(b, &ak)
    logger.Println(string(b))
    logger.Println(ak)
    logger.Println(resp1.Cookies())

    values = url.Values{}
    values.Add("seqid", ak.RetSeq)
    values.Add("serialNumber", serialNumber)
    values.Add("encodePwd", ak.RetDwp)
    values.Add("channelId", "5")
    res, err := http.PostForm(loginUrl, values)
    defer res.Body.Close()
    b, _ = ioutil.ReadAll(res.Body)
    logger.Println(string(b))
    logger.Println(res.Cookies())
    var login Login
    json.Unmarshal(b, &login)
    for _, v := range res.Cookies() {
        if v.Name == "JSESSIONIDGrabFlows" {
            login.SessionId = v.Value
            break
        }
    }
    users[serialNumber] = login
    return nil
}

func getLastRobTime() (rt RobTime, err error) {
    values := url.Values{}
    values.Add("serialNumber", serialNumber)
    b, err := request(serialNumber, getLastRobTimeUrl, values)
    if err != nil {
        return RobTime{}, err
    }
    var robTime RobTime
    json.Unmarshal(b, &robTime)
    return robTime, nil
}

func getStrangerList() (s StrangerList, err error) {
    values := url.Values{}
    values.Add("serialNumber", serialNumber)
    resp, err := http.PostForm(getStrangerListUrl, values)
    if err != nil {
        logger.Println(err)
        return StrangerList{}, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    var sl StrangerList
    err = json.Unmarshal(b, &sl)
    if err != nil {
        logger.Println(err)
        return StrangerList{}, err
    }
    json.Unmarshal([]byte(sl.RetData), &sl.Strangers)
    return sl, nil
}

func getEnemyList() (e EnemyList, err error) {
    values := url.Values{}
    values.Add("serialNumber", serialNumber)
    values.Add("currentPage", "1")
    values.Add("pageSize", "5")
    resp, err := http.PostForm(getEnemyListUrl, values)
    if err != nil {
        return EnemyList{}, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    var el EnemyList
    err = json.Unmarshal(b, &el)
    if err != nil {
        logger.Println(err)
        return EnemyList{}, err
    }
    json.Unmarshal([]byte(el.RetData), &el.Enemys)
    return el, nil
}

func getFriendsList() (f FriendList, err error) {
    values := url.Values{}
    values.Add("serialNumber", serialNumber)
    values.Add("currentPage", "1")
    values.Add("pageSize", "5")
    resp, err := http.PostForm(getFriendsListUrl, values)
    if err != nil {
        logger.Println(err)
        return FriendList{}, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    var fl FriendList
    err = json.Unmarshal(b, &fl)
    if err != nil {
        logger.Println(err)
        return FriendList{}, err
    }
    json.Unmarshal([]byte(fl.RetData), &fl.Friends)
    return fl, nil
}

func doRob(serialNumber string, robType int, robSerialNumber string, currentZl, robZl int) error {
    values := url.Values{}
    values.Add("serialNumber", serialNumber)
    values.Add("robType", strconv.Itoa(robType))
    values.Add("robSerialNumber", robSerialNumber)
    if currentZl > 0 {
        values.Add("currentZl", strconv.Itoa(currentZl))
        values.Add("robZl", strconv.Itoa(robZl))
    }
    b, err := request(serialNumber, doRobUrl, values)
    if err != nil {
        logger.Println(err)
        return err
    }
    logger.Println(string(b))
    return err
}

func doStranger() error {
    logger.Println("开始处理陌生人........")
    user := users[serialNumber]
    //获取陌生人列表
    sl, err := getStrangerList()
    if err != nil {
        logger.Println(err)
        return err
    }
    logger.Println(sl)
    var strangerList []Stranger
    for i := 0; i < len(sl.Strangers); i++ {
        if len(strangerList) == 2 {
            break
        }
        robZl := sl.Strangers[i].CurrentZl + sl.Strangers[i].Att1*100
        if sl.Strangers[i].Diff < 0 && robZl < user.CurrentZl {
            strangerList = append(strangerList, sl.Strangers[i])
        }
    }
    logger.Println(strangerList)
    for i := 0; i < len(strangerList); i++ {
        doRob(serialNumber, STRANGER, strangerList[i].SerialNumber, user.CurrentZl, strangerList[i].CurrentZl+strangerList[i].Att1*100)
    }
    return nil
}

func doEnemy() error {
    logger.Println("开始处理敌人........")
    user := users[serialNumber]
    //获取敌人列表
    el, err := getEnemyList()
    if err != nil {
        logger.Println(err)
        return err
    }
    logger.Println(el)
    var enemyList []Enemy
    for i := 0; i < len(el.Enemys); i++ {
        if len(enemyList) == 2 {
            break
        }
        robZl := el.Enemys[i].CurrentZl + el.Enemys[i].Att1*100
        if el.Enemys[i].Diff < 0 && robZl < user.CurrentZl {
            enemyList = append(enemyList, el.Enemys[i])
        }
    }
    logger.Println(enemyList)
    for i := 0; i < len(enemyList); i++ {
        doRob(serialNumber, ENEMY, enemyList[i].SerialNumber, user.CurrentZl, enemyList[i].CurrentZl+enemyList[i].Att1*100)
    }
    return nil
}

func doBoss() {
    logger.Println("处理BOSS...........")
    doRob(serialNumber, BOSS, "BOSS", 0, 0)
}

func doFriend() error {
    logger.Println("开始处理朋友........")
    user := users[serialNumber]
    //获取敌人列表
    el, err := getFriendsList()
    if err != nil {
        logger.Println(err)
        return err
    }
    logger.Println(el)
    var friendsList []Friend
    for i := 0; i < len(el.Friends); i++ {
        if len(friendsList) == 2 {
            break
        }
        robZl := el.Friends[i].CurrentZl + el.Friends[i].Att1*100
        if el.Friends[i].Diff < 0 && robZl < user.CurrentZl {
            friendsList = append(friendsList, el.Friends[i])
        }
    }
    logger.Println(friendsList)
    for i := 0; i < len(friendsList); i++ {
        doRob(serialNumber, FRIEND, friendsList[i].FriendSerialNumber, user.CurrentZl, friendsList[i].CurrentZl+friendsList[i].Att1*100)
    }
    return nil
}

func main() {
    flag.StringVarP(&serialNumber, "serialNumber", "s", "00000000000", "-s serialNumber")
    flag.StringVarP(&serialNumberKey, "serialNumberKey", "k", "0000000000", "-k serialNumberKey")
    flag.Parse()

    if serialNumber == "00000000000" || serialNumberKey == "00000000000" {
        fmt.Println("Usage:worose -s serialNumber -k serialNumberKey")
        os.Exit(1)
    }

    logger = log.New(os.Stderr, "worose: ", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)

    logger.Println("worose running.......")
    logger.Println(serialNumber, serialNumberKey)

    login()

    task()

    gocron.Every(5).Minutes().Do(task)
    <-gocron.Start()
}