嗨玩手游网

Go集合VC实现简单的QQ消息派发接口

不少微信QQ机器人大多通过分析通讯包,模拟包方式实现消息的发送,该方式会随着QQ 微信的升级儿很容易失效需要不断升级。通过模拟界面操作方式虽然也存在界面改变失效的问题,但该方式相对协议方式失效的周期应该更长一点。闲来无事儿,实现一个简单QQ消息投送,原理主要通过Go实现web接口便于外部通过浏览器或http或websocket接口给指定的QQ发送消息,web服务接收到消息后,通过回调函数通知VC实现对指定QQ窗口操作完成消息的发送

VC主要通过查找指定QQ号主窗口,查找要发送QQ消息的QQ号,模拟点击,模拟键盘输入,实现消息的投送

Go编写dll由VC调用

主要代码实现如下

Go部分

//Go导出函数便于VC调用

/*

#cgo CFLAGS: -I .

#include <unistd.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

typedef void (*callback)(int,void *,int,void *,int);

extern void c_callback (int,void *,int,void *,int);

extern callback _cb;

*/

import "C"

import "unsafe"

/*以下两行标识导出特别重要*/

//InitHttpWebSocket :

//export InitHttpWebSocket

//初始Web服务和websocket服务,node为websocket接口调用名,nPort为web服务接口,pClass为VC的类指针,p为回调函数

func InitHttpWebSocket(node string, nPort int, pClass int, p C.callback) (bool, string) {

//myConfig := new(Config.Config)

//sInitFile := Share.GetCurrentDirectory() + "/web/conf/appi"

//myConfig.InitConfig(sInitFile)

m_AddrMap = make(map[string]OneWSLink)

if p != nil {

C._cb = p

//WebSocketCallBack(0, "call OK", 4)

pSaveClass = pClass

}

t1 := time.Now()

go InitHTTP(t1, nPort, node)

str := "正在初始化"

WebSocketCallBack(pSaveClass, "", 0, str)

return true, "正在初始化"

}

//数据处理函数

func ActionAPI(res http.ResponseWriter, req *http.Request, ModeName, FName string, m_VarHH map[string]interface{}) {

fmt.Println(ModeName, FName)

var m_ReturnJson ReturnJson

switch ModeName {

case "CORESYS.SYS":

switch FName {

case "API":

//获得参数核实参数合法性

ok, _ := GetParameValues(m_VarHH, "appid", "sign", "action")

if !ok {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "缺少必要参数"

NETReturnData(res, req, m_ReturnJson)

return

}

var keyArray = [...]string{}

keyArrayT := keyArray[:]

for k, _ := range m_VarHH {

if k != "sign" {

keyArrayT = append(keyArrayT, k)

}

}

sort.Strings(keyArrayT)

fmt.Println(keyArrayT)

_, appid := GetParameValue(m_VarHH, "appid")

_, sign := GetParameValue(m_VarHH, "sign")

appkeyString := ""

if isDBSave {

fmt.Println("采用数据库存储")

ok, m_Rows := m_baseDB.XNGetRecord(false, "select appkey from sys_apps where appid=?", appid)

if ok {

if len(m_Rows) == 0 {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "未能查询到appid:" + appid

NETReturnData(res, req, m_ReturnJson)

return

}

appkey, ok := m_Rows[0]["appkey"]

if ok {

appkeyString = appkey.(string)

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "查询appid:" + appid + "的appkey失败"

NETReturnData(res, req, m_ReturnJson)

}

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "查询appid:" + appid + "失败"

NETReturnData(res, req, m_ReturnJson)

return

}

} else {

fmt.Println("采用INI存储")

m_oneApp, ok := m_AppIDMAP[appid]

if ok {

appkeyString = m_oneApp.AppKey

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "查询appid:" + appid + "失败"

NETReturnData(res, req, m_ReturnJson)

return

}

}

ok, m_PArray := GetParameValues(m_VarHH, keyArrayT...)

str := ""

for i := 0; i < len(m_PArray); i++ {

str += m_PArray[i]

}

str += appkeyString

fmt.Println("原始计算:" + str)

str = Share.GetMd5String(str)

fmt.Println("计算结果:" + str)

if str == sign {

bArray, _ := json.Marshal(m_VarHH)

jsonString := string(bArray)

//调用VC回调函数

WebSocketCallBack(pSaveClass, req.RemoteAddr, 1, jsonString)

m_ReturnJson.BOK = true

m_ReturnJson.sg = "执行正常"

NETReturnData(res, req, m_ReturnJson)

return

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "sign验证失败"

fmt.Println("sign验证失败")

}

NETReturnData(res, req, m_ReturnJson)

default:

m_ReturnJson.BOK = false

m_ReturnJson.sg = "未实现的函数:" + FName

NETReturnData(res, req, m_ReturnJson)

}

default:

m_ReturnJson.BOK = false

m_ReturnJson.sg = "未实现应用:" + ModeName + ",函数:" + FName

NETReturnData(res, req, m_ReturnJson)

}

}

//页面处理函数

func HomePage(res http.ResponseWriter, req *http.Request) {

fmt.Println("dom:", req.Host)

fmt.Println("url:", req.RequestURI)

url := req.RequestURI

nPos := strings.Index(url, "?")

if nPos != -1 {

url = Share.Substr(url, 0, nPos)

}

DefaultModeName := "CORESYS.SYS"

DefaultFuncName := "INDEX"

var MName, FName string

var urlArray []string = strings.Split(strings.ToUpper(url), "/")

nn := len(urlArray)

if nn >= 1 {

if nn == 1 {

MName = urlArray[0]

FName = DefaultFuncName

} else {

MName = urlArray[nn-2]

FName = urlArray[nn-1]

}

} else {

MName = DefaultModeName

FName = DefaultFuncName

}

if MName == "" {

MName = DefaultModeName

}

if FName == "" {

FName = DefaultFuncName

}

if FName == "FICON.ICO" {

b, err := ioutil.ReadFile(Share.GetCurrentDirectory() + "/web/favicon.ico")

if err != nil {

fmt.Print(err)

return

}

res.Header().Set("Content-Type", "image/x-icon")

res.Header().Set("Content-Length", strconv.Itoa(len(b)))

res.Write(b)

b = nil

return

}

ReturnType := 0

nIndex := strings.Index(FName, ".")

strLength := len([]byte(FName))

if nIndex != -1 {

DotName := Share.Substr(FName, nIndex+1, strLength-nIndex-1)

FName = Share.Substr(FName, 0, nIndex)

nIndex = strings.Index(FName, "_RAWJSON")

if nIndex != -1 {

ReturnType = 2

} else {

fmt.Println("DotName", DotName)

if DotName == "AJAX" {

ReturnType = 1

}

}

} else {

nIndex := strings.Index(FName, "_RAWJSON")

if nIndex != -1 {

ReturnType = 2

}

}

fmt.Println("ReturnType:", ReturnType)

if ReturnType == 1 {

var m_ReturnJson ReturnJson

fmt.Println("获得数据")

m_VarHH := GetRequestParameHH(req)

isQQ := true

var m_PArray []string

var ok bool

ok, m_PArray = GetParameValues(m_VarHH, "appid", "msg", "qq", "sign", "qqnickname")

if ok {

} else {

ok, m_PArray = GetParameValues(m_VarHH, "appid", "msg", "weixin", "sign", "weixinnickname")

if !ok {

//处理数据

ActionAPI(res, req, MName, FName, m_VarHH)

return

}

isQQ = false

}

//bArray, _ := json.Marshal(m_Vars)

//fmt.Println(string(bArray))

if ok {

//fmt.Println("appid:" + m_PArray[0])

//fmt.Println("msg:" + m_PArray[1])

//fmt.Println("qq:" + m_PArray[2])

//fmt.Println("sign:" + m_PArray[3])

appid := m_PArray[0]

msg := m_PArray[1]

qq := m_PArray[2]

sign := m_PArray[3]

nickname := m_PArray[4]

appkeyString := ""

if isDBSave {

fmt.Println("采用数据库存储")

ok, m_Rows := m_baseDB.XNGetRecord(false, "select appkey from sys_apps where appid=?", appid)

if ok {

if len(m_Rows) == 0 {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "未能查询到appid:" + appid

NETReturnData(res, req, m_ReturnJson)

return

}

appkey, ok := m_Rows[0]["appkey"]

if ok {

appkeyString = appkey.(string)

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "查询appid:" + appid + "的appkey失败"

NETReturnData(res, req, m_ReturnJson)

}

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "查询appid:" + appid + "失败"

NETReturnData(res, req, m_ReturnJson)

return

}

} else {

fmt.Println("采用INI存储")

m_oneApp, ok := m_AppIDMAP[appid]

if ok {

appkeyString = m_oneApp.AppKey

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "查询appid:" + appid + "失败"

NETReturnData(res, req, m_ReturnJson)

return

}

}

str := ""

if isQQ {

str = "appid=" + m_PArray[0] + "&msg=" + msg + "&qq=" + qq + "&qqnickname=" + nickname + appkeyString

} else {

str = "appid=" + m_PArray[0] + "&msg=" + msg + "&weixin=" + qq + "&weixinnickname=" + nickname + appkeyString

}

fmt.Println("原始计算:" + str)

str = Share.GetMd5String(str)

fmt.Println("计算结果:" + str)

if str == sign {

m_ReturnJson.BOK = true

m_ReturnJson.sg = "OK"

fmt.Println("sign验证成功")

jsonString := ""

word := PickupHTML(msg)

/*

doc, err := goquery.NewDocument(msg)

if err != nil {

//log.Fatal(err)

}

doc.Find("img").Each(func(i int, s *goquery.Selection) {

src, _ := s.Attr("src")

fmt.Printf("img:%s\n", src)

})

*/

imgs := PickupImages(msg)

if len(word) > 50 {

word = Share.Substr(word, 0, 50)

}

onClickURL := ""

FString := "onclick=\"javascript:window.location.href='"

nPos := Share.StringIndex(msg, FString)

if nPos != -1 {

rightString := Share.Substr(msg, nPos+len(FString), -1)

fmt.Println("rightString:" + rightString)

FString = "';"

nPos = Share.StringIndex(rightString, FString)

if nPos != -1 {

onClickURL = Share.Substr(rightString, 0, nPos)

}

}

fmt.Println("onClickURL:" + onClickURL)

m_Data := make(map[string]interface{})

if isQQ {

m_Data["qq"] = qq

m_Data["datatype"] = "qq"

m_Data["nickname"] = nickname

} else {

m_Data["weixin"] = qq

m_Data["datatype"] = "weixin"

m_Data["nickname"] = nickname

}

m_Data["word"] = word

if imgs != nil {

m_Data["imgs"] = imgs

}

if onClickURL != "" {

m_Data["link"] = onClickURL

}

m_Data["rawtext"] = msg

m_Data["action"] = "sendmsg"

bArray, _ := json.Marshal(m_Data)

jsonString = string(bArray)

//回调通知VC处理

WebSocketCallBack(pSaveClass, req.RemoteAddr, 1, jsonString)

return

} else {

m_ReturnJson.BOK = false

m_ReturnJson.sg = "sign验证失败"

fmt.Println("sign验证失败")

}

NETReturnData(res, req, m_ReturnJson)

}

}

t, err := template.ParseFiles("web/index.html")

if err != nil {

fmt.Println(err)

return

}

err = WriteTemplateToHttpResponse(res, t)

if err != nil {

fmt.Println(err)

return

}

}

VC部分主要代码

//初始化函数部分

void CWebRobotDlg::OnButton1()

{

// TODO: Add your control notification handler code here

m_RobotEngine.InitEngine();

char m_Data[500];

int nDataL=500;

GoString m_GoString=GoStringClass::CString2GoString("ws",(char *)m_Data,nDataL);

InitHttpWebSocket_return m_InitHttpWebSocket_return=InitHttpWebSocket(m_GoString, 12000, (DWORD)this,WSCallBack);

if((BOOL)m_InitHttpWebSocket_return.r0)

{

m_BT.EnableWindow(false);

}

}

其中m_RoboteEngine为实际操作QQ操作的类,主要代码将在下面提供

VC的回调函数

void WSCallBack(int pClass,void *WSAddress,int NetEvent,void *pData,int nDataL)

{

CWebRobotDlg *pCWebRobotDlg=(CWebRobotDlg *)pClass;

printf("NetEvent:%d\r\n",NetEvent);

CString sText="";

if(nDataL>0)

{

char *pText=CChineseCodeLib::UTF_8ToGB2312((char *)pData, nDataL);

pCWebRobotDlg->AddMsg(pText);

sText.Format("%s",pText);

//printf("sText:\r\n%s\r\n",pText);

delete[]pText;

}

switch(NetEvent)

{

case 1:

{

HANDLE hJson=TextToJson((char *)(const char *)sText);

if(hJson!=NULL)

{

//真正处理消息函数

pCWebRobotDlg->ActionJson(hJson);

CloseJson(hJson);

}

//pCWebRobotDlg->ActionQQ();

}

break;

}

}

//处理函数

void CWebRobotDlg::ActionJson(HANDLE hJson)

{

CString sAction;

CString sName="datatype",sValue,sType,sDataType="";

CString NO,Word,Link,RawText,NickName;

CStringArray m_PICArray;

sName="action";

if(GetMFCJsonVar(hJson, sName,sAction,sType))

{

if(sAction=="sendmsg")

{

sName="datatype";

if(GetMFCJsonVar(hJson, sName,sValue,sType))

{

if(sValue=="qq")

{

sDataType=sValue;

GetMFCJsonVar(hJson, "qq",NO,sType);

}

else

{

if(sValue=="weixin")

{

sDataType="weixin";

GetMFCJsonVar(hJson, "weixin",NO,sType);

}

}

GetMFCJsonVar(hJson, "word",Word,sType);

GetMFCJsonVar(hJson, "rawtext",RawText,sType);

GetMFCJsonVar(hJson, "link",Link,sType);

CString FString="title=";

int nPos=Link.Find(FString);

if(nPos!=-1)

{

CString LString=Link.Mid(0,nPos);

CString RString=Link.Mid(nPos);

Link=LString+"&"+RString;

FString="linkto=";

nPos=Link.Find(FString);

if(nPos!=-1)

{

LString=Link.Mid(0,nPos);

RString=Link.Mid(nPos);

Link=LString+"&"+RString;

}

}

GetMFCJsonVar(hJson, "nickname",NickName,sType);

int nSize=GetJsonArraySize(hJson,"imgs");

CString PICString="";

for(int i=0;i<nSize;i++)

{

sName.Format("imgs[%d]",i);

GetMFCJsonVar(hJson, sName,sValue,sType);

m_PICArray.Add(sValue);

if(PICString!="")

{

PICString+=",";

}

PICString+=sValue;

}

CString TStr;

TStr.Format("DataType:%s,NO:%s,NickName:%s,Word:%s,Link:%s,ImgSize:%d,imgs:%s",(char *)(const char *)sDataType,(char *)(const char *)NO,(char *)(const char *)NickName,(char *)(const char *)Word,(char *)(const char *)Link,nSize,(char *)(const char *)PICString);

AddMsg((char *)(const char *)TStr);

if(sDataType=="qq" || sDataType=="weixin")

{

OneMsg *pOneMsg=new OneMsg();

pOneMsg->m_msgType=sDataType;

pOneMsg->m_textArray.Add(Word);

pOneMsg->m_textArray.Add(Link);

pOneMsg->m_linkUrl=Link;

for(int i=0;i<m_PICArray.GetSize();i++)

{

pOneMsg->m_imageArray.Add(m_PICArray.GetAt(i));

}

if(sDataType=="qq")

{

sprintf(pOneMsg->m_Robot.m_OneQQ.QQ,"%s",(char *)(const char *)NO);

sprintf(pOneMsg->m_Robot.m_OneQQ.QQName,"%s",(char *)(const char *)NickName);

}

else

{

if(sDataType=="weixin")

{

sprintf(pOneMsg->m_Robot.m_OneWX.WX,"%s",(char *)(const char *)NO);

sprintf(pOneMsg->m_Robot.m_OneWX.WXName,"%s",(char *)(const char *)NickName);

}

else

{

delete pOneMsg;

return;

}

}

//要处理的消息投递给RobotEngine处理,RobotEngine的代码后面提供

m_RobotEngine.AddOneMsg(pOneMsg);

}

}

}

else

{

printf("未实现的动作:%s\r\n",(char *)(const char *)MFCJsonToText(hJson));

}

}

}

RobotEngine操作QQ发送消息核心代码如下

RobotEngine::RobotEngine()

{

bInit=false;

}

RobotEngine::~RobotEngine()

{

if(bInit)

{

::DeleteCriticalSection(&m_SendWorkCS);

::DeleteCriticalSection(&m_RobotCS);

::DeleteCriticalSection(&m_GetMessageCS);

}

}

void RobotEngine::InitEngine()

{

if(bInit)

return;

bInit=true;

::InitializeCriticalSection(&m_SendWorkCS);

::InitializeCriticalSection(&m_RobotCS);

::InitializeCriticalSection(&m_GetMessageCS);

hSendStartEvent=::CreateEvent(NULL,true,false,NULL);

hGetMessageStartEvent=::CreateEvent(NULL,true,false,NULL);

hExitEvent=::CreateEvent(NULL,true,false,NULL);

CWinThread *pThread=AfxBeginThread(PostMessageThread,this);

pThread->m_bAutoDelete=true;

pThread=AfxBeginThread(GetMessageThread,this);

pThread->m_bAutoDelete=true;

LoadQQGroup();

}

UINT RobotEngine::PostMessageThread(LPVOID p)

{

RobotEngine *pRobotEngine=(RobotEngine*)p;

pRobotEngine->ActionPostMessage();

return 0;

}

UINT RobotEngine::GetMessageThread(LPVOID p)

{

RobotEngine *pRobotEngine=(RobotEngine*)p;

pRobotEngine->ActionGetMessage();

return 0;

}

void RobotEngine::ActionPostMessage()

{

HANDLE m_Events[2];

m_Events[0]=hSendStartEvent;

m_Events[1]=hExitEvent;

while(true)

{

DWORD nWait=WaitForMultipleObjects(2,m_Events,false,INFINITE);

switch(nWait)

{

case WAIT_OBJECT_0:

{

ActionOneMsg();

}

break;

case WAIT_OBJECT_0+1:

{

ClearPostWork();

return;

}

break;

default:

{

}

break;

}

}

}

void RobotEngine::ActionGetMessage()

{

HANDLE m_Events[2];

m_Events[0]=hGetMessageStartEvent;

m_Events[1]=hExitEvent;

while(true)

{

DWORD nWait=WaitForMultipleObjects(2,m_Events,false,INFINITE);

switch(nWait)

{

case WAIT_OBJECT_0:

{

ActionGetMsg();

}

break;

case WAIT_OBJECT_0+1:

{

ClearAllGetMsg();

return;

}

break;

default:

{

}

break;

}

}

}

//添加任务

void RobotEngine::AddOneMsg(OneMsg *pOneMsg)

{

::EnterCriticalSection(&m_SendWorkCS);

m_SendWorkPtr.AddTail(pOneMsg);

if(m_SendWorkPtr.GetCount()==1)

{

::SetEvent(hSendStartEvent);

}

::LeaveCriticalSection(&m_SendWorkCS);

}

void RobotEngine::ClearPostWork()

{

::EnterCriticalSection(&m_SendWorkCS);

for(int i=0;i<m_SendWorkPtr.GetCount();i++)

{

OneMsg *pOneMsg=(OneMsg *)m_SendWorkPtr.GetAt(m_SendWorkPtr.FindIndex(i));

delete pOneMsg;

}

m_SendWorkPtr.RemoveAll();

::LeaveCriticalSection(&m_SendWorkCS);

}

void RobotEngine::ActionOneMsg()

{

OneMsg *pOneMsg=NULL;

::EnterCriticalSection(&m_SendWorkCS);

if(m_SendWorkPtr.GetCount()>0)

{

pOneMsg=(OneMsg *)m_SendWorkPtr.GetHead();

m_SendWorkPtr.RemoveHead();

if(m_SendWorkPtr.GetCount()==0)

{

::ResetEvent(hSendStartEvent);

}

}

::LeaveCriticalSection(&m_SendWorkCS);

if(pOneMsg!=NULL)

{

::EnterCriticalSection(&m_RobotCS);

if(pOneMsg->m_msgType=="qq")

{

QQRobot::PostQQRichMessage((char *)pOneMsg->m_Robot.m_OneQQ.QQ,(char *)pOneMsg->m_Robot.m_OneQQ.QQName,pOneMsg->m_imageArray,pOneMsg->m_textArray);

}

else

{

if(pOneMsg->m_msgType=="weixin")

{

WXRobot::PostWXRichMessage((char *)pOneMsg->m_Robot.m_OneWX.WXName,pOneMsg->m_imageArray,pOneMsg->m_textArray);

}

else

{

if(pOneMsg->m_msgType=="qqgroupmember")

{

QQRobot::PostGoupMember(pOneMsg->m_Robot.m_OneGroupMember.GroupQQ,pOneMsg->m_Robot.m_OneGroupMember.GroupName,pOneMsg->m_Robot.m_OneGroupMember.ToQQ,pOneMsg->m_Robot.m_OneGroupMember.ToQQName,pOneMsg->m_imageArray,pOneMsg->m_textArray);

}

}

}

::LeaveCriticalSection(&m_RobotCS);

delete pOneMsg;

}

Sleep(2000);

}

//具体执行一个消息

void RobotEngine::ActionOneGetMsg(OneGetMsg *pOneGetMsg)

{

::EnterCriticalSection(&m_RobotCS);

QQRobot::ActionQQGroupMessage(pOneGetMsg);

::LeaveCriticalSection(&m_RobotCS);

}

CString RobotEngine::GetDBString()

{

//Provider=SQLOLEDB.1;Connect Timeout=10;Persist Security Info=true;Initial Catalog=Ticket;Data Source=127.0.0.1;User ID=sa;Password=;

CString TStr,Path;

CString IP,DBName,UserName,PWD;

char tt[200];

GetModuleFileName(NULL,tt,200);

TStr.Format("%s",tt);

int nWei=TStr.ReverseFind('\\');

TStr=TStr.Mid(0,nWei+1);

Path=TStr+"web\\conf\\appi";

char Xiang[40];

sprintf(Xiang,"连接IP");

GetPrivateProfileString("WEB服务配置",Xiang,"",tt,200,Path);

IP.Format("%s",tt);

sprintf(Xiang,"库名");

GetPrivateProfileString("WEB服务配置",Xiang,"",tt,200,Path);

DBName.Format("%s",tt);

sprintf(Xiang,"库用户名");

GetPrivateProfileString("WEB服务配置",Xiang,"",tt,200,Path);

UserName.Format("%s",tt);

sprintf(Xiang,"库密码");

GetPrivateProfileString("WEB服务配置",Xiang,"",tt,200,Path);

PWD.Format("%s",tt);

CString DBString="";

DBString.Format("Provider=SQLOLEDB.1;Connect Timeout=10;Persist Security Info=true;Initial Catalog=%s;Data Source=%s;User ID=%s;Password=%s",(char *)(const char *)DBName,(char *)(const char *)IP,(char *)(const char *)UserName,(char *)(const char *)PWD);

return DBString;

}

void RobotEngine::SetOneQQWord(CString GroupName, oneQQWord &m_oneQQWord)

{

oneQQWord m_oneQQWordT;

if(m_QQGroupWordMAP.Lookup(GroupName,m_oneQQWordT))

{

}

else

{

m_QQGroupWordMAP.SetAt(GroupName,m_oneQQWord);

}

}

BOOL RobotEngine::GetOneQQWord(CString GroupName, oneQQWord &m_oneQQWord)

{

return m_QQGroupWordMAP.Lookup(GroupName,m_oneQQWord);

}

void RobotEngine::AddOneGetMsg(OneGetMsg *pOneGetMsg)

{

::EnterCriticalSection(&m_GetMessageCS);

OneGetMsg *pTOneGetMsg=new OneGetMsg();

pTOneGetMsg->GroupName=pOneGetMsg->GroupName;

pTOneGetMsg->GroupQQ=pOneGetMsg->GroupQQ;

pTOneGetMsg->GroupMainKey=pOneGetMsg->GroupMainKey;

pTOneGetMsg->m_oneQQWordLast.QQName=pOneGetMsg->m_oneQQWordLast.QQName;

pTOneGetMsg->m_oneQQWordLast.Time=pOneGetMsg->m_oneQQWordLast.Time;

pTOneGetMsg->m_oneQQWordLast.Word=pOneGetMsg->m_oneQQWordLast.Word;

int i;

for(i=0;i<pOneGetMsg->QQArray.GetSize();i++)

{

pTOneGetMsg->QQArray.Add(pOneGetMsg->QQArray.GetAt(i));

}

for(i=0;i<pOneGetMsg->QQNameArray.GetSize();i++)

{

pTOneGetMsg->QQNameArray.Add(pOneGetMsg->QQNameArray.GetAt(i));

}

for(i=0;i<pOneGetMsg->NotifyUrlArray.GetSize();i++)

{

pTOneGetMsg->NotifyUrlArray.Add(pOneGetMsg->NotifyUrlArray.GetAt(i));

}

for(i=0;i<pOneGetMsg->AppIDArray.GetSize();i++)

{

pTOneGetMsg->AppIDArray.Add(pOneGetMsg->AppIDArray.GetAt(i));

}

for(i=0;i<pOneGetMsg->AppKeyArray.GetSize();i++)

{

pTOneGetMsg->AppKeyArray.Add(pOneGetMsg->AppKeyArray.GetAt(i));

}

m_GetMessagePtr.AddTail(pTOneGetMsg);

::SetEvent(hGetMessageStartEvent);

::LeaveCriticalSection(&m_GetMessageCS);

}

void RobotEngine::ClearAllGetMsg()

{

::EnterCriticalSection(&m_GetMessageCS);

for(int i=0;i<m_GetMessagePtr.GetCount();i++)

{

OneGetMsg *pOneGetMsg=(OneGetMsg *)m_GetMessagePtr.GetAt(m_GetMessagePtr.FindIndex(i));

delete pOneGetMsg;

}

m_GetMessagePtr.RemoveAll();

::LeaveCriticalSection(&m_GetMessageCS);

}

void RobotEngine::ActionGetMsg()

{

::EnterCriticalSection(&m_GetMessageCS);

for(int i=0;i<m_GetMessagePtr.GetCount();i++)

{

OneGetMsg *pOneGetMsg=(OneGetMsg *)m_GetMessagePtr.GetAt(m_GetMessagePtr.FindIndex(i));

ActionOneGetMsg(pOneGetMsg);

}

::LeaveCriticalSection(&m_GetMessageCS);

Sleep(10000);

}

void RobotEngine::LoadQQGroup()

{

CString TStr,Path;

CString IP,DBName,UserName,PWD;

char tt[200];

GetModuleFileName(NULL,tt,200);

TStr.Format("%s",tt);

int nWei=TStr.ReverseFind('\\');

TStr=TStr.Mid(0,nWei+1);

Path=TStr+"WebRoboti";

char Xiang[40],MainKey[40];

sprintf(Xiang,"group数量");

GetPrivateProfileString("群配置",Xiang,"",tt,200,Path);

TStr.Format("%s",tt);

int n=atoi(TStr);

CString GroupName,GroupQQ;

for(int i=0;i<n;i++)

{

sprintf(MainKey,"group_%d",i);

GetPrivateProfileString(MainKey,"groupname","",tt,200,Path);

GroupName.Format("%s",tt);

GetPrivateProfileString(MainKey,"groupqq","",tt,200,Path);

GroupQQ.Format("%s",tt);

GetPrivateProfileString(MainKey,"kfcnt","",tt,200,Path);

int kfcnt=atoi(tt);

if(GroupName!="" && GroupQQ!="" && kfcnt>0)

{

OneGetMsg m_OneGetMsg;

m_OneGetMsg.GroupMainKey.Format("%s",MainKey);

m_OneGetMsg.GroupName=GroupName;

m_OneGetMsg.GroupQQ=GroupQQ;

GetPrivateProfileString(MainKey,"lastqqname","",tt,200,Path);

m_OneGetMsg.m_oneQQWordLast.QQName.Format("%s",tt);

GetPrivateProfileString(MainKey,"lasttime","",tt,200,Path);

m_OneGetMsg.m_oneQQWordLast.Time.Format("%s",tt);

m_OneGetMsg.m_oneQQWordLast.Word="";

for(int j=0;j<kfcnt;j++)

{

CString QQ,QQName,NotifyUrl,AppID,AppKey;

sprintf(Xiang,"kfqq_%d",j);

GetPrivateProfileString(MainKey,Xiang,"",tt,200,Path);

QQ.Format("%s",tt);

sprintf(Xiang,"kfqqname_%d",j);

GetPrivateProfileString(MainKey,Xiang,"",tt,200,Path);

QQName.Format("%s",tt);

sprintf(Xiang,"kfnotifyurl_%d",j);

GetPrivateProfileString(MainKey,Xiang,"",tt,200,Path);

NotifyUrl.Format("%s",tt);

sprintf(Xiang,"kfappid_%d",j);

GetPrivateProfileString(MainKey,Xiang,"",tt,200,Path);

AppID.Format("%s",tt);

sprintf(Xiang,"kfappkey_%d",j);

GetPrivateProfileString(MainKey,Xiang,"",tt,200,Path);

AppKey.Format("%s",tt);

if(QQ!="" && QQName!="")

{

m_OneGetMsg.QQArray.Add(QQ);

m_OneGetMsg.QQNameArray.Add(QQName);

m_OneGetMsg.NotifyUrlArray.Add(NotifyUrl);

m_OneGetMsg.AppIDArray.Add(AppID);

m_OneGetMsg.AppKeyArray.Add(AppKey);

}

}

AddOneGetMsg(&m_OneGetMsg);

}

}

}

关于该应用使用文件

文件结构

conf下的配置文件appi

[WS服务配置]

端口=6100

节点名=node

HTTPS站点=false

HTTPS证书名=122

[WEB服务配置]

数据存储方式=INI

库类型=MSSQL

连接IP=127.0.0.1

库名=robot

库端口=5432

库用户名=hello

库密码=123

app数量=1

[app_0]

appid=appid

appname=QQ

appkey=appkey

notifyurl=

其中主要配置一般采用数据存储采用INI方式以免安装数据库

接口app的数量也就是调用该接口的app的数量,及接口配置参数在[app]节点

在调用QQ消息发送时候需要

Post的JSON参数

{

"appid":"",

"msg":"消息内容",

"qq":"接收消息QQ号",

"sign":"签名",

"qqnickname":"QQ昵称"

}

sign签名为键排序后键名+键值各键之间用&拼接成串再加上appkey做MD5

PostJson地址为:http://服务地址:端口/qq.ajax

解决远程桌面解决断开后UI交互问题

远程登录服务器后,启动主程序

执行以下命令

query session

查询远程连接编号一般为 #0

然后执行

tscon rdp-tcp#0 /dest:console

给机器人分配一个远程账户,登录进去后执行连接到本地

日常维护的用另一个远程账户

qq幸运字符字母怎么快速点亮教程 每天最多点亮几个字母说明

不少人通过聊天已经抽取到幸运字符了,而现在大家就是想要快点点亮字母了,这样我们的字符表示才会更加明显。而qq幸运字符字母如何快速点亮呢?下文教大家方法。

qq幸运字符字母如何快速点亮

首先通过和好友的互动发消息之后,我们会获得一个幸运字符进行领取的。

领取以后,我们需要进行抽卡的,运气好的话,就可以抽到字符卡了。

抽到字符卡以后,我们就需要点亮字符上面的字母的,上面显示的有互动消息的数量,我们就需要继续和好友进行聊天发消息了。

互动的消息数量每达到100次的话,就可以点亮一个字母,达到200点亮第二个字母。

点亮的字母我们和好友的聊天界面的最上面互动标识可以看到的,是有颜色的,就是点亮的。

幸运字符每天最多点亮几个字母

但是每天不是说一直都可以点亮所有的,上面提示的就有,每天最多2个字母,因此到了2个以后,就需要等待第二天继续点亮了。

来源:腾牛网

更多资讯
游戏推荐
更多+