func NewBot(conf *Configure) (*WeChat, error) {
	if conf == nil {
		conf = DefaultConfigure()
	}
	wechat, err := newWeChat(conf)
	if err != nil {
		return nil, err
	}
	wechat.evtStream.init()
	go func() {
		for {
			ls := <-wechat.loginState
			event := Event{
				Path: `/login`,
				From: `Wechat`,
				To:   `End`,
				Data: ls,
				Time: time.Now().Unix(),
			}
			wechat.evtStream.serverEvt <- event
		}
	}()
	wechat.keepAlive()
	if conf.Debug {
		log.SetLevel(log.DebugLevel)
	}
	return wechat, nil
}
NewBot is start point for wx bot.
package wechat
import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/cookiejar"
	"net/http/httputil"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"
	log "github.com/Sirupsen/logrus"
)
var logger = log.WithFields(log.Fields{
	"module": "wechat",
})
const httpOK = `200`
type BaseRequest struct {
	XMLName xml.Name `xml:"error" json:"-"`
	Ret        int    `xml:"ret" json:"-"`
	Message    string `xml:"message" json:"-"`
	Wxsid      string `xml:"wxsid" json:"Sid"`
	Skey       string `xml:"skey"`
	DeviceID   string `xml:"-"`
	Wxuin      int64  `xml:"wxuin" json:"Uin"`
	PassTicket string `xml:"pass_ticket" json:"-"`
}
type Caller interface {
	IsSuccess() bool
	Error() error
}
type Response struct {
	BaseResponse *BaseResponse
}
func (response *Response) IsSuccess() bool {
	return response.BaseResponse.Ret == 0
}
func (response *Response) Error() error {
	return fmt.Errorf("error message:[%s]", response.BaseResponse.ErrMsg)
}
type BaseResponse struct {
	Ret    int
	ErrMsg string
}
type Configure struct {
	Processor         UUIDProcessor
	Debug             bool
	CachePath         string
	UniqueGroupMember bool
	version           string
}
func DefaultConfigure() *Configure {
	return &Configure{
		Processor:         new(defaultUUIDProcessor),
		Debug:             true,
		UniqueGroupMember: true,
		CachePath:         `.wechat/debug`,
		version:           `1.0.1-rc1`,
	}
}
func (c *Configure) contactCachePath() string {
	return filepath.Join(c.CachePath, `contact-cache.json`)
}
func (c *Configure) baseInfoCachePath() string {
	return filepath.Join(c.CachePath, `basic-info-cache.json`)
}
func (c *Configure) cookieCachePath() string {
	return filepath.Join(c.CachePath, `cookie-cache.json`)
}
func (c *Configure) httpDebugPath(url *url.URL) string {
	ps := strings.Split(url.Path, `/`)
	lastP := strings.Split(ps[len(ps)-1], `?`)[0][5:]
	return c.CachePath + `/` + lastP
}
type WeChat struct {
	Client      *http.Client
	BaseURL     string
	BaseRequest *BaseRequest
	MySelf      Contact
	IsLogin     bool
	conf       *Configure
	evtStream  *evtStream
	cache      *cache
	syncKey    map[string]interface{}
	syncHost   string
	retryTimes time.Duration
	loginState chan int  
}
func newWeChat(conf *Configure) (*WeChat, error) {
	if _, err := os.Stat(conf.CachePath); err != nil {
		if os.IsNotExist(err) {
			err = os.MkdirAll(conf.CachePath, os.ModePerm)
			if err != nil {
				return nil, err
			}
		} else {
			return nil, err
		}
	}
	client, err := newClient()
	if err != nil {
		return nil, err
	}
	baseReq := new(BaseRequest)
	baseReq.Ret = 1
	baseReq.DeviceID = `e999471493880231`
	wechat := &WeChat{
		Client:      client,
		BaseRequest: baseReq,
		evtStream:   newEvtStream(),
		IsLogin:     false,
		retryTimes:  time.Duration(0),
		loginState:  make(chan int),
		conf:        conf,
		cache:       newCache(),
	}
	return wechat, nil
}
func newClient() (*http.Client, error) {
	jar, err := cookiejar.New(nil)
	if err != nil {
		return nil, err
	}
	transport := http.Transport{
		Dial: (&net.Dialer{
			Timeout: 1 * time.Minute,
		}).Dial,
		TLSHandshakeTimeout: 1 * time.Minute,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}
	client := &http.Client{
		Transport: &transport,
		Jar:       jar,
		Timeout:   1 * time.Minute,
	}
	return client, nil
}