自從博客園閃存發布了QQ機器人以後閃存數量一下子就上升了很多很多人也一直都在詢問QQ機器人是如何開發的這足以說明QQ在中國不僅僅是普通人使用的IM工具在程序員圈子裡也相當有人緣的其老大地位不容懷疑啊我這篇也算是給解答一些朋友的疑惑吧
所謂的IM機器人(QQMSN)其實就是一個簡化版的IM客戶端(QQMSN)利用這個簡單的客戶端連接到IM服務器接收和發送消息來達到自動回復的目的可惜NET中並沒有開源的QQ機器人的開發包(MSN有DotMSN詳見《使用DotMSN 開發MSN機器人》)博客園使用的是商業組件而對大部分人來說更希望是免費的NET中沒有開源開發包但是JAVA中卻有在Liunx等其它非Windows平台下會有很多的開源QQ其中的LumaQQ也算是比較有名的開源QQ了你可以從它的官方主頁上了解更多的信息在網絡上也已經有人根據LumaQQ的協議使用C#來開發機器人了遺憾的是沒有一個是開源的沒有也罷那我們就直接使用JAVA版本來的LumaQQ來開發自己的機器人吧
其實使用JAVA語法對於我們來說並不是一件難事我想大家主要的麻煩就在於如何去使用JAVA的開發工具引用LumaQQ的包以及編譯調試打包和部署但這些在這裡都不是難事我會提供引用好了點整個的Eclipse解決方案(工作空間)你下載了直接在這個空間下開發編輯源代碼即可下面先來說說簡單的原理
原理部分
這個機器人我們直接開發一個一直運行的機器人即可如果你對JAVA本身並不是很了解的話那麼我建議QQ機器人本身只提供一個QQ客戶端收發信息的作用並不將機器人邏輯寫在這個機器人客戶端裡面把機器人邏輯寫到一個WebService中一方面你可以用你最擅長的語言來開發WebService一方面如果你需要多種平台的機器人(MSN機器人等)這部分的邏輯是可以公用的而不需再次去開發測試這部分
代碼部分
關於LumaQQ接口開發機器人網上已經有很多的代碼了我也是從網上直接拷貝的代碼下來的最關鍵的代碼有以下兩部分
CODE 設置參數登錄代碼
: private void connect()
: {
: try
: {
: client = new QQClient();
: clientaddQQListener(this);
: clientsetConnectionPoolFactory(new PortGateFactory());
: user = new QQUser( qqrobot);
: usersetStatus(QQQQ_LOGIN_MODE_NORMAL);
:
: clientsetUser(user);
: //TCP登錄
: usersetUdp(false);
: clientsetTcpLoginPort();
: clientsetLoginServer();
: //UDP登錄
: //usersetUdp(true);
: //clentsetLoginServer();
:
: //clientsetProxyType(Socks);
: // clientsetProxy(new InetSocketAddress(AF));
:
: clientlogin();
: }
: catch (Exception ex)
: {
: exprintStackTrace();
: //clientrelease();
: }
: }
分代碼裡面提供了兩種方式TCP和UDP來登錄到服務器大家都知道QQ直接這兩種方式的登錄但是需要使用不同的服務器地址
CDOE 事件處理代碼
: public void qqEvent(QQEvent e)
: {
: switch (etype)
: {
: case QQEventQQ_LOGIN_SUCCESS:
: msg(QQ_LOGIN_SUCCESS);
: break;
: case QQEventQQ_LOGIN_FAIL:
: msg(QQ_LOGIN_FAIL);
: msg(reconnect);
: connect();
: // clientrelease();
: //Systemexit();
: break;
: case QQEventQQ_LOGIN_UNKNOWN_ERROR:
: msg(QQ_LOGIN_UNKNOWN_ERROR);
: msg(reconnect);
: connect();
: // clientrelease();
: //Systemexit();
: break;
: case QQEventQQ_LOGIN_REDIRECT_NULL:
: msg(QQ_LOGIN_REDIRECT_NULL);
: msg(reconnect);
: connect();
: // clientrelease();
: //Systemexit();
: break;
: case QQEventQQ_CONNECTION_LOST:
: msg(QQ_CONNECTION_LOST);
: msg(reconnect);
: connect();
: // clientrelease();
: //Systemexit();
: break;
: case QQEventQQ_NETWORK_ERROR:
: msg(QQ_NETWORK_ERROR);
: msg(reconnect);
: connect();
: // clientrelease();
: //Systemexit();
: break;
: case QQEventQQ_CONNECTION_BROKEN:
: msg(QQ_CONNECTION_BROKEN);
: msg(reconnect);
: connect();
: // clientrelease();
: //Systemexit();
: break;
: case QQEventQQ_RECEIVE_TEMP_SESSION_IM:
: SimpleDateFormat tempDate = new SimpleDateFormat(MMdd HH:mm);
: impacket = (ReceiveIMPacket) egetSource();
: qqnum = impackettempSessionIMsender;
: immsg = new String(impackssage);
: msg([
: + tempDateformat(new Date(impackettempSessionIMtime))
: + ] + qqnum + : + immsg);
: addFriend(qqnum);
: msg(臨時回復);
: clientsendIM(qqnum UtilgetBytes(對不起: + impackettempSessionIMnick + GK助手暫時還不支持臨時會話請先將我加為好友然後在正常聊天窗體與我聊天這樣我才能幫助你:)));
: break;
: case QQEventQQ_RECEIVE_NORMAL_IM:// 收到正常消息;?
: SimpleDateFormat sdf = new SimpleDateFormat(MMdd HH:mm);
: impacket = (ReceiveIMPacket) egetSource();
: qqnum = impacketnormalHeadersender;
: immsg = new String(issageBytes);
: msg([
: + sdfformat(new Date(impacketnormalHeadersendTime))
: + ] + qqnum + : + immsg);
: if (impacketnormalIMreplyType != QQQQ_IM_AUTO_REPLY)
: {
: msg(好友: + qqnum +請求信息: + immsg );
: clientsendIM(qqnum UtilgetBytes(immsg));
: }
: //if (immsgtrim()equalsIgnoreCase(exit))
: // {
: // Systemoutprintln(qqnum + 命令你;退出);
: // clientlogout();
: // clientrelease();
: // Systemexit();
: // }
: break;
: case QQEventQQ_ADDED_BY_OTHERS:// 事件發生在有人將我加為好友時
: case QQEventQQ_ADDED_BY_OTHERS_EX:// 事件發生在有人將我加為好友時
: msg(QQ_ADDED_BY_OTHERS_EX);
: snpacket = (SystemNotificationPacket) egetSource();
: qqnum = snpacketfrom;
: msg(qqnum + 把我加為了好友;?);
: clientsendIM(qqnum UtilgetBytes(hello));
: break;
: case QQEventQQ_REQUEST_ADD_ME:// 事件發生在有人請求加我為好友;?
: case QQEventQQ_REQUEST_ADD_ME_EX:// 事件發生在有人請求加我為好友;?
: msg(QQ_REQUEST_ADD_ME_EX);
: snpacket = (SystemNotificationPacket) egetSource();
: qqnum = snpacketfrom;
: msg(qqnum + 想加我為好友;);//
: clientapproveAddMe(qqnum);
: addFriend(qqnum);
: break;
: case QQEventQQ_ADD_FRIEND_NEED_AUTH:
: AddFriendExReplyPacket packet = (AddFriendExReplyPacket)egetSource();
: qqnum = packetfriendQQ;
: sendAddFriendAuth(qqnum);
: break;
: case QQEventQQ_REQUEST_ADD_OTHER_APPROVED:// 事件發生在有人請求加我為好友時我同意並且加他為好友
: msg(QQ_REQUEST_ADD_OTHER_APPROVED);
: break;
: case QQEventQQ_REQUEST_ADD_OTHER_APPROVED_AND_ADD:// 事件發生在有人請求加我為好友時我同意並且加他為好友
: msg(QQ_REQUEST_ADD_OTHER_APPROVED_AND_ADD);
: break;
: case QQEventQQ_REQUEST_ADD_OTHER_REJECTED:// 事件發生在我請求加一個人那個人拒絕;?
: snpacket = (SystemNotificationPacket) egetSource();
: msg(snpacketfrom
: + 拒絕加我為好友;?理由為
: + ((ssage == null || ssage
: equals()) ? ;? : ssage));
: break;
: case QQEventQQ_KICKED_OUT_BY_SYSTEM:
: msg(QQ在別處登錄了重新登錄);
: connect();
: break;
: default :
: msg(etype);
: break;
: }
: }
大家看到了LumaQQ裡面的事件處理看起來似乎比較原始了一點但是沒關系它是確實可用的LumaQQ裡面支持的QQ事件協議都在QQEvent中已經有定義了同時不同的事件它的事件參數egetSource()都是不同類型的對象比如接收到正常消息它的事件枚舉是QQEventQQ_RECEIVE_NORMAL_IMegetSource()的類型是ReceiveIMPacket你把這個對象轉換成ReceiveIMPacket類型後就可以得知是誰發送的什麼樣的消息了這時候你就可以調用clientsendIM方法來回復消息了至於回復什麼就是你的機器人要做的事件了它裡可以調用WebService也可以把業務邏輯直接寫在這邊
還有就是斷點重連LumaQQ已經可以保證長時間在線了但是我們也要有斷線重連的功能這個在例子中也已經有了還有其它的事件和接口我就不詳細介紹了因為我個人對JAVA的了解也不夠多下面再來介紹一下Eclipse的打包吧這也是一個比較麻煩的地方沒有同事的幫忙我也是一時半會兒也搞不定
編譯打包部分
同事給我的是裝有ObjectWeb Lomboz插件的eclipse我還必須要說明一下我的eclipse目錄是在D\Program Files\ecplise 因為它有可能影響到一些包的引用和編譯它的啟動界面是這樣的
圖一
大家下載完附件的示例代碼後在文件菜單下點擊Switch Workspace選擇解壓後的目錄就可以打開解決方案了(工作空間)裡面會有三個工程LumaQQ是QQ協議工程 是LumaQQ負責網絡連接部分的工程代碼robot是QQ機器人工程如果你要在eclipse裡面運行或調試機器人點擊QQRobotjava右鍵在菜單中選擇RunAs或DebugAs Java Applcation就可以運行或調試了
圖二
更多的調試技巧我就不多介紹了下面來介紹打包吧eclipse要打包成控制台程序那也不是一件容易的事情要先將這個解決方案導出成jar包File Export 選擇Java目錄下的JAR File
圖三
把三個工程都選擇起來選擇包存放的路徑和包的文件名
圖四
一路Next或者直接Finish可能是彈出警告提示看不懂也不用管它轉到你剛才包的保存路徑正常情況下你可以看到你剛才保存的文件名jar這麼一個文件接下來的工作就是把這個jar打包成exe控制台程序了這還得借助於另一個工具的幫忙我使用的是exej你從網絡上去下載就可以了不過它是共享軟件非注冊版本打包的exe在運行前會彈出一個提示告訴你是這個exe是用什麼打包的宣傳一下有點討厭
打包exe需要創建exej的工程文件還有一個麻煩的就是要指定它所引用的所有第三方包的路徑而且設置輸出路徑版本運行環境等等這麼信息為了方便起見我也把這個文件放在附件的示例中了安裝了exej後就可以打開這個文件了打開了點擊Finish就在編譯了
圖五exej工程文件
圖六引用的第三方包
圖七編譯中
經過這一系列的步驟後你所得到的exe文件就是一個可用的控制台程序了這時候除了JRE外不需要其它的插件的支持了
寫在最後
做為一個NET平台的開發人員以上的步驟對我們來說確實是太過於煩雜了在寒冬季節我寫這樣的一篇文章都快要滿頭大汗了我相信各位看官如果能堅持看到這裡那麼你一定是非常有耐力了但是沒有辦法我們需要忍受如果有時間有精力我還是很願意以LumaQQ為樣本開發一個開源的QQ開發包這樣大家就不用再這麼麻煩了
From:http://tw.wingwit.com/Article/program/net/201311/12851.html