自定义QQ机器人,实现关键字回复


使用第三方接口,可以很轻松的实现QQ机器人的自定义:打开源代码->找到相应接口(私聊或群聊或其他)->自定义自己的内容->编译生成*.dll动态库->放入下载好的酷Q相应文件夹->登陆酷Q(最好用小号)。

这里主要强调有两个方面:

1、如何实现自定义的对人友好化:即不需要编程知识也可以自定义实现。可以把关键字、回复内容放入一个配置文档内,这样只需修该配置文档即可。我使用的是xml。在源代码添加一个xmlLoader类即可解决问题

2、如何提高机器人处理消息的性能:给程序添加一个专门处理消息的线程。其中自己在使用互斥锁时不够熟练,应记得及时解锁,否则会出现函数堵塞。

具体代码如下:

 1 #pragma once
 2 #include "qqSupport.h"
 3 #include <list>
 4 #include "tinyxml/tinyxml.h"
 5 
 6 using namespace std;
 7 
 8 class xmlLoader
 9 {
10 public:
11     string getXmlPath()
12     {
13         string xP = getPath();
14         string xmlPath = xP + "config.xml";
15 
16         return xmlPath;
17     }
18 
19 
20     int loadXml(string xmlPath)
21     {
22         //加载xml文件
23         TiXmlDocument* doc = new TiXmlDocument();
24         if (doc == NULL)
25         {
26             return -1;
27         }
28         doc->LoadFile(xmlPath);
29 
30         TiXmlElement* xmlRoot = doc->RootElement();
31         TiXmlElement* xmlChildDef = xmlRoot->FirstChildElement("default");
32         defaultAnswer = xmlChildDef->GetText();
33 
34 
35         TiXmlElement* xmlChild = xmlRoot->FirstChildElement("match");
36         while (xmlChild)
37         {
38             TiXmlElement* xmlKW = xmlChild->FirstChildElement("keyword");
39             TiXmlElement* xmlAS = xmlChild->FirstChildElement("answer");
40             msgContent mC;
41             mC.keyword = xmlKW->GetText();
42             mC.answer = xmlAS->GetText();
43 
44             m_msgContentList.push_back(mC);
45             //addLog(mC.keyword.c_str());
46             //addLog(mC.anwser.c_str());
47 
48             xmlChild = xmlChild->NextSiblingElement("match");
49         }
50 
51         return 0;
52     }
53 
54     string findAnswer(int type,string msg)
55     {
56         //根据关键字找答案
57         for (list<msgContent>::iterator iter = m_msgContentList.begin();
58             iter != m_msgContentList.end(); iter++)
59         {
60             
61             msgContent& mC = *iter;
62             addLog(mC.keyword.c_str());
63             addLog(msg.c_str());
64             addLog(mC.answer.c_str());
65             if ((int)msg.find(mC.keyword)>0)
66             {
67                 //addLog("有答案");
68                 return mC.answer;
69             }
70         }
71 
72         return defaultAnswer;
73     }
74 
75 private:
76     struct msgContent //xml内容
77     {
78         string keyword;
79         string answer;
80     };
81     list<msgContent> m_msgContentList; //保存到列表
82     string defaultAnswer;
83 };
xmlLoader.h
 1 #pragma once
 2 #include "afos/AfMutex.h"
 3 #include "afos/AfThread.h"
 4 #include "xmlLoader.h"
 5 #include <list>
 6 
 7 using namespace std;
 8 
 9 class syncTask:public AfThread
10 {
11 public:
12     int startService();
13     void stopService();
14     int addMsg(int type, int64_t from, const char *msg);
15 private:
16     int ThreadMain();
17 private:
18     struct recvMsg   //收到的信息
19     {
20         int type;
21         int64_t from;
22         string msg;
23     };
24 
25 private:
26 
27     list<recvMsg> m_recvMsgList;   //保存信息到列表
28     AfMutex m_mutex;  //互斥锁
29     bool m_quitFlag;
30     xmlLoader m_loader;  //加载xml类
31 };
32 
33 
34 void myIniti();
35 
36 void myEexit();
37 
38 void msgToThread(int type,int64_t from,const char *msg);
myplugin.h
 1 #include "myplugin.h"
 2 #include "xmlLoader.h"
 3 #include "qqSupport.h"
 4 
 5 
 6 syncTask m_serviceTask;
 7 
 8 int syncTask::startService()
 9 {
10     std::string xp = m_loader.getXmlPath();
11     if (m_loader.loadXml(xp)<0)
12     {
13         return -1;
14         //addLog("不能加载xml");
15     }
16     m_quitFlag = false;
17 
18     //进入线程
19     this->Run();
20 
21     return 0;
22 }
23 
24 
25 void syncTask::stopService()
26 {
27     m_quitFlag = true;
28     Join(this);
29 }
30 
31 
32 int syncTask::ThreadMain()
33 {
34     //addLog("进入线程");
35     while (!m_quitFlag)
36     {
37         AfThread::Msleep(50);
38 
39         bool flag=false;
40         recvMsg rM;
41         m_mutex.Lock();//加锁
42         if (m_recvMsgList.size()>0)
43         {
44             flag = true;
45             rM = m_recvMsgList.front();
46             addLog(rM.msg.c_str());
47             m_recvMsgList.pop_front();
48             //addLog("有消息进入");
49         }
50         m_mutex.Unlock();
51         if (!flag)
52         {
53             continue;
54         }
55         std::string answer = m_loader.findAnswer(rM.type, rM.msg);
56         sendMsg(rM.type, rM.from, answer.c_str());
57     }
58     return 0;
59 }
60 
61 
62 int syncTask::addMsg(int type, int64_t from, const char * msg)
63 {
64     recvMsg rM;
65     rM.type = type;
66     rM.from = from;
67     rM.msg = msg;
68 
69     m_mutex.Lock();//加锁
70     if (m_recvMsgList.size()<100)
71     {
72         m_recvMsgList.push_back(rM);
73     }
74     m_mutex.Unlock();
75     
76     return 0;
77 }
78 
79 
80 
81 void myIniti()
82 {
83     m_serviceTask.startService();
84 }
85 
86 void myEexit()
87 {
88     m_serviceTask.stopService();
89 }
90 
91 void msgToThread(int type, int64_t from, const char *msg)
92 {
93     m_serviceTask.addMsg(type, from, msg);
94 }
myplugin.cpp
1 #pragma once
2 #include "stdafx.h"
3 #include <string>
4 #include "cqp.h"
5 #include "appmain.h"
6 
7 void sendMsg(int type, int64_t from, std::string msg);
8 void addLog(const char* msg);
9 std::string getPath();
qqSupport.h

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM