`
naner3344
  • 浏览: 4278 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

webqq go语言的实现

阅读更多
最近开始学习go语言,觉得非常有趣,便从http入手,写了个web挂机程序。适用go版本r59-201108最新版本,低版本编译通不过。
// webQQ.go
/*
 *GO语言讨论群:102319854
 *GO语言官网:www.golang.org
 *作者: 不死爬虫
 *主页: http://www.gososo.org http://www.daohang361.com/news/index.html
 *见证的轨迹
 *乱码的解决方法
 *	1、dos执行chcp 65001 //修改代码页为utf-8,否则无法通过编译 
 *	2、修改dos窗口字体为Lucida Console,否则显示的字符为乱码 
 *	http://bbs.golang-china.org/viewtopic.php?f=4&t=8&start=10#p93
 *  chcp 命令:
 *  chcp 65001  就是换成UTF-8代码页,在命令行标题栏上点击右键,选择"属性"->"字体",将字体修改为True Type字体"Lucida Console",然后点击确定将属性应用到当前窗口
 *  chcp 936 可以换回默认的GBK
 *  chcp 437 是美国英语
 */
package main

import (
	"fmt"
	"os"
	"http"
	"net"
	"regexp"
	"crypto/md5" 
	"hash" 
	"strings"
	"encoding/hex"
	"io/ioutil"
	"bytes"
	"bufio"
)
var mcookies = make(map[string] *http.Cookie)//保存cookie
var qq string
var pass string
var ptwebqq string//cookie值登陆和后面用
var skey string//cookie值登陆和后面用
var clientid string="63690451"//随机取
var vfwebqq string     //第二次返回的参数
var psessionid string //第二次登陆返回的参数
var refer string
func main() {
fmt.Println("If you run this First time,Please run 'chcp 65001' in then cmd ,then set front 'Lucida Console'")
fmt.Println("And run 'chcp 936 to back default'")
	if len(os.Args) != 3 {
                fmt.Println("Usage: ", os.Args[0], "365183440 pass")
               in := bufio.NewReader(os.Stdin)
               line, _ := in.ReadString('\n')
               qq=strings.Split(line," ")[0]
               pass=strings.Split(line," ")[1]
               pass=strings.TrimSpace(pass)
     }else{
	    qq   = os.Args[1];
	    pass =os.Args[2];
	}
	fmt.Println("qq:"+qq+"pass:"+pass)
	refer="http://web2-b.qq.com/proxy.html"
	s:=getUrl("http://ptlogin2.qq.com:80/check?appid=1003903&uin="+qq,refer);
	var r=string(s[0:len(s)])
	fmt.Println(r)
	var checkType string=""
	re,_:=regexp.Compile("([^//']*)")
	s2:=re.FindAllString(r,-1)
	checkType=s2[3]
	fmt.Println("checkType:"+checkType)
	var checkcode string=""
	checkImg:
    if strings.Index(checkType,"!")==0{
		fmt.Println("Not Need checkcode")
		checkcode=checkType;	
 	}else{
		fmt.Println("Need checkcode")
		checkcode=getImg("http://captcha.qq.com:80/getimage?aid=1003903&uin="+qq+"&vc_type="+checkType,refer)	
	}
	fmt.Println("checkcode:"+checkcode)
	//接下来开始登陆了
	//第1次登陆
    loginUrl := "http://ptlogin2.qq.com:80/login?u="+qq+"&" +
	"p=" +GetCryPass(pass, checkcode)+
	"&verifycode="+checkcode+"&remember_uin=1&aid=1003903" +
	"&u1=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html%3Fstrong%3Dtrue" +
	"&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert";
	rb:=getUrl(loginUrl,refer)
	var loginS string=string(rb[:])
	fmt.Println(loginS)
	if strings.Index(loginS,"成功")>0{
		fmt.Println("第一次登陆成功!")
	}else if  strings.Index(loginS,"验证码有误")>0{
		fmt.Println("验证码有误!重新获取验证码图片")
		goto checkImg
	}else if  strings.Index(loginS,"密码有误")>0{
		fmt.Println("密码有误!")
		os.Exit(0)
	}else{
		fmt.Println("未知错误!")
		os.Exit(0)
	}
	ptwebqq=mcookies["ptwebqq"].Value
	skey=mcookies["skey"].Value
	fmt.Println("skey:"+skey)
	fmt.Println("ptwebqq:"+ptwebqq)
	
	//再次登陆,只有这次登陆,才算真正登陆qq,这个时候,如果你qq已经登陆,会把你的qq踢下线,而且此次登陆才算上线
    channelLoginUrl := "http://d.web2.qq.com:80/channel/login2";
    content := "{\"status\":\"\",\"ptwebqq\":\""+ptwebqq+"\",\"passwd_sig\":\"\",\"clientid\":\""+clientid+"\"}";
	content = urlEncode(content);//urlencode
	content = "r="+content;//post的数据
	res := PostUrl(channelLoginUrl,refer,[]byte(content));//post
	re_twice:=string(res[:]) //第二次返回是个json格式,如下,我们要获取 psessionid vfwebqq值
	/*
	{"retcode":0,"result":{"uin":526868457,"cip":1987728778,"index":1075,"port":40831,"status":"online","vfwebqq":"6c47630a8cd98902d38d919420ffb019141ba7f
	ebd6b8ce02b0b69d7b85e0ad2205c8f141a66f364","psessionid":"8368046764001d636f6e6e7365727665725f77656271714031302e3133342e362e31333800006023000005ee026e0
	400e95f671f6d0000000a4058474d6430776c35476d000000286c47630a8cd98902d38d919420ffb019141ba7febd6b8ce02b0b69d7b85e0ad2205c8f141a66f364","user_state":0,"f
	":0}}*/
   fmt.Print(re_twice)
   re,_=regexp.Compile("(vfwebqq\":\")([^\"]*)(\")")
   s2=re.FindStringSubmatch(re_twice)
   vfwebqq=s2[2];
   re,_=regexp.Compile("(psessionid\":\")([^\"]*)(\")")
   s2=re.FindStringSubmatch(re_twice)
   psessionid=s2[2]
   fmt.Println("psessionid:"+psessionid)
   fmt.Println("vfwebqq:"+vfwebqq)
   if len(vfwebqq)==0||len(psessionid)==0{
   fmt.Println("登陆失败");
   os.Exit(0)
   }
   //到此登陆成功  调用poll消息函数
   poll()
}
func urlEncode(urlin string) string{
    return http.URLEscape(urlin)
}
func poll(){
    var pollUrl string="http://d.web2.qq.com:80/channel/poll2?clientid="+clientid+"&psessionid="+psessionid
    for {
    fmt.Println("获取消息......................................")
    fmt.Println("Loop Get Message ......................................")
       s:=getUrl(pollUrl,refer);
       fmt.Println(string(s[:]))
    }
}
/*
 *获取验证码图片,并且返回输入验证码
 */
func getImg(urlin string ,refer string) string{
	imgByte:=getUrl(urlin,refer)
	fmt.Print("write img begin and the img length is:")
    fmt.Println(len(imgByte))
    err2 := ioutil.WriteFile("d:/aa.jpg", imgByte,0)
    if err2 != nil { 
		fmt.Println(err2)
		return ""
	} 
	fmt.Println("请打开文件:d:/aa.jpg 并输入验证码回车");
	fmt.Println("Need CheckCode Open :d:/aa.jpp input CheckCode");
	 var line string 
    _, err := fmt.Scanln(&line) 
    if err!=nil{
	return ""	
	}
	return line
}

/*
 *带cookie获取url
 */
func getUrl(urlin string ,refer string)([]byte){
	url, err := http.ParseURL(urlin)
	checkError(err)
	// build a TCP connection first
	host := url.Host
	conn, err := net.Dial("tcp", host)
    checkError(err)

	// then wrap an HTTP client connection around it
	clientConn := http.NewClientConn(conn, nil)
	if clientConn == nil {
		fmt.Println("Can't build connection")
		os.Exit(1)
	}
	// define the additional HTTP header fields
	header := map[string][] string {
	"Accept":{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*,q=0.8"},
	"Accept-Language":{"zh-cn,zh;q=0.5"},
	"Accept-Charset": {"UTF-8,utf-8;q=0.7,*;q=0.7"},
	"Connection":{"keep-alive"},
	"Referer": {refer},
	"User-Agent":{"Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0"} ,
	}
	// and build the request
	request := http.Request{Method: "GET", URL: url, Header: header}

	for _, value := range mcookies {
		request.AddCookie(value)
	}

	dump, _ := http.DumpRequest(&request, false)
	fmt.Println(string(dump))
	// send the request
	err = clientConn.Write(&request)
	checkError(err)
	// and get the response
	response, err := clientConn.Read(&request)
	checkError(err)
	if response.Status != "200 OK" {
		fmt.Println(response.Status)
		os.Exit(2)
	}
	//Set-cookie
	for i:=0;i<len(response.Cookies());i++{
		mcookies[response.Cookies()[i].Name]=response.Cookies()[i]
	}
	const NBUF = 1      
	var buf =make([]byte,NBUF) 
	//http://code.google.com/p/golang-china/wiki/go_tutorial
	reader := response.Body
	result :=make([]byte,0)
	//我们一个byte取可以有效避免数据覆盖的问题,不过与整块读取略微慢点,暂且这样写吧
	 for { 
		 switch nr, _ := reader.Read(buf[:]); true { 
			 case nr < 0: 
			   goto a1
			   break
		     case nr == 0:// EOF              
				goto a1
				break;            
			 case nr > 0:     
				result=append(result,buf[0])          
			} 
		}
a1:
	return result[0:len(result)];
}

/*
 *带cookie post
 */
func PostUrl(urlin string ,refer string,sendBytes []byte)([]byte){
	url, err := http.ParseURL(urlin)
	checkError(err)
	// build a TCP connection first
	host := url.Host
	conn, err := net.Dial("tcp", host)
    checkError(err)

	// then wrap an HTTP client connection around it
	clientConn := http.NewClientConn(conn, nil)
	if clientConn == nil {
		fmt.Println("Can't build connection")
		os.Exit(1)
	}
	// define the additional HTTP header fields
	header := map[string][] string {
	"Accept":{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*,q=0.8"},
	"Accept-Language":{"zh-cn,zh;q=0.5"},
	"Accept-Charset": {"UTF-8,utf-8;q=0.7,*;q=0.7"},
	"Content-Type":{"application/x-www-form-urlencoded"}   ,
	"Connection":{"keep-alive"},
	"Transfer-Encoding":{"chunked"},
	"Referer": {refer},
	"User-Agent":{"Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0"} ,
	}
	// and build the request
	request := http.Request{Method: "POST", URL: url, Header: header}
	request.ContentLength= (int64)(len(sendBytes))
	for _, value := range mcookies {
        request.AddCookie(value)
	}

	request.Body= &ClosingBuffer{bytes.NewBuffer(sendBytes)}

	dump, _ := http.DumpRequest(&request, false)
	fmt.Println(string(dump))
	// send the request
	err = clientConn.Write(&request)
	checkError(err)
	// and get the response
	response, err := clientConn.Read(&request)
	checkError(err)
	if response.Status != "200 OK" {
		fmt.Println(response.Status)
	}
	//Set-cookie
		for i:=0;i<len(response.Cookies());i++{
		mcookies[response.Cookies()[i].Name]=response.Cookies()[i]
	}
	const NBUF = 1      
	var buf =make([]byte,NBUF) 
	//http://code.google.com/p/golang-china/wiki/go_tutorial
	reader := response.Body
	result :=make([]byte,0)
	//我们一个byte取可以有效避免数据覆盖的问题,不过与整块读取略微慢点,暂且这样写吧
	 for { 
		 switch nr, _ := reader.Read(buf[:]); true { 
			 case nr < 0: 
			   goto a2
			   break
		     case nr == 0:// EOF              
				goto a2
				break;            
			 case nr > 0:     
				result=append(result,buf[0])          
			} 
		}
a2:
	return result[0:len(result)];
}

func checkError(err os.Error) {
        if err != nil {
                fmt.Println("Fatal error ", err.String())
                //os.Exit(1)
        }
}

/*
 *webqq加密方式
 */
func GetCryPass(pass string,code string) string{
	cryPss_3:=Getmd5_3(pass)
	cryPss_3=strings.ToUpper(hex.EncodeToString([]byte(cryPss_3)))+strings.ToUpper(code)
	r:=Getmd5(cryPss_3)
	return strings.ToUpper(hex.EncodeToString(r[0:len(r)]))
}

func Getmd5(original string) []byte { 
      var h hash.Hash = md5.New() 
      h.Write([]byte(original)) 
      //fmt.Printf("%x\n", h.Sum()) 
	return  h.Sum()
 } 

func Getmd5_3(in string) string{
	cry :=Getmd5(in)
	var r string=string(cry[0:len(cry)])
	cry =Getmd5(r)
	r=string(cry[0:len(cry)])
	cry =Getmd5(r)
	r=string(cry[0:len(cry)])
	return r 
}
//实现io.ReadCloser接口
type ClosingBuffer struct {
        *bytes.Buffer
}

func (cb *ClosingBuffer) Close() (err os.Error) {
        //we don't actually have to do anything here, since the buffer is
//just some data in memory
        //and the error is initialized to no-error
        return
}
分享到:
评论

相关推荐

    go语言webqq简单实现

    在本项目中,我们将探讨如何使用Go语言实现一个简单的WebQQ客户端。Go语言,也称为Golang,是由Google开发的一种静态类型的、编译型的、并发型的、垃圾回收的编程语言,以其简洁的语法和高效的性能在后端开发领域...

    WebQQ效果实现例子

    WebQQ是一种基于网页技术实现的在线聊天应用,它允许用户在浏览器中体验类似于桌面QQ的交互功能。这个“WebQQ效果实现例子”很显然是一个示例项目,旨在展示如何在Web环境中模拟桌面QQ的酷炫效果,如桌面拖拽、桌面...

    本源码已经实现webQQ的大部分功能

    本源码已经实现webQQ的大部分功能 熬了几个通宵终于做好了,里面实现的webQQ的大部分功能,而且全开源,适用中高级.net开发人员研究,主要是对 XML 的操作和ajax,还用了少量的JQ可以自由增加组,加好友等 数据库在...

    ext 实现的webQQ 源码、应用、含数据库

    在本压缩包中,重点是EXT框架实现的WebQQ源码,以及可能包含的数据库文件,这为我们提供了深入理解EXT框架在构建富互联网应用程序(RIA)方面的应用以及WebQQ背后的架构设计提供了宝贵的学习资源。 EXT是一个强大的...

    仿WEBQQ,只实现了前端

    【标题】"仿WEBQQ,只实现了前端"的项目是一个基于Web技术的QQ客户端模拟实现,专注于用户界面和交互设计的开发,旨在提供与原版WEBQQ类似的用户体验。这个项目并未涉及后端服务,因此不包含服务器通信、数据存储或...

    用go语言实现qq简易客户端.zip

    本项目的目标是用Go语言实现一个简易的QQ客户端,该项目不仅是一个编程实践,更是对Go语言特性的学习和运用。通过这个项目,开发者能够深入了解Go语言在实际应用中的表现,包括但不限于其网络通信、字符串处理、并发...

    JSP+Mysql 实现简易的 WebQQ

    【JSP+MySQL实现简易WebQQ】是一种基于Java服务器页面(JSP)技术和MySQL数据库构建的在线聊天系统,它允许用户通过网页进行即时通讯。在这个项目中,我们将深入探讨涉及的技术、步骤以及关键知识点。 首先,JSP是...

    webqq 界面实现代码 html 直接运行 和现有版本完全一致

    WebQQ界面的华丽效果主要由CSS实现,包括色彩、字体、布局、动画效果等,使得用户界面既美观又易用。 3. **JavaScript**:JavaScript是实现网页动态交互的关键,负责处理用户的输入、响应事件、更新页面内容等功能...

    ajax+servlet+jsp实现webqq

    【标题】:“Ajax + Servlet + JSP 实现WebQQ” 【描述】:此项目是基于Ajax、Servlet和JSP技术实现的一个网页版QQ应用。它旨在提供与原版QQ相似的功能,让用户能够在网页上进行即时通讯,无需安装任何客户端软件。...

    webQQ

    【标题】"WebQQ"揭示了我们讨论的主题是基于网页的QQ客户端实现,它允许用户在Web浏览器上体验类似于桌面版QQ的聊天功能。这种技术的实现基于Asp.net平台,利用C#编程语言编写了全部的源代码,旨在提供跨平台的即时...

    webqq2协议分析和qq聊天机器人简单实现

    【标题】"WebQQ2协议分析与QQ聊天机器人简单实现" 在互联网技术中,QQ作为一款流行的即时通讯软件,其背后的通信协议一直是开发者们研究的焦点。本话题主要围绕WebQQ2协议进行深入探讨,并介绍如何利用这些知识构建...

    WebQQ协议及客户端

    通过抓包分析WebQQ3.0协议做出的WebQQ客户端,开发工具Visual studio 2008,开发语言C#,此WebQQ客户端包括验证码获取,QQ登录,获取好友列表,获取在线好友列表,接收消息,发送消息等功能,基本上实现聊天需求。...

    仿WebQQ.rar

    这个项目是用纯JQuery技术实现的,这意味着它主要依赖于JQuery库来处理DOM操作、事件绑定、动画效果等。 【描述】提到,该项目的代码设计得易于理解,这对于开发者来说是一个巨大的优势。它意味着初学者或者有经验...

    webQQ协议2014版Java实现

    总的来说,这个项目展示了如何用Java语言实现WebQQ协议,实现QQ的基本功能,并通过NLP技术增强了其交互性。对于想要学习网络编程、即时通讯协议、NLP应用的开发者来说,这是一个非常有价值的参考案例。

    WebQQ_Demo WebQQ_Demo

    WebQQ_Demo是一个基于Web技术实现的QQ在线聊天示例应用。这个项目展示了如何利用Web技术来模拟原生QQ客户端的功能,让用户可以在浏览器上进行即时通讯。WebQQ_Demo的出现,是互联网技术和社交应用结合的一个典范,它...

    WebQQ协议.rar

    这个"WebQQ协议.rar"压缩包文件很可能包含了一组用易语言编写的源代码,用于解析和实现WebQQ协议的细节。 易语言是一种面向对象的、具有图形化编程界面的中文编程语言,它的设计理念是“易学易用”。通过这个源码,...

    WebQQ桌面布局 WebQQ

    WebQQ桌面布局是一种基于网页技术实现的QQ客户端界面设计,它允许用户在浏览器上体验类似于桌面应用的QQ聊天功能。这种布局充分利用了Web技术的优势,如JavaScript库jQuery,来实现动态交互和响应式设计,为用户提供...

    迷你QQ-WEBQQ

    迷你WEBQQ

    webQQ.rar_webqq

    【标题】"webQQ.rar_webqq" 涉及的核心技术是WebQQ的实现,这是一种基于Web技术的QQ客户端,允许用户在网页中直接使用QQ服务,无需下载和安装传统桌面版的QQ软件。WebQQ的出现使得即时通讯更加便捷,尤其对于那些...

    qt c++ webQQ 源码

    这个"qt c++ webQQ"源码项目,是开发者利用Qt库调用腾讯的Web接口,实现了一个高仿真的QQ客户端应用。 首先,我们要理解Qt库的核心特点。Qt库包含了丰富的类库,覆盖了图形绘制、网络通信、数据库访问、XML处理等多...

Global site tag (gtag.js) - Google Analytics