• C# WebQQ协议群发机器人(一)


    原创性申明

    本文地址 http://blog.csdn.net/zhujunxxxxx/article/details/38931287 转载的话请注明出处。

    之前我也写过一篇使用python来实现的一个版本号 点击打开链接

    前言

    如今我用c#语言改写过后也放出源代码来让大家学习,希望大家喜欢,不懂的相互交流,

    眼下我实现的一些功能包含  第一次登录  二次登陆 获取群信息  获取群好友 发送群消息 发送消息给好友

    先给出一些webqq的一些參数吧

     假设有人须要源代码能够联系我 qq: 10588690。可是不是无偿提供,请大家理解。

    协议分析

    psessionid 这个是在第二次登录的时候在 cookie中的一个重要的值,在后面获取群信息。获取好友信息等 都要用到这个參数

    vfwebqq 这个同上

    ptwebqq 同上

    hash  这个參数是后面发送群消息和好友消息须要用到的,曾经版本号没有 后面加上了

    先给出腾讯password加密算法  这部分我是用我曾经python版本号的 比較懒这部分没有转为c#版本号的

    #md5
        def PCMd5(self,s):
            h=hashlib.md5()
            h.update(s)
            return h.hexdigest()
        #16 to cgar
        def hex2asc(self,s):
            _str="".join(s.split(r'x'))
            length=len(_str)
            data=''
            for i in range(0,length,2):
                data+=chr(int(_str[i:i+2],16))
            return data
        #the password encrypt  v1 is checkcode
        def PasswordSecret(self,password,v1,v2,md5=True):
            if md5==True:
                password=self.PCMd5(password).upper()
            length=len(password)
            temp=''
            for i in range(0,length,2):
                temp+=r'x'+password[i:i+2]
            return self.PCMd5(self.PCMd5(self.hex2asc(temp)+self.hex2asc(v2)).upper()+v1).upper()


    Hash算法

    然后给的是hash算法

    /// <summary>
            /// 获取hash值的算法
            /// </summary>
            /// <param name="b"></param>
            /// <param name="j"></param>
            /// <returns></returns>
            public string Hash(string b, string j)
            {
                string a = j + "password error";
                string i = "";
                List<int> E = new List<int>();
                while(true)
                {
                    if (i.Length <= a.Length)
                    {
                        i += b;
                        if (i.Length == a.Length)
                        {
                            break;
                        }
                    }
                    else
                    {
                        i = i.Substring(0, a.Length);
                        break;
                    }
    
                }
                for (int c = 0; c < i.Length; c++)
                {
                    int tmp = (char)i[c] ^ (char)a[c];
                    E.Add(tmp);
                }
                string[] seed = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
                i = "";
                for (int c = 0; c < E.Count; c++)
                {
                    i += seed[E[c] >> 4 & 15];
                    i += seed[E[c] & 15];
                }
    
                return i;
            }


    这个函数的參数是 第一个是你的qq号 第二个是ptwebqq 之前一直以为是vfwebqq 结果一直出错

     这两个函数都是正确的,网上非常多的方法已经失效了

    是否须要验证码

    首先在登录时,你必须检查是否须要输入验证码 这个函数的返回值是一个字符串

    ptui_checkVC('0','!NTZ','x00x00x00x00x22x79x9fx0d', 'ef0e577a40249cc2b77dc9f266a3a4141a987d06a8f3ae39117183f1ff0491720e1f6f498a9a038f032d99f8622ea628');

    第一个參数是0 表示不须要输入參数,第二个參数是一个验证码 后面用来加密password的

    //检查是否须要 验证码
            public bool check()
            {
                string url = "https://ssl.ptlogin2.qq.com/check?

    uin={$uin}&appid=1003903&js_ver=10092&js_type=0&login_sig=K5F0E8woS74td4sRIqKiSHmH6B2RYYP467z2r*6YWaH4wc7vE*4G*X7V2kGP9s1*&u1=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html&r=0.2689784204121679"; url = url.Replace("{$uin}", this.qq); HttpItem item = new HttpItem() { URL = url,//URL 必需项 Encoding = System.Text.Encoding.GetEncoding("utf-8"),//URL 可选项 默觉得Get Method = "get",//URL 可选项 默觉得Get IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 Timeout = 100000,//连接超时时间 可选项默觉得100000 ReadWriteTimeout = 30000,//写入Post数据超时时间 可选项默觉得30000 UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本号,操作系统 可选项有默认值 ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 ResultType = ResultType.String, }; HttpResult result = http.GetHtml(item); Regex reg = new Regex(@"ptui_checkVC('(.*)','(.*)','(.*)', '(.*)');"); Match m = reg.Match(result.Html); string[] ret = new string[m.Groups.Count]; for (int i = 0; i < m.Groups.Count; i++) { ret[i] = m.Groups[i].Value; } this.checkv2 = ret[3]; if (ret[1] == "0") { this.checkcode = ret[2]; this.session = ret[4]; return false; } else return true; }


     一次登录

    接下来是我们第一次登录

    public bool Login()
            {
                string url = "https://ssl.ptlogin2.qq.com/login?u={$uin}&p={$pwd}&verifycode={$verify}&webqq_type=10&remember_uin=1&login2qq=0&aid=1003903&u1=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html%3Flogin2qq%3D0%26webqq_type%3D10&h=1&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=2-9-33854&mibao_css=m_webqq&t=1&g=1&js_type=0&js_ver=10092&login_sig=K5F0E8woS74td4sRIqKiSHmH6B2RYYP467z2r*6YWaH4wc7vE*4G*X7V2kGP9s1*&pt_uistyle=5&pt_vcode_v1=0&pt_verifysession_v1={$session}";
                url=url.Replace("{$uin}",this.qq);
                url=url.Replace("{$verify}",this.checkcode);
                string pwd = encrypt.Encrypt_Password(this.qq,this.password,this.checkcode);
                url=url.Replace("{$pwd}",pwd);
                url = url.Replace("{$session}", this.session);
                HttpItem item = new HttpItem()
                {
                    URL = url,
                    Encoding = System.Text.Encoding.GetEncoding("utf-8"),  
                    Method = "get",
                    IsToLower = false,
                    Timeout = 100000, 
                    Referer="https://ui.ptlogin2.qq.com/cgi-bin/login?daid=164&target=self&style=5&mibao_css=m_webqq&appid=1003903&enable_qlogin=0&no_verifyimg=1&s_url=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html&f_url=loginerroralert&strong_login=1&login_state=10&t=20140612002",
                    Host="d.web2.qq.com",
                    UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本号。操作系统     可选项有默认值   
                    ContentType = "application/x-www-form-urlencoded",
                    ResultType = ResultType.String
                };
                HttpResult result = http.GetHtml(item);
    
                foreach (Cookie c in result.CookieCollection)
                {
                    if (c.Name == "ptwebqq")
                        this.ptwebqq = c.Value;
                }
                this.hash= Hash(this.qq, this.ptwebqq);
    
                Regex reg = new Regex(@"ptuiCB('(.*)','(.*)','(.*)','(.*)','(.*)',s'(.*)');");
                Match m = reg.Match(result.Html);
                string[] ret = new string[m.Groups.Count];
                for (int i = 0; i < m.Groups.Count; i++)
                {
                    ret[i] = m.Groups[i].Value;
                }
                if (ret[1] == "0")
                {
                    this.proxyurl = ret[3];
                    return true;
                }
                else
                    return false;
                
            }


    第一次登录后会返回 return ptuiCB('0','0','http://ptlogin4.web2.qq.com/check_sig?pttype=1&uin=578395917&service=login&nodirect=0&ptsig=uV34Xt9XM3e2oQ3wuub8LIBIGsIIZATjiz-cqSVHJ5o_&s_url=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html%3Flogin2qq%3D0%26webqq_type%3D10&f_url=&ptlang=2052&ptredirect=100&aid=1003903&daid=164&j_later=0&low_login_hour=0&regmaster=0&pt_login_type=1&pt_aid=0&pt_aaid=0&pt_light=0','0','登录成功!', '你的名字');

    假设第一个參数不是0的话 表示有错,假设像这种话就表示成功了

    返回结果中的那个ur链接我们用get方式打开它,这个步骤是为了获取一个关键的cookie值 p_skey 这个是第二次登录的时候实用

     二次登陆

    接下来是我们二次登录了

    public void Login2()
            {
                
                Dictionary<string, Object> r = new Dictionary<string, Object>();
                r.Add("status", "online");
                r.Add("ptwebqq", this.ptwebqq);
                r.Add("passwd_sig", "");
                r.Add("clientid", this.clientid.ToString());
                r.Add("psessionid", null);
                Dictionary<string, Object> data = new Dictionary<string, Object>();
                data.Add("r", JsonConvert.SerializeObject(r));
                data.Add("clientid", this.clientid);
                data.Add("psessionid", "null");
                string postdata = Tool.MakePostData(data);
                
                //string postdata="r=%7B%22status%22%3A%22online%22%2C%22ptwebqq%22%3A%22{$ptwebqq}%22%2C%22passwd_sig%22%3A%22%22%2C%22clientid%22%3A%22{$clientid}%22%2C%22psessionid%22%3Anull%7D&clientid={$clientid}&psessionid=null";
                //postdata=postdata.Replace("{$ptwebqq}",this.ptwebqq);
                //postdata = postdata.Replace("{$clientid}", this.clientid);
                HttpItem item = new HttpItem()
                {
                    URL = "http://d.web2.qq.com/channel/login2",//URL     必需项     
                    Method = "POST",//URL     可选项 默觉得Get
                    IsToLower = false,//得到的HTML代码是否转成小写     可选项默认转小写
                    Timeout = 100000,//连接超时时间     可选项默觉得100000    
                    Postdata=postdata,
                    Host=HOST[0],
                    Referer=REFERER[0],
                    UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36",//用户的浏览器类型。版本号,操作系统     可选项有默认值   
                    ContentType = "application/x-www-form-urlencoded",//返回类型    可选项有默认值
                    Accept="*/*",
                    ResultType = ResultType.String
                };
                HttpResult result = http.GetHtml(item);
                JObject obj = (JObject)JsonConvert.DeserializeObject(result.Html);
                this.vfwebqq= obj["result"]["vfwebqq"].ToString();
                this.psessionid = obj["result"]["psessionid"].ToString();
    
            }


    这个步骤非常重要,获取非常多实用的cookie值,上面提到的那些就要用一个变量保存下来,以便后面使用

    获取群列表

    以下我们就要拉去我们的群组信息了

    这个返回结果是一个json格式的,我们须要序列化为json对象,把里面的群相关信息存起来

    /// <summary>
            /// 获取群列表
            /// </summary>
            public void GetGroupNameList()
            {
                
                Dictionary<string, Object> r = new Dictionary<string, Object>();
                r.Add("hash", this.hash);
                r.Add("vfwebqq", this.vfwebqq);
                Dictionary<string, Object> data = new Dictionary<string, Object>();
                data.Add("r", JsonConvert.SerializeObject(r));
                string postdata = Tool.MakePostData(data);
                
                //string postdata = "r=%7B%22hash%22%3A%22{$hash}%22%2C%22vfwebqq%22%3A%22{$vfwebqq}%22%7D";
                //postdata = postdata.Replace("{$hash}", this.hash);
                //postdata = postdata.Replace("{$vfwebqq}", this.vfwebqq);
                HttpItem item = new HttpItem()
                {
                    URL = "http://s.web2.qq.com/api/get_group_name_list_mask2",
                    Method = "POST",
                    IsToLower = false,
                    Timeout = 100000,
                    Postdata = postdata,
                    Host = HOST[1],
                    Referer = REFERER[1],
                    UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36",//用户的浏览器类型。版本号,操作系统     可选项有默认值   
                    ContentType = "application/x-www-form-urlencoded",
                    ResultType = ResultType.String
                };
                HttpResult result = http.GetHtml(item);
                JObject ret = (JObject)JsonConvert.DeserializeObject(result.Html);
                JObject retjson = (JObject)ret["result"];
                foreach (JToken jk in retjson["gnamelist"])//获取群信息用 code  发送群信息用 gid
                {
                    this.grouplist.Add(jk["gid"].ToString()+":"+jk["code"].ToString(), jk["name"].ToString());
                }
    
            }


    每一个群 有个gid 和code  name  当中获取群成员的使用code 而向群发送消息的时候用的是gid 这部分一定要注意 我花了非常多时间才发现自己的错误

     群信息

    获取某个群的群成员信息 參数就是上面提到的code 不要用错了哦

    /// <summary>
            /// 依据群code得到群信息
            /// </summary>
            /// <param name="gcode"></param>
            public void GetGroupInfo(string gcode)
            {
                string url = "http://s.web2.qq.com/api/get_group_info_ext2?

    gcode={$gcode}&cb=undefined&vfwebqq={$vfwebqq}&t=1409316979595"; url=url.Replace("{$vfwebqq}",this.vfwebqq); url = url.Replace("{$gcode}", gcode); HttpItem item = new HttpItem() { URL = url, Encoding = System.Text.Encoding.GetEncoding("utf-8"), Method = "get", IsToLower = false, Timeout = 100000, ReadWriteTimeout = 30000, Host=HOST[1], Referer=REFERER[1], UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本号,操作系统 可选项有默认值 ContentType = "application/x-www-form-urlencoded", ResultType = ResultType.String, }; HttpResult result = http.GetHtml(item); JObject ret = (JObject)JsonConvert.DeserializeObject(result.Html); JObject retjson = (JObject)ret["result"]; foreach (JToken jk in retjson["cards"]) { this.groupinfo.Add(jk["muin"].ToString(), jk["card"].ToString()); } }

    发送群消息

    以下是向群里面发送消息  这个用的就是刚才说的 gid 也不要用错了

    public void SendGroupMsg(long groupid,string msg)
            {
                string style=""{content}"";
                string temp="";
                temp += style.Replace("{content}", msg) + ",";
                temp = temp.Substring(0, temp.Length - 1);
                Random rd = new Random();
                int msg_id = (rd.Next(100000) + 100000);
                string content="[{$msg},"",["font",{"name":"宋体","size":"10","style":[0,0,0],"color":"000000"}]]";
                content = content.Replace("{$msg}", temp);
                
                Dictionary<string, Object> r = new Dictionary<string, Object>();
                r.Add("group_uin", groupid);
                r.Add("content", content);
                r.Add("msg_id", msg_id);
                r.Add("clientid", this.clientid);
                r.Add("psessionid",this.psessionid);
                Dictionary<string, Object> data = new Dictionary<string, Object>();
                data.Add("r", JsonConvert.SerializeObject(r));
                data.Add("clientid", this.clientid);
                data.Add("psessionid", this.psessionid);
                string postdata = Tool.MakePostData(data);
                
                HttpItem item = new HttpItem()
                {
                    URL = "http://d.web2.qq.com/channel/send_qun_msg2",
                    Accept="*/*",
                    Method = "POST",
                    IsToLower = false,
                    KeepAlive=true,
                    Timeout = 100000,
                    Postdata = postdata,
                    Host = HOST[0],
                    Referer = REFERER[0],
                    UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2041.4 Safari/537.36",
                    ContentType = "application/x-www-form-urlencoded",
                    ResultType = ResultType.String
                };
                HttpResult result = http.GetHtml(item);
                JObject ret = (JObject)JsonConvert.DeserializeObject(result.Html);
                
                //string html = HttpHelper2.GetHtml("http://d.web2.qq.com/channel/send_qun_msg2", postdata,HttpHelper.cookies);
    
            }


    接下来还有 获取好友信息和 向好友发送消息...

    这一部分我放在下一篇将    头昏啊!

    sorry!

  • 相关阅读:
    ABAP——动态排序内表
    通过jmeter往kafka写入数据
    清空kafka全部数据
    redis命令
    Eureka的工作原理
    Spring Cloud Ribbon 原理解析
    Redis单实例数据迁移到集群
    Spring Cloud Hystrix
    ElasticSearch
    关于Java导出100万行数据到Excel的优化方案
  • 原文地址:https://www.cnblogs.com/llguanli/p/7249567.html
Copyright © 2020-2023  润新知