lynnlin linID:lynnlin1122
46223次访问,排名2341(-1)好友4人,关注者13
lynnlin1122的文章
原创 117 篇
翻译 2 篇
转载 38 篇
评论 56 篇
lynnlin1122的公告
最近评论
kyovs:很好,很强大,小弟受用了
$:不错,对我 帮助很大
jinjinbaobei1981:谢谢分享!
gavin_luo:这个东西有权威性没?我好像很多都不会,天呐
zzq:写的真的很好,浅显易懂。谢谢
文章分类
收藏
    相册
    连接
    C# 判断TextBox框输入字符串是否是Int32数字的方法
    c#窗体间传递复杂数据
    Csdn DotNet频道
    Csdn软件测试频道
    Visual C#中实现窗体间的数据传递
    windows/.net
    WinForm Control - DataGridView 编程36计
    为您的软件系统设计选择最佳的工具
    技术出身,如何做好项目经理
    水晶报表
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    转载 使用LumaQQ来开发QQ机器人收藏

    新一篇: 掌握ADO.NET的十个热门技巧 | 旧一篇: 运用设计模式构建通用数据库访问类

      自从博客园闪存发布了QQ机器人以后,闪存数量一下子就上升了很多。很多人也一直都在询问QQ机器人是如何开发的,这足以说明QQ在中国不仅仅是普通人使用的IM工具,在程序员圈子里也相当有人缘的,其老大地位不容怀疑啊。我这篇也算是给解答一些朋友的疑惑吧。
     
      所谓的IM机器人(QQ,MSN),其实就是一个简化版的IM客户端(QQ,MSN)。利用这个简单的客户端连接到IM服务器, 接收和发送消息来达到自动回复的目的。可惜,。NET中并没有开源的QQ机器人的开发包(MSN,有DotMSN,详见《使用DotMSN 2.0开发MSN机器人》)。博客园使用的是商业组件,而对大部分人来说更希望是免费的。。NET中没有开源开发包,但是JAVA中却有。在Liunx等 其它非Windows平台下,会有很多的开源QQ,其中的LumaQQ也算是比较有名的开源QQ了,你可以从它的官方主页上了解更多的信息。在网络上也已经有人根据LumaQQ的协议,使用C#来开发机器人了。遗憾的是,没有一个是开源的。没有也罢,那我们就直接使用JAVA版本来的LumaQQ来开发自己的机器人吧。
     
      其实使用JAVA语法,对于我们来说并不是一件难事。我想大家主要的麻烦就在于如何去使用JAVA的开发工具,引用LumaQQ的包,以及编译,调试,打包和部署。但这些在这里都不是难事,我会提供引用好了点整个的Eclipse解决方案(工作空间)。你下载了,直接在这个空间下开发编辑源代码即可。下面先来说说简单的原理。
     

    原理部分

      这个机器人,我们直接开发一个一直运行的机器人即可。如果你对JAVA本身并不是很了解的话,那么我建议QQ机器人本身只提供一个QQ客户端收 发信息的作用,并不将机器人逻辑写在这个机器人客户端里面,把机器人逻辑写到一个WebService中。一方面你可以用你最擅长的语言来开发 WebService;一方面,如果你需要多种平台的机器人(MSN机器人等)这部分的逻辑是可以公用的,而不需再次去开发测试这部分。
     

    代码部分

      关于LumaQQ接口开发机器人,网上已经有很多的代码了,我也是从网上直接拷贝的代码下来的。最关键的代码有以下两部分:
     

    CODE 1:设置参数,登录代码

       1: private void connect()    2: {    3:      try    4:      {      5:          client = new QQClient();    6:          client.addQQListener(this);    7:          client.setConnectionPoolFactory(new PortGateFactory());    8:          user = new QQUser(739330764, "qqrobot");    9:          user.setStatus(QQ.QQ_LOGIN_MODE_NORMAL);                10:             11:          client.setUser(user);   12:          //TCP登录   13:          user.setUdp(false);   14:          client.setTcpLoginPort(8000);   15:          client.setLoginServer("219.133.48.103");   16:          //UDP登录   17:          //user.setUdp(true);   18:          //clent.setLoginServer("sz.tencent.com");   19:             20:          //client.setProxyType("Socks5");   21:          // client.setProxy(new InetSocketAddress("AF25",1080));   22:             23:          client.login();   24:      }   25:      catch (Exception ex)   26:      {   27:          ex.printStackTrace();   28:          //client.release();   29:      }   30: }
    分代码里面提供了两种方式:TCP和UDP来登录到服务器。大家都知道QQ直接这两种方式的登录,但是需要使用不同的服务器地址。

    CDOE 2:事件处理代码

       1: public void qqEvent(QQEvent e)
    2: {
    3: switch (e.type)
    4: {
    5: case QQEvent.QQ_LOGIN_SUCCESS:
    6: msg("QQ_LOGIN_SUCCESS");
    7: break;
    8: case QQEvent.QQ_LOGIN_FAIL:
    9: msg("QQ_LOGIN_FAIL");
    10: msg("reconnect");
    11: connect();
    12: // client.release();
    13: //System.exit(0);
    14: break;
    15: case QQEvent.QQ_LOGIN_UNKNOWN_ERROR:
    16: msg("QQ_LOGIN_UNKNOWN_ERROR");
    17: msg("reconnect");
    18: connect();
    19: // client.release();
    20: //System.exit(0);
    21: break;
    22: case QQEvent.QQ_LOGIN_REDIRECT_NULL:
    23: msg("QQ_LOGIN_REDIRECT_NULL");
    24: msg("reconnect");
    25: connect();
    26: // client.release();
    27: //System.exit(0);
    28: break;
    29: case QQEvent.QQ_CONNECTION_LOST:
    30: msg("QQ_CONNECTION_LOST");
    31: msg("reconnect");
    32: connect();
    33: // client.release();
    34: //System.exit(0);
    35: break;
    36: case QQEvent.QQ_NETWORK_ERROR:
    37: msg("QQ_NETWORK_ERROR");
    38: msg("reconnect");
    39: connect();
    40: // client.release();
    41: //System.exit(0);
    42: break;
    43: case QQEvent.QQ_CONNECTION_BROKEN:
    44: msg("QQ_CONNECTION_BROKEN");
    45: msg("reconnect");
    46: connect();
    47: // client.release();
    48: //System.exit(0);
    49: break;
    50: case QQEvent.QQ_RECEIVE_TEMP_SESSION_IM:
    51: SimpleDateFormat tempDate = new SimpleDateFormat("MM-dd HH:mm");
    52: impacket = (ReceiveIMPacket) e.getSource();
    53: qqnum = impacket.tempSessionIM.sender;
    54: immsg = new String(impacket.tempSessionIM.message);
    55: msg("["
    56: + tempDate.format(new Date(impacket.tempSessionIM.time))
    57: + "] " + qqnum + ":" + immsg);
    58: addFriend(qqnum);
    59: msg("临时回复");
    60: client.sendIM(qqnum, Util.getBytes("对不起:" + impacket.tempSessionIM.nick + ",GK助手暂时还不支持临时会话,请先将我加为好友,然后在正常聊天窗体与我聊天,这样我才能帮助你。:)"));
    61: break;
    62: case QQEvent.QQ_RECEIVE_NORMAL_IM:// 收到正常消息�?
    63: SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");
    64: impacket = (ReceiveIMPacket) e.getSource();
    65: qqnum = impacket.normalHeader.sender;
    66: immsg = new String(impacket.normalIM.messageBytes);
    67: msg("["
    68: + sdf.format(new Date(impacket.normalHeader.sendTime))
    69: + "] " + qqnum + ":" + immsg);
    70: if (impacket.normalIM.replyType != QQ.QQ_IM_AUTO_REPLY)
    71: {
    72: msg("好友:" + qqnum +"请求信息:" + immsg );
    73: client.sendIM(qqnum, Util.getBytes(immsg));
    74: }
    75: //if (immsg.trim().equalsIgnoreCase("exit"))
    76: // {
    77: // System.out.println(qqnum + "命令你�退出");
    78: // client.logout();
    79: // client.release();
    80: // System.exit(0);
    81: // }
    82: break;
    83: case QQEvent.QQ_ADDED_BY_OTHERS:// 事件发生在有人将我加为好友时
    84: case QQEvent.QQ_ADDED_BY_OTHERS_EX:// 事件发生在有人将我加为好友时
    85: msg("QQ_ADDED_BY_OTHERS_EX");
    86: snpacket = (SystemNotificationPacket) e.getSource();
    87: qqnum = snpacket.from;
    88: msg(qqnum + "把我加为了好友�?");
    89: client.sendIM(qqnum, Util.getBytes("hello."));
    90: break;
    91: case QQEvent.QQ_REQUEST_ADD_ME:// 事件发生在有人请求加我为好友�?
    92: case QQEvent.QQ_REQUEST_ADD_ME_EX:// 事件发生在有人请求加我为好友�?
    93: msg("QQ_REQUEST_ADD_ME_EX");
    94: snpacket = (SystemNotificationPacket) e.getSource();
    95: qqnum = snpacket.from;
    96: msg(qqnum + "想加我为好友�");// 1675103
    97: client.approveAddMe(qqnum);
    98: addFriend(qqnum);
    99: break;
    100: case QQEvent.QQ_ADD_FRIEND_NEED_AUTH:
    101: AddFriendExReplyPacket packet = (AddFriendExReplyPacket)e.getSource();
    102: qqnum = packet.friendQQ;
    103: sendAddFriendAuth(qqnum);
    104: break;
    105: case QQEvent.QQ_REQUEST_ADD_OTHER_APPROVED:// 事件发生在有人请求加我为好友时,我同意并且加他为好友
    106: msg("QQ_REQUEST_ADD_OTHER_APPROVED");
    107: break;
    108: case QQEvent.QQ_REQUEST_ADD_OTHER_APPROVED_AND_ADD:// 事件发生在有人请求加我为好友时,我同意并且加他为好友
    109: msg("QQ_REQUEST_ADD_OTHER_APPROVED_AND_ADD");
    110: break;
    111: case QQEvent.QQ_REQUEST_ADD_OTHER_REJECTED:// 事件发生在我请求加一个人,那个人拒绝�?
    112: snpacket = (SystemNotificationPacket) e.getSource();
    113: msg(snpacket.from
    114: + "拒绝加我为好友�?理由为:"
    115: + ((snpacket.message == null || snpacket.message
    116: .equals("")) ? "�?" : snpacket.message));
    117: break;
    118: case QQEvent.QQ_KICKED_OUT_BY_SYSTEM:
    119: msg("QQ在别处登录了,重新登录.");
    120: connect();
    121: break;
    122: default :
    123: msg(e.type);
    124: break;
    125: }
    126: }
    大家看到了LumaQQ里面的事件处理看起来似乎比较原始了一点。但是没关系,它是确实可用的。LumaQQ里面支持的QQ事件协议都 在QQEvent中已经有定义了,同时不同的事件,它的事件参数e.getSource()都是不同类型的对象。比如接收到正常消息,它的事件枚举是 QQEvent.QQ_RECEIVE_NORMAL_IM,e.getSource()的类型是ReceiveIMPacket.你把这个对象转换成 ReceiveIMPacket类型后,就可以得知是谁发送的什么样的消息了。这时候你就可以调用client.sendIM方法来回复消息了。至于回复 什么,就是你的机器人要做的事件了,它里可以调用WebService,也可以把业务逻辑直接写在这边。

      还有就是断点重连,LumaQQ已经可以保证长时间在线了。但是我们也要有断线重连的功能,这个在例子中也已经有了。还有其它的事件和接口我就 不详细介绍了,因为我个人对JAVA的了解也不够多。下面再来介绍一下Eclipse的打包吧,这也是一个比较麻烦的地方,没有同事的帮忙我也是一时半会 儿也搞不定。 

    编译,打包部分

      同事给我的是装有ObjectWeb Lomboz插件的eclipse,我还必须要说明一下,我的eclipse目录是在:D:\Program Files\ecplise ,因为它有可能影响到一些包的引用和编译。它的启动界面是这样的:
     

    图一:

    pic1

      大家下载完附件的示例代码后,在文件菜单下点击"Switch Workspace"选择解压后的目录。就可以打开解决方案了(工作空间),里面会有三个工程:LumaQQ是QQ协议工程,LumaQQ.net 是LumaQQ负责网络连接部分的工程代码,robot是QQ机器人工程。如果你要在eclipse里面运行或调试机器人,点击QQRobot.java右键在菜单中选择RunAs或DebugAs Java Applcation就可以运行或调试了:

    图二:

    pic2

      更多的调试技巧我就不多介绍了。下面来介绍打包吧。eclipse要打包成控制台程序那也不是一件容易的事情。要先将这个解决方案导出成jar包:File ---  Export 选择Java目录下的JAR File:

    图三:

    pic3

    把三个工程都选择起来,选择包存放的路径和包的文件名:

    图四:

    pic4

      一路Next或者直接Finish,可能是弹出警告提示,看不懂也不用管它。转到你刚才包的保存路径,正常情况下,你可以看到你刚才保存的文件 名.jar这么一个文件。接下来的工作就是把这个jar打包成exe控制台程序了。这还得借助于另一个工具的帮忙,我使用的是exe4j,你从网络上去下载就可以了。不过它是共享软件,非注册版本打包的exe在运行前会弹出一个提示,告诉你是这个exe是用什么打包的。宣传一下,有点讨厌。

      打包exe,需要创建exe4j的工程文件。还有一个麻烦的就是要指定它所引用的所有第三方包的路径,而且设置输出路径,版本,运行环境等等这 么信息。为了方便起见,我也把这个文件放在附件的示例中了。安装了exe4j后就可以打开这个文件了,打开了点击Finish就在编译了。

    图五:exe4j工程文件

     

    pic5

    图六:引用的第三方包

    pic6

    图七:编译中

    pic7

      经过这一系列的步骤后,你所得到的exe文件,就是一个可用的控制台程序了。这时候除了JRE外,不需要其它的插件的支持了。

    写在最后

      做为一个.NET平台的开发人员,以上的步骤对我们来说确实是太过于烦杂了。在寒冬季节我写这样的一篇文章都快要满头大汗了,我相信各位看官如 果能坚持看到这里那么你一定是非常有耐力了。但是没有办法,我们需要忍受。如果有时间,有精力,我还是很愿意以LumaQQ为样本,开发一个开源的QQ开 发包,这样大家就不用再这么麻烦了。

    发表于 @ 2008年06月02日 20:03:21|评论(loading...)|编辑

    新一篇: 掌握ADO.NET的十个热门技巧 | 旧一篇: 运用设计模式构建通用数据库访问类

    评论

    #skyarrate 发表于2008-07-14 11:46:55  IP: 218.94.62.*
    很好,赞一个
    #yunfeng007 发表于2008-08-30 14:26:26  IP: 61.29.197.*
    cnblogs上的阿不有.net上的lumaqq开源qq开发包
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © lynnlin1122