⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 messagehelper.java

📁 java写的qq代码实现qq的部分功能
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
				    return;		            
		        } else {
		            GroupModel g = (GroupModel)model.getTab(indices[0]);
		            if(!g.isFriendly()) {
		                log.debug("设置了拒绝陌生人消息,忽略该消息");
		                return;
		            }
		        }
		    } else {
				// 在陌生人组中为它分配一个序号
		        if(indices == null || indices.length == 0)
		            indices = mvcHelper.getStrangerIndex(packet.normalHeader.sender);
		    }
		} else {
            GroupModel g = (GroupModel)model.getTab(indices[0]);
            if(g.isBlackList()) {
                model.removeItem(indices[0], indices[1]);
                indices = mvcHelper.getStrangerIndex(packet.normalHeader.sender);
            }
		}
		
	    Shutter shutter = main.getShutter();
	    ShellRegistry shellRegistry = main.getShellRegistry();
	    MessageQueue mq = main.getMessageQueue();
	    UIHelper uiHelper = main.getUIHelper();
	    ReplyUtil replies = ReplyUtil.getInstance();
	    QQClient client = main.getClient();
	    
		Integer qqNum = new Integer(packet.normalHeader.sender);
		
		// 得到好友的view control,也就是ShutterLabel,以及从control的data属性得到model
		CoolButton viewPart = shutter.getItemControl(indices[0], indices[1]);
		CoolButton tab = shutter.getTabControl(indices[0]);
		FriendModel f = (FriendModel)model.getItem(indices[0], indices[1]);
		// 如果最近联系人功能是打开的,添加到最近联系人中
		if(options.isEnableLatest() && (!isStranger || (isStranger && options.isKeepStrangerInLatest()))) {
		    // 得到最近联系人组,如果没有最近联系人这个组,则新建一个
		    int[] i = mvcHelper.listLatestGroup();
		    if(i == null || i.length == 0) {		        
		        main.getMVCHelper().createLatestGroup();
		        i = new int[] { model.getTabCount() - 1 };
		    } 
		    // 得到最近联系人设定最大数量
		    int max = options.getLatestSize();
		    // 得到当前联系人数量
		    int num = model.getItemCount(i[0]);
		    // 删除多余的联系人
		    if(max > 0) {
			    while(num >= max)
			        model.removeItem(i[0], --num);
			    // 如果没有这个人,添加
			    int[] temp = mvcHelper.listFriend(i[0], f.getQQ(), false);
			    if(temp == null || temp.length == 0) {
			        FriendModel cf = f.cloneProperties();
			        cf.addProperty(IQQNode.ORIGINAL, "false");
			        model.addItem(i[0], cf);		        
			    }
		    }
		}
		// 在这里要检查好友的发送消息状态,如果在这个时候,好友的发送消息窗口是打开的
		//     并且与好友处于聊天模式中,那么就直接把这个消息推到这个窗口,而不需要再
		//     闪烁图标了
		if(shellRegistry.hasSendIMWindow(f) && f.isTalkMode()) {
			// 得到发送消息窗口实例
		    SendIMWindow sms = shellRegistry.getSendIMWindow(f);
			// 在把这条消息推入窗口之前,我们还需要检查是否之前还有这个好友的消息,这种情况是
			// 可能的,发生在用户开始处于消息模式,后来处于聊天模式,而这之间有消息未读时
			while(mq.hasMessage(qqNum)) {
				ReceiveIMPacket p = (ReceiveIMPacket)mq.getMessage(qqNum);
				sms.appendMessage(f, p.normalIM, p.normalHeader);
			}
			// 现在轮到把这条消息推入窗口中了
			sms.appendMessage(f, packet.normalIM, packet.normalHeader);
			// 停止跳动和闪烁头像
			viewPart.stopBounceImage();
			uiHelper.resetGroupImageEffect(indices[0]);
			uiHelper.resetTrayImageEffect();
			// 如果聊天窗口当前不是active的,闪烁图标并播放声音提示用户有消息到来
			if(!sms.isActive()) {
			    sms.startBlinkImage();
				main.getSoundDaemon().play(LumaQQ.MSG_SOUND);			    
			}
			return;
		}
		// 修改好友的是否有消息属性,这个属性主要用于排序,也就是如果一个好友是隐身的
		// 那么一般他在排在下面,需要翻页才能看到,很不方便,所以通过设置这个属性,
		// 能够让好友有消息来时排到列表的最前面,方便用户选择查看消息
		if(f.isOffline()) {
		    // 如果好友当前是离线状态,临时设置他的状态为在线
		    main.setFriendProperty(f, IQQNode.STATUS, IQQNode.VALUE_ONLINE);
			// 把好友加入到当前在线名单
			main.getCurrentOnlines().add(f);		    
		}
		main.setFriendProperty(f, IQQNode.HAS_MESSAGE, "true");
		// 从model得到好友的头像
		Image face = HeadFactory.getOnlineHead(f);
		// 检查这是否是第一个消息,如果是,则需要闪烁tray icon,同时还要
		//     在tab上闪烁图标,还要在friend上跳动一个图标,如果不是,则
		//     不需要闪动tray icon,但是其他两个还是要的。如果当前好友已经
		//     有其他消息还没有读,则声音提示就免掉
		if(!mq.hasNext())
		    uiHelper.startBlinkImage(HeadFactory.getOnlineSmallHead(f));
		if(!tab.isBlinking())
			tab.startBlinkImage(face);
		if(!viewPart.isBouncing()) {		    
			viewPart.startBounceImage(face);
			main.getSoundDaemon().play(LumaQQ.MSG_SOUND);
		}
		
		// 推入队列
		mq.putMessage(packet, tab);
		log.debug("新的普通消息被推入队列");
		// 检查是否这个好友的消息窗口已经被打开,如果是,使下一条按钮使能
		if(shellRegistry.hasReceiveIMWindow(f)) {
			ReceiveIMWindow rms = shellRegistry.getReceiveIMWindow(f);
			rms.setNextButtonEnabled(true);
		}
		// 检查当前是否在离开状态,并且是否设置了自动回复,如果是,自动回复消息
		if(client.getUser().getStatus() == QQ.QQ_FRIEND_STATUS_AWAY 
				&& packet.normalIM.replyType != QQ.QQ_IM_AUTO_REPLY
				&& replies.isAutoReply()) {
			client.sendIM(packet.normalHeader.sender, replies.getCurrentAutoReplyString(), QQ.QQ_IM_AUTO_REPLY);
			log.debug("自动回复消息已发送");			
		}
		// 检查是否设置了自动弹出消息且当前没有打开的查看消息窗口,则自动弹出
		//     如果没有设置自动弹出,且目前主窗口处于最小化状态,显示消息提示
		if(!shellRegistry.hasReceiveIMWindow(f)) {
		    if(options.isAutoEject())
		        main.getShellLauncher().openNormalIMWindow(viewPart);
		}
	}
	
	/**
	 * 推入一条群消息并更新各种图标的闪烁状态,如果好友列表还没有全部得到,
	 * 则推入延迟队列
	 * 
	 * @param packet
	 * 		消息包对象
	 * @param resolved
	 * 		true表示其中的自定义表情都已经得到
	 */
	public void putClusterIM(ReceiveIMPacket packet) {
	    MessageQueue mq = main.getMessageQueue();
	    ShellRegistry shellRegistry = main.getShellRegistry();
	    SoundDaemon soundDaemon = main.getSoundDaemon();
	    
		// 检查好友列表是否完全得到
		if(main.isFriendListFinished()) {
			// 得到群的内部ID
			int clusterId = packet.header.sender;
			if(packet.header.type == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM)
			    clusterId = packet.clusterIM.clusterId;
			// 得到群的model。如果没有,则新建一个
			ClusterModel c = null;
			if(packet.header.type == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM)
			    c = main.getMVCHelper().addTempCluster(packet.clusterIM.type, clusterId, packet.clusterIM.externalId);
			else
			    c = main.getMVCHelper().addCluster(clusterId, false);
			if(c == null) return;
			
			// 如果群消息发送者是我自己,则不处理这条消息
			if(main.getMyModel().getQQ() == packet.clusterIM.sender) return;
			
			// 得到消息设定,如果设置了阻止群消息,返回
			String messageOption = c.getMessageOption();
		    if(IQQNode.VALUE_BLOCK == messageOption)
		        return;
		        
		    // 如果这个消息是分片消息,如果这个消息已经完成,则继续处理,否则推入分片缓冲
		    if(!packet.clusterIM.faceResolved && isFragment(packet.clusterIM)) {
		        addFragment(packet.clusterIM);
		        if(isMessageComplete(packet.clusterIM.messageId)) {
		            packet.clusterIM = getIntegratedClusterIM(packet.clusterIM.messageId);
		        } else {
		            return;
		        }
		    } 
		    
		    // 检查消息里面是否有自定义表情,如果是,提交给自定义表情接收器,返回
		    if(!packet.clusterIM.faceResolved) {
		        if(packet.clusterIM.message == null)
		            packet.clusterIM.message = convertBytes(packet.clusterIM.messageBytes);			    
		        if(packet.clusterIM.message.indexOf(IRichContent.CUSTOM_FACE_TAG) != -1) {		            
		            main.getFaceReceiver().addClusterIM(packet);
		            return;
		        } 
		    }
		    
			// 检查versionId,如果不符合,更新群信息
			if(c.isClusterDirty(packet.clusterIM.versionId)) {
			    c.setVersionId(packet.clusterIM.versionId);
			    if(c.isPermanent())
			        main.getClient().getClusterInfo(clusterId);
			    else
			        main.getClient().getTempClusterInfo(c.getType(), clusterId, c.getParentClusterId());
			}
			// 保存到聊天记录
		    main.getMessageManager().saveMessage(clusterId, clusterId, packet.clusterIM.sender, packet.clusterIM.message, (int)(packet.clusterIM.sendTime / 1000L));
			// 得到群组的索引和这个群组的view part
			int cgIndex = main.getMVCHelper().getFirstClusterGroup();
			CoolButton tab = main.getShutter().getTabControl(cgIndex);
			// 如果这个群的聊天窗口当前处于打开状态,则把消息直接推入,但是也是有一个例外
			// 就是用户设置了阻止该群的一切消息时。
		    // 如果这个群的聊天窗口没有打开,则要根据用户的设置来判断动作
			if(shellRegistry.hasSendClusterIMWindow(c)) {
				if(!IQQNode.VALUE_BLOCK.equals(messageOption)) {
					// 得到发送消息窗口实例
				    SendClusterIMWindow scms = shellRegistry.getSendClusterIMWindow(c);
					// 把这条消息推入窗口中
					scms.appendMessage(c, packet.clusterIM, false);			    
					// 如果窗口不是active的,闪烁图标并播放声音提醒用户
					// 目前禁止声音提示,有些用户觉得群窗口打开时播放声音太烦
					if(!scms.isActive()) {
					    scms.startBlinkImage();						    
						//soundDaemon.play(LumaQQ.MSG_SOUND);
					}
				}
			} else {
				if(IQQNode.VALUE_ACCEPT.equals(messageOption)) {
					// 检查这是否是第一个消息,如果是,则需要闪烁tray icon,同时还要
					// 在tab上闪烁图标,还要在群上跳动一个图标,如果不是,则
					// 不需要闪动tray icon,但是其他两个还是要的。如果当前群有
				    // 消息未读,则不播放提示声音
					CoolButton viewPart = main.getMVCHelper().getClusterViewPart(clusterId);
					if(!mq.hasNext())
					    main.getUIHelper().startBlinkImage(icons.getSmallClusterHead(c.getFaceId()));
					if(!tab.isBlinking())
						tab.startBlinkImage(c.getImage());
					if(!viewPart.isBouncing()) {
						viewPart.startBounceImage(c.getImage());
						// 播放消息提示声音
						soundDaemon.play(LumaQQ.MSG_SOUND);						    
					}
					// 推入队列
					mq.putMessage(packet, tab);
				} else if(IQQNode.VALUE_EJECT.equals(messageOption)) {
					// 推入队列
					mq.putMessage(packet, tab);
					// 弹出窗口
					main.getShellLauncher().openClusterIMWindow(c);
					// 播放消息提示声音
					soundDaemon.play(LumaQQ.MSG_SOUND);
				} else if(IQQNode.VALUE_SHOW_NUMBER.equals(messageOption)) {
					// 推入队列
					mq.putMessage(packet, tab, false);
				}
				
				// 消息数增1
			    c.increaseMessageCount();
			}
		} else {
			log.debug("好友列表未完全得到,延迟处理该群消息");
			mq.postponeMessage(packet);
		}
	}

    /**
	 * 推入一个系统消息并更新动画,这个比较简单,如果系统消息按钮没有闪烁就闪烁它
	 * 如果这是第一个消息,则tray icon也要闪烁,其他没什么要判断的了
	 * 
	 * @param packet
	 * 			系统通知包
	 */
	public void putSystemNotificationAndUpdateAnimate(SystemNotificationPacket packet) {
		// 保存到聊天记录,系统通知一概做为10000的QQ号存入,其中消息部分有些特殊
		//     分成两个域,第一个是消息类型字节,第二个是消息内容,用|分隔,这只
		//     是个权宜之计,因为我匆匆定义的聊天记录格式比较土
		StringBuffer sb = new StringBuffer();
		String qq = String.valueOf(packet.from);
		sb.append((int)packet.type);
		sb.append('|');
		if(packet.type == QQ.QQ_MSG_SYS_BEING_ADDED) 
			sb.append(LumaQQ.getString("receive.system.message.addme", new Object[] { qq }));
		else if(packet.type == QQ.QQ_MSG_SYS_ADD_FRIEND_REQUEST)
			sb.append(LumaQQ.getString("receive.system.message.request", new Object[] { qq, packet.message }));
		else if(packet.type == QQ.QQ_MSG_SYS_ADD_FRIEND_APPROVED) 
			sb.append(LumaQQ.getString("receive.system.message.approved", new Object[] { qq }));
		else if(packet.type == QQ.QQ_MSG_SYS_ADD_FRIEND_REJECTED) 
			sb.append(LumaQQ.getString("receive.system.message.rejected", new Object[] { qq, packet.message }));
		main.getMessageManager().saveMessage(10000, packet.from, packet.from, sb.toString(), (int)(System.currentTimeMillis() / 1000));
		// 调整动画状态
		if(!main.getMessageQueue().hasNext())
		    main.getUIHelper().startBlinkImage(icons.getImage(IconHolder.icoSysMsg));
		if(!main.isSystemMessageIconBlinking())
			main.startBlinkSystemMessageIcon();
		
		main.getMessageQueue().putSystemMessage(packet);
		// 播放声音
		main.getSoundDaemon().play(LumaQQ.SYS_MSG_SOUND);
		log.debug("一个系统消息被推入队列");
	}
	
    /**
     * 把一个短信推入消息队列
     * 
     * @param packet
     * 		短消息包
     */
    public void putSMS(ReceiveIMPacket packet) {
		// 保存到聊天记录中
		main.getMessageManager().saveMessage(packet.header.sender, packet.header.sender, packet.header.sender, packet.sms.message, (int)(System.currentTimeMillis() / 1000));
		// 得到好友在model中的位置,但是有可能为null,因为也许这是用户的第一次登陆
		//     其好友列表还没得到,但是这时候有消息来了,所有也无法闪烁图标了,对于
		//     这种情况,需要特殊处理一下,基本的方法是把消息推入延迟处理队列
		int[] indices = main.getMVCHelper().getFriendCoordinate(packet.header.sender);
		if((indices == null || indices.length == 0) && !main.isFriendListFinished()) {
			main.getMessageQueue().postponeMessage(packet);
			log.debug("发来短信的好友还未出现在好友列表中,延迟处理该短信");
			return;
		} else {
			// 检查这是否是第一个消息,如果是,则需要闪烁tray icon
			// 同时检查是否第一条短信,如果是,需要闪烁按钮
			if(!main.getMessageQueue().hasNext())
			    main.getUIHelper().startBlinkImage(icons.getImage(IconHolder.icoMobile));
			if(!main.isSMSIconBlinking())
			    main.startBlinkSMSIcon();
			
			// 播放声音
			main.getSoundDaemon().play(LumaQQ.MSG_SOUND);
			
			// 推入队列
			main.getMessageQueue().putSMS(packet);
			log.debug("新的手机短信被推入队列");
			// 检查是否短消息接收窗口已经被打开,如果是,使下一条按钮使能
			if(main.getShellRegistry().isReceiveSMSShellOpened()) 
			    main.getShellRegistry().getReceiveSMSShell().setNextButtonEnabled(true);
		}
    }
	
	/**
	 * 把对方的文件传输请求推入到发送消息窗口中
	 * 
	 * @param packet
	 * 		ReceiveIMPacket对象
	 */
	public void putSendFileRequestIM(ReceiveIMPacket packet) {
		// 得到发送窗口的实例,如果没有就创建一个,并设置为聊天模式
		FriendModel f = main.getMVCHelper().getFriendModel(packet.normalHeader.sender);
		SendIMWindow sms = null;
		if(main.getShellRegistry().hasSendIMWindow(f)) {
			sms = main.getShellRegistry().getSendIMWindow(f);
			if(!sms.isTalkMode()) sms.setTalkMode(true);
			sms.setMinimized(false);
			sms.setActive();
		} else {
			sms = ShellFactory.createSendIMWindow(main, f);
			sms.setTalkMode(true);
		}
		// 打开窗口
		sms.open();
		// 把请求传送文件的源包传递给窗口
		sms.setRequestPacket(packet);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -