📄 qqclient.java
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.channels.UnresolvedAddressException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.tsinghua.lumaqq.qq.beans.ContactInfo;
import edu.tsinghua.lumaqq.qq.beans.FriendRemark;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.events.QQListener;
import edu.tsinghua.lumaqq.qq.packets.OutPacket;
import edu.tsinghua.lumaqq.qq.packets.Packet;
import edu.tsinghua.lumaqq.qq.packets.in.GetFriendListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetFriendOnlineReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetUserInfoReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AddFriendAuthPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AddFriendPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ChangeStatusPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterActivatePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterAuthPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterCreatePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterExitPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetMemberInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetOnlineMemberPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterJoinPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterModifyInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSearchPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSendIMPacket;
import edu.tsinghua.lumaqq.qq.packets.out.DeleteFriendPacket;
import edu.tsinghua.lumaqq.qq.packets.out.FriendRemarkOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetFriendListPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetFriendOnlinePacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetUserInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.LoginPacket;
import edu.tsinghua.lumaqq.qq.packets.out.LogoutPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ModifyInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ReceiveIMReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.RemoveSelfPacket;
import edu.tsinghua.lumaqq.qq.packets.out.RequestKeyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SearchUserPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SendIMPacket;
/**
* QQ的客户端类,这个类为用户提供一个方便的接口,比如发送消息之类的,只需要调用一个
* 方法便可以完成了
*
* @author 马若劼
*/
public class QQClient implements QQListener {
/**
* <pre>
* 执行清理任务的Runnable类
* </pre>
*
* @author 马若劼
*/
private class CleanRunnable implements Runnable {
private KeepAliveThread thread;
private IPort port;
public CleanRunnable(KeepAliveThread thread, IPort port) {
this.thread = thread;
this.port = port;
}
public void run() {
// 终止Keep Alive线程
if(thread != null)
thread.setStop(true);
// 停止接收发送线程
try {
if(port != null)
port.dispose();
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
// Log对象
private static Log log = LogFactory.getLog(QQClient.class);
// Keep Alive 线程
private KeepAliveThread kaThread;
// 登陆的服务器IP
private String loginServer;
// packet monitor
private PacketMonitor monitor;
// 包处理类
private PacketProcessor pp;
// 保存QQ事件监听器的List
private List qqListeners;
// QQ用户
private QQUser user;
// 是否在登陆后自动请求好友列表
private boolean autoGetFriend;
// 当前是否正在登陆
private boolean logging;
// 当前是否在重定向登录
private boolean loginRedirect;
// port接口
private IPort port;
// 代理类型
private int proxyType;
// 代理服务器地址
private InetSocketAddress proxyAddress;
// 代理服务器验证用户名,null表示不需要验证
private String proxyUsername;
// 代理服务器验证密码
private String proxyPassword;
/**
* 构造函数
*/
public QQClient() {
pp = new PacketProcessor(this);
qqListeners = new ArrayList();
monitor = PacketMonitor.getInstance();
autoGetFriend = true;
logging = false;
loginRedirect = false;
}
/**
* 设置代理类型
* @param type
*/
public void setProxyType(String type) {
if(type.equalsIgnoreCase("None"))
proxyType = QQ.PROXY_NONE;
else if(type.equalsIgnoreCase("Socks5"))
proxyType = QQ.PROXY_SOCKS5;
else if(type.equalsIgnoreCase("Http"))
proxyType = QQ.PROXY_HTTP;
else
proxyType = QQ.PROXY_NONE;
}
/**
* 设置代理服务器地址
* @param proxyAddress
*/
public void setProxy(InetSocketAddress proxyAddress) {
this.proxyAddress = proxyAddress;
}
/**
* 上传好友备注信息
* @param qqNum 好友的QQ号
* @param remark 备注类
*/
public void uploadFriendRemark(int qqNum, FriendRemark remark) {
if(user.isLoggedIn()) {
FriendRemarkOpPacket packet = new FriendRemarkOpPacket();
packet.setRemark(remark);
packet.setQQ(qqNum);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 下载好友备注信息
* @param qqNum 好友的QQ号
*/
public void downloadFriendRemark(int qqNum) {
if(user.isLoggedIn()) {
FriendRemarkOpPacket packet = new FriendRemarkOpPacket();
packet.setType(QQ.QQ_DOWNLOAD_FRIEND_REMARK);
packet.setQQ(qqNum);
port.add(packet);
}
}
/**
* 搜索所有的在线用户
* @param page 页号,从0开始
*/
public void searchUser(int page) {
if(user.isLoggedIn()) {
SearchUserPacket packet = new SearchUserPacket();
packet.setPage(page);
port.add(packet);
}
}
/**
* 自定义搜索用户
* @param page 页号
* @param qqNum 要搜索的QQ号字符串形式
* @param nick 要搜索的昵称
* @param email 要搜索的email
* @param matchEntire 字符串是否完全匹配
*/
public void searchUser(int page, String qqStr, String nick, String email, boolean matchEntire) {
if(user.isLoggedIn()) {
SearchUserPacket packet = new SearchUserPacket();
packet.setSearchType(QQ.QQ_SEARCH_CUSTOM);
packet.setPage(page);
packet.setQQStr(qqStr);
packet.setNick(nick);
packet.setEmail(email);
packet.setMatchEntireString(matchEntire);
port.add(packet);
}
}
/**
* 添加一个好友
* @param qqNum 要添加的人的QQ号
* @return 发送出的包的序号
*/
public int addFriend(int qqNum) {
if(user.isLoggedIn()) {
AddFriendPacket packet = new AddFriendPacket();
packet.setTo(qqNum);
monitor.putRequest(packet);
port.add(packet);
return (int)packet.getSequence();
}
return -1;
}
/**
* 删除一个好友
* @param qqNum 要删除的好友的QQ号
* @return 如果包发送成功则返回包序号,否则返回-1
*/
public int deleteFriend(int qqNum) {
if(user.isLoggedIn()) {
DeleteFriendPacket packet = new DeleteFriendPacket();
packet.setTo(qqNum);
monitor.putRequest(packet);
port.add(packet);
return (int)packet.getSequence();
}
return -1;
}
/**
* 把某人的好友列表中的自己删除
* @param qqNum 我想把我自己删除的好友的QQ号
*/
public void removeSelfFrom(int qqNum) {
if(user.isLoggedIn()) {
RemoveSelfPacket packet = new RemoveSelfPacket();
packet.setRemoveFrom(qqNum);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 如果要加的人需要认证,用这个方法发送验证请求
* @param qqNum 要加的人的QQ号
* @param message 附加的请求消息内容
*/
public void sendAddFriendAuth(int qqNum, String message) {
if(user.isLoggedIn()) {
AddFriendAuthPacket packet = new AddFriendAuthPacket();
packet.setTo(qqNum);
packet.setMessage(message);
packet.setType(QQ.QQ_MY_AUTH_REQUEST);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 发送传送文件请求包,我们把包序号用作会话序号返回
* @param filePath 文件名,不包含路径
* @param fileSize 文件大小
* @param directPort 直接端口
* @param udp true表示UDP方式
* @return 文件传输会话序号
*/
public char requestSendFile(int receiver, String filePath, int fileSize, int directPort, boolean udp) {
if(user.isLoggedIn()) {
SendIMPacket packet = new SendIMPacket();
packet.setMessageType(udp ? QQ.QQ_IM_UDP_REQUEST : QQ.QQ_IM_TCP_REQUEST);
packet.setReceiver(receiver);
packet.setFileName(filePath);
packet.setFileSize(fileSize);
packet.setDirectPort(directPort);
monitor.putRequest(packet);
port.add(packet);
return packet.getSequence();
} else
return 0;
}
/**
* 取消发送文件
* @param receiver
* @param sequence
*/
public void cancelSendFile(int receiver, char sequence) {
if(user.isLoggedIn()) {
SendIMPacket packet = new SendIMPacket();
packet.setMessageType(QQ.QQ_IM_REQUEST_CANCELED);
packet.setReceiver(receiver);
packet.setRequestSequence(sequence);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 发送同意接收文件包
* @param receiver 接收者
* @param directPort 我的直接端口
* @param sequence 会话序号
* @param udp true表示UDP方式
*/
public void acceptSendFile(int receiver, int directPort, char sequence, boolean udp) {
if(user.isLoggedIn()) {
SendIMPacket packet = new SendIMPacket();
packet.setMessageType(udp ? QQ.QQ_IM_ACCEPT_UDP_REQUEST : QQ.QQ_IM_ACCEPT_TCP_REQUEST);
packet.setReceiver(receiver);
packet.setDirectPort(directPort);
packet.setRequestSequence(sequence);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 发送拒绝接收文件包
* @param receiver 接收者
* @param sequence 会话序号
* @param udp true表示是UDP请求,false表示TCP请求
*/
public void rejectSendFile(int receiver, char sequence, boolean udp) {
if(user.isLoggedIn()) {
SendIMPacket packet = new SendIMPacket();
packet.setMessageType(udp ? QQ.QQ_IM_REJECT_UDP_REQUEST : QQ.QQ_IM_REJECT_TCP_REQUEST);
packet.setReceiver(receiver);
packet.setRequestSequence(sequence);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 发送通知端口信息包
* @param receiver
* @param directPort
* @param localIp
* @param localPort
* @param sequence
*/
public void notifyFilePort(int receiver, int directPort, byte[] localIp, int localPort, char sequence) {
if(user.isLoggedIn()) {
SendIMPacket packet = new SendIMPacket();
packet.setMessageType(QQ.QQ_IM_NOTIFY_IP);
packet.setReceiver(receiver);
packet.setRequestSequence(sequence);
packet.setDirectPort(directPort);
packet.setLocalIp(localIp);
packet.setLocalPort(localPort);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 请求对方连接我
* @param receiver
* @param directPort
* @param sequence
*/
public void pleaseConnectMe(int receiver, int directPort, char sequence) {
if(user.isLoggedIn()) {
SendIMPacket packet = new SendIMPacket();
packet.setMessageType(QQ.QQ_IM_ARE_YOU_BEHIND_FIREWALL);
packet.setReceiver(receiver);
packet.setRequestSequence(sequence);
packet.setDirectPort(directPort);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 如果我要拒绝一个人加我为好友的请求,用这个方法发送拒绝消息
* @param qqNum 请求加我的人的QQ号
* @param message 附加消息
*/
public void rejectAddMe(int qqNum, String message) {
if(user.isLoggedIn()) {
AddFriendAuthPacket packet = new AddFriendAuthPacket();
packet.setTo(qqNum);
packet.setMessage(message);
packet.setType(QQ.QQ_MY_AUTH_REJECT);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* 如果我要同意一个人加我为好友的请求,用这个方法发送同意消息
* @param qqNum 请求加我的人的QQ号
*/
public void approveAddMe(int qqNum) {
if(user.isLoggedIn()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -